diff --git a/.env.dev b/.env.dev index c4c8a0d35..d0c9a1576 100644 --- a/.env.dev +++ b/.env.dev @@ -22,4 +22,3 @@ JWT_SECRET_KEY= # For more info, see: https://nx.dev/concepts/inferred-tasks NX_ADD_PLUGINS=false -NX_NATIVE_COMMAND_RUNNER=false diff --git a/.env.example b/.env.example index 766894992..e4a935626 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ COMPOSE_PROJECT_NAME=ghostfolio # CACHE -REDIS_HOST=localhost +REDIS_HOST=redis REDIS_PORT=6379 REDIS_PASSWORD= @@ -12,5 +12,5 @@ POSTGRES_PASSWORD= # VARIOUS ACCESS_TOKEN_SALT= -DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer +DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer JWT_SECRET_KEY= diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 75e362465..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "root": true, - "ignorePatterns": ["**/*"], - "plugins": ["@nx"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "@nx/enforce-module-boundaries": [ - "warn", - { - "enforceBuildableLibDependency": true, - "allow": [], - "depConstraints": [ - { - "sourceTag": "*", - "onlyDependOnLibsWithTags": ["*"] - } - ] - } - ], - "@typescript-eslint/no-extra-semi": "error", - "no-extra-semi": "off" - } - }, - { - "files": ["*.ts", "*.tsx"], - "extends": ["plugin:@nx/typescript"] - }, - { - "files": ["*.js", "*.jsx"], - "extends": ["plugin:@nx/javascript"] - }, - { - "files": ["*.ts"], - "plugins": ["eslint-plugin-import", "@typescript-eslint"], - "extends": [ - "plugin:@typescript-eslint/recommended-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked" - ], - "rules": { - "@typescript-eslint/consistent-indexed-object-style": "off", - "@typescript-eslint/dot-notation": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "off", - { - "accessibility": "explicit" - } - ], - "@typescript-eslint/member-ordering": "warn", - "@typescript-eslint/naming-convention": [ - "off", - { - "selector": "default", - "format": ["camelCase"], - "leadingUnderscore": "allow", - "trailingUnderscore": "allow" - }, - { - "selector": ["variable", "classProperty", "typeProperty"], - "format": ["camelCase", "UPPER_CASE"], - "leadingUnderscore": "allow", - "trailingUnderscore": "allow" - }, - { - "selector": "objectLiteralProperty", - "format": null - }, - { - "selector": "enumMember", - "format": ["camelCase", "UPPER_CASE", "PascalCase"] - }, - { - "selector": "typeLike", - "format": ["PascalCase"] - } - ], - "@typescript-eslint/no-empty-interface": "warn", - "@typescript-eslint/no-inferrable-types": [ - "warn", - { - "ignoreParameters": true - } - ], - "@typescript-eslint/no-non-null-assertion": "warn", - "@typescript-eslint/no-shadow": [ - "warn", - { - "hoist": "all" - } - ], - "@typescript-eslint/unified-signatures": "error", - "@typescript-eslint/no-loss-of-precision": "warn", - "@typescript-eslint/no-var-requires": "warn", - "@typescript-eslint/ban-types": "warn", - "arrow-body-style": "off", - "constructor-super": "error", - "eqeqeq": ["error", "smart"], - "guard-for-in": "warn", - "id-blacklist": "off", - "id-match": "off", - "import/no-deprecated": "warn", - "no-bitwise": "error", - "no-caller": "error", - "no-debugger": "error", - "no-empty": "off", - "no-eval": "error", - "no-fallthrough": "error", - "no-new-wrappers": "error", - "no-restricted-imports": ["error", "rxjs/Rx"], - "no-undef-init": "error", - "no-underscore-dangle": "off", - "no-var": "error", - "radix": "error", - "no-unsafe-optional-chaining": "warn", - "no-extra-boolean-cast": "warn", - "no-empty-pattern": "warn", - "no-useless-catch": "warn", - "no-unsafe-finally": "warn", - "no-prototype-builtins": "warn", - "no-async-promise-executor": "warn", - "no-constant-condition": "warn", - - // The following rules are part of @typescript-eslint/recommended-type-checked - // and can be remove once solved - "@typescript-eslint/await-thenable": "warn", - "@typescript-eslint/ban-ts-comment": "warn", - "@typescript-eslint/no-base-to-string": "warn", - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-floating-promises": "warn", - "@typescript-eslint/no-misused-promises": "warn", - "@typescript-eslint/no-redundant-type-constituents": "warn", - "@typescript-eslint/no-unnecessary-type-assertion": "warn", - "@typescript-eslint/no-unsafe-argument": "warn", - "@typescript-eslint/no-unsafe-assignment": "warn", - "@typescript-eslint/no-unsafe-enum-comparison": "warn", - "@typescript-eslint/no-unsafe-member-access": "warn", - "@typescript-eslint/no-unsafe-return": "warn", - "@typescript-eslint/no-unsafe-call": "warn", - "@typescript-eslint/require-await": "warn", - "@typescript-eslint/restrict-template-expressions": "warn", - "@typescript-eslint/unbound-method": "warn", - - // The following rules are part of @typescript-eslint/stylistic-type-checked - // and can be remove once solved - "@typescript-eslint/prefer-nullish-coalescing": "warn" // TODO: Requires strictNullChecks: true - } - } - ], - "extends": ["plugin:storybook/recommended"] -} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 1fabe2f48..329a9a5a3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -26,7 +26,7 @@ Thank you for your understanding and cooperation! 2. 3. -**Expected behavior** +**Expected Behavior** @@ -48,6 +48,6 @@ Thank you for your understanding and cooperation! - Browser - OS -**Additional context** +**Additional Context** diff --git a/.github/workflows/build-code.yml b/.github/workflows/build-code.yml index 18240ebc4..7a8f72ac4 100644 --- a/.github/workflows/build-code.yml +++ b/.github/workflows/build-code.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: node_version: - - 20 + - 22 steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 47943977f..6b4601733 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -19,7 +19,7 @@ jobs: id: meta uses: docker/metadata-action@v4 with: - images: ghostfolio/ghostfolio + images: ${{ vars.DOCKER_REPOSITORY || 'ghostfolio/ghostfolio' }} tags: | type=semver,pattern={{major}} type=semver,pattern={{version}} diff --git a/.github/workflows/extract-locales.yml b/.github/workflows/extract-locales.yml new file mode 100644 index 000000000..c17eac5b6 --- /dev/null +++ b/.github/workflows/extract-locales.yml @@ -0,0 +1,40 @@ +name: Extract locales + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + extract_locales: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install dependencies + run: npm ci + + - name: Extract locales + run: npm run extract-locales + + - name: Check changes + id: verify-changed-files + uses: tj-actions/verify-changed-files@v20 + + - name: Create pull request + if: steps.verify-changed-files.outputs.files_changed == 'true' + uses: peter-evans/create-pull-request@v7 + with: + author: 'github-actions[bot] ' + branch: 'feature/update-locales' + commit-message: 'Update locales' + delete-branch: true + title: 'Feature/update locales' + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index d7e5e5eb1..e753d3bf7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,10 @@ npm-debug.log # misc /.angular/cache +.cursor/rules/nx-rules.mdc .env .env.prod +.github/instructions/nx.instructions.md .nx/cache .nx/workspace-data /.sass-cache diff --git a/.nvmrc b/.nvmrc index 9a2a0e219..53d1c14db 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 +v22 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c285cb13..beb21afed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,1054 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added a _Storybook_ story for the membership card component + +### Changed + +- Moved the support for changing the asset profile identifier (`dataSource` and `symbol`) in the asset profile details dialog of the admin control panel from experimental to general availability +- Improved the balance of headings on the landing page +- Improved the language localization for Spanish (`es`) +- Upgraded `angular` from version `20.0.7` to `20.1.3` +- Upgraded `Nx` from version `21.2.4` to `21.3.9` + +## 2.186.0 - 2025-07-30 + +### Added + +- Added the allocation column to the accounts table component of the holding detail dialog + +### Changed + +- Improved the _Top 3_ and _Bottom 3_ performers on the analysis page by removing items without performance +- Improved the usability of the toggle component +- Simplified the users table of the admin control panel +- Restructured the response of the portfolio report endpoint (_X-ray_) +- Refreshed the cryptocurrencies list +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Chinese (`zh`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for German (`de`) +- Improved the language localization for Spanish (`es`) +- Upgraded `ng-extract-i18n-merge` from version `2.15.1` to `3.0.0` + +### Fixed + +- Fixed the links of the _Top 3_ and _Bottom 3_ performers on the analysis page +- Excluded the holdings originated of `FEE`, `INTEREST` and `LIABILITY` activities from the closed holdings on the portfolio holdings page +- Fixed an issue with serving _Storybook_ related to missing styles + +## 2.185.0 - 2025-07-26 + +### Added + +- Added a _Storybook_ story for the activity type component +- Added a _Storybook_ story for the toggle component + +### Changed + +- Extended the import functionality by custom asset profiles +- Migrated the get country and sector weightings, dividends, ETF holdings, ETF info, historical price, profile, quote and symbol search functionalities of the _Financial Modeling Prep_ service to its stable API version +- Refactored the toggle component to standalone +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Turkish (`tr`) +- Upgraded the _Stripe_ dependencies +- Upgraded `angular` from version `19.2.1` to `20.0.7` +- Upgraded `ngx-device-detector` from version `9.0.0` to `10.0.2` +- Upgraded `ngx-markdown` from version `19.0.0` to `20.0.0` +- Upgraded `ngx-stripe` from version `19.7.0` to `20.7.0` +- Upgraded `Nx` from version `21.1.2` to `21.2.4` +- Upgraded `storybook` from version `8.6.12` to `9.0.17` + +### Fixed + +- Fixed the date format of the retirement date in the _FIRE_ calculator +- Fixed an issue with the permissions of the impersonation mode related to the onboarding on the overview tab of the home page +- Fixed an issue with the permissions of the impersonation mode related to the manage activities button of the holdings tab on the home page +- Fixed an issue with the currency detection related to `USD.AX` in the _Yahoo Finance_ service + +## 2.184.0 - 2025-07-22 + +### Added + +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Asia-Pacific) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Emerging Markets) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Europe) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (Japan) +- Set up the language localization for the static portfolio analysis rule: _Regional Market Cluster Risks_ (North America) + +### Changed + +- Localized the tooltips of the about page +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for German (`de`) +- Improved the language localization for Spanish (`es`) +- Upgraded `countries-and-timezones` from version `3.7.2` to `3.8.0` +- Upgraded `prisma` from version `6.11.1` to `6.12.0` + +### Fixed + +- Fixed an issue with the landing page related to the public page routes of the `AuthGuard` + +## 2.183.0 - 2025-07-20 + +### Added + +- Set up the language localization for the static portfolio analysis rule: _Economic Market Cluster Risks_ (Developed Markets) +- Set up the language localization for the static portfolio analysis rule: _Economic Market Cluster Risks_ (Emerging Markets) + +### Changed + +- Extended the export functionality by custom asset profiles +- Improved the platform icon in the create or update platform dialog of the admin control +- Localized the durations of the coupon system +- Refactored the admin pages to standalone +- Refactored the Frequently Asked Questions (FAQ) pages to standalone +- Refactored the home pages to standalone +- Refactored the resources pages to standalone +- Refactored the access table component to standalone +- Refactored the accounts table component to standalone +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for German (`de`) +- Improved the language localization for Italian (`it`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Spanish (`es`) + +### Fixed + +- Fixed the horizontal ellipsis icon in the accounts table component +- Fixed the quantity value in the update activity dialog +- Fixed the static portfolio analysis rule for no accounts: _Account Cluster Risks_ (Current Investment) +- Fixed the static portfolio analysis rule for no accounts: _Account Cluster Risks_ (Single Account) + +## 2.182.0 - 2025-07-16 + +### Added + +- Added a message to the assistant if no results have been found +- Added the category title to the settings dialog to customize the rule thresholds of the _X-ray_ page (experimental) + +### Changed + +- Improved the label for asset profiles with `MANUAL` data source in the chart of the asset profile details dialog in the admin control panel +- Improved the label for asset profiles with `MANUAL` data source in the chart of the holding detail dialog +- Skipped errors for the custom asset profiles in the portfolio snapshot calculation +- Removed the date range query parameter from the search for the holdings in the assistant +- Improved the language localization for Chinese (`zh`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Spanish (`es`) + +### Fixed + +- Fixed an issue with the clone functionality related to a custom asset profile activity + +## 2.181.0 - 2025-07-11 + +### Changed + +- Improved the portfolio calculations for activities without historical market data +- Improved the asset profile dialog’s asset sub class selector of the admin control panel to update the options dynamically based on the selected asset class +- Improved the asset profile dialog’s data gathering checkbox of the admin control panel to reflect the global settings +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Chinese (`zh`) +- Improved the language localization for German (`de`) +- Improved the language localization for Italian (`it`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Spanish (`es`) +- Improved the language localization for Turkish (`tr`) + +### Fixed + +- Fixed an issue in the biometric authentication related to matching passkeys + +## 2.180.0 - 2025-07-08 + +### Added + +- Added alternative investment as an asset class +- Added collectible as an asset sub class + +### Changed + +- Respected the filter by account for accounts when exporting activities on the portfolio activities page +- Improved the label for asset profiles with `MANUAL` data source in the chart of the holdings tab on the home page +- Renamed `AccessGive` to `accessesGive` in the `User` database schema +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for German (`de`) +- Improved the language localization for Spanish (`es`) + +### Fixed + +- Fixed the export functionality for accounts without activities + +## 2.179.0 - 2025-07-07 + +### Added + +- Added a _Manage Asset Profile_ button for administrators to the holding detail dialog + +### Changed + +- Improved the language localization in the users table of the admin control panel +- Refactored the accounts pages to standalone +- Refactored the portfolio pages to standalone +- Refactored the user account pages to standalone +- Renamed `Settings` to `settings` in the `User` database schema +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for Español (`es`) +- Improved the language localization for German (`de`) +- Upgraded `ionicons` from version `7.4.0` to `8.0.10` + +### Fixed + +- Fixed the allocations by asset class for unknown asset classes on the allocations page + +## 2.178.0 - 2025-07-05 + +### Changed + +- Increased the width of the markets overview +- Increased the width of the watchlist +- Deprecated the `ITEM` activity type in favor of `BUY` +- Renamed `Access` to `accessesGet` in the `User` database schema +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for Italian (`it`) +- Upgraded `prisma` from version `6.10.1` to `6.11.1` + +### Fixed + +- Set the name column to sticky in the table of the benchmark component + +## 2.177.0 - 2025-07-03 + +### Added + +- Extended the _Fear & Greed Index_ (market mood) in the markets overview by cryptocurrencies (experimental) + +### Changed + +- Refactored the about pages to standalone +- Made the `getByKey()` function generic in the property service +- Renamed `AuthDevice` to `authDevices` in the `User` database schema +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for German (`de`) +- Improved the language localization for Portuguese (`pt`) +- Upgraded `@internationalized/number` from version `3.6.0` to `3.6.3` +- Upgraded `ngx-skeleton-loader` from version `11.0.0` to `11.2.1` +- Upgraded `yahoo-finance2` from version `3.3.5` to `3.4.1` + +## 2.176.0 - 2025-06-30 + +### Added + +- Added support for generating a new _Security Token_ via the user’s account access panel + +### Changed + +- Moved the main content of the holding detail dialog to a new overview tab +- Introduced fuzzy search for the holdings of the assistant +- Introduced fuzzy search for the quick links of the assistant +- Improved the search results of the assistant to only display categories with content +- Enhanced the sitemap to dynamically compose public routes +- Renamed `Account` to `account` in the `Order` database schema +- Improved the language localization for German (`de`) +- Upgraded `prettier` from version `3.5.3` to `3.6.2` + +## 2.175.0 - 2025-06-28 + +### Added + +- Set up the language localization for the static portfolio analysis rule: _Asset Class Cluster Risks_ (Equity) +- Set up the language localization for the static portfolio analysis rule: _Asset Class Cluster Risks_ (Fixed Income) +- Set up the language localization for the static portfolio analysis rule: _Currency Cluster Risks_ (Investment) +- Set up the language localization for the static portfolio analysis rule: _Currency Cluster Risks_ (Investment: Base Currency) + +### Changed + +- Extended the selector handling of the scraper configuration for more use cases +- Extended the _AI_ service by an access to _OpenRouter_ (experimental) +- Changed `node main` to `exec node main` in the `entrypoint.sh` file to improve the container signal handling +- Renamed `Account` to `account` in the `AccountBalance` database schema +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for Español (`es`) +- Improved the language localization for German (`de`) +- Improved the language localization for Turkish (`tr`) + +### Fixed + +- Fixed an issue with the locale in the scraper configuration + +## 2.174.0 - 2025-06-24 + +### Added + +- Set up the language localization for the static portfolio analysis rule: _Account Cluster Risks_ (Current Investment) +- Extended the data providers management of the admin control panel by the online status + +### Changed + +- Migrated the `@ghostfolio/ui/value` component to control flow +- Renamed `Platform` to `platform` in the `Account` database schema +- Refactored the health check endpoint for data enhancers +- Refactored the health check endpoint for data providers +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Refreshed the cryptocurrencies list + +## 2.173.0 - 2025-06-21 + +### Added + +- Set up `open-color` for CSS variable usage + +### Changed + +- Simplified the data providers management of the admin control panel +- Migrated the `@ghostfolio/ui/assistant` component to control flow +- Migrated the `@ghostfolio/ui/value` component to control flow +- Renamed `GranteeUser` to `granteeUser` in the `Access` database schema +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Upgraded `class-validator` from version `0.14.1` to `0.14.2` +- Upgraded `prisma` from version `6.9.0` to `6.10.1` + +### Fixed + +- Fixed an issue in the `HtmlTemplateMiddleware` related to incorrect variable resolution +- Eliminated the _Unsupported route path_ warning of the `LegacyRouteConverter` on startup + +## 2.172.0 - 2025-06-19 + +### Added + +- Set up the language localization for the static portfolio analysis rule: _Account Cluster Risks_ (Single Account) +- Included the admin control panel in the quick links of the assistant + +### Changed + +- Adapted the options of the date range selector in the assistant dynamically based on the user’s first activity +- Switched the data provider service to `OnModuleInit`, ensuring (currency) quotes are fetched only once +- Migrated the `@ghostfolio/ui/assistant` component to control flow +- Migrated the `@ghostfolio/ui/value` component to control flow +- Improved the language localization for Chinese (`zh`) +- Improved the language localization for Español (`es`) +- Improved the language localization for German (`de`) +- Improved the language localization for Portuguese (`pt`) + +## 2.171.0 - 2025-06-15 + +### Added + +- Added the current holdings as default options of the symbol search in the create or update activity dialog + +### Changed + +- Improved the style of the assistant +- Reused the value component in the data providers management of the admin control panel +- Set the market state of exchange rate symbols to `open` in the _Financial Modeling Prep_ service +- Restructured the content of the pricing page +- Migrated the `@ghostfolio/ui/assistant` component to control flow +- Migrated the `@ghostfolio/ui/value` component to control flow +- Migrated the `HtmlTemplateMiddleware` to use `@Injectable()` +- Renamed `User` to `user` in the database schema +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Español (`es`) +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Improved the language localization for Italian (`it`) +- Improved the language localization for Polish (`pl`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Turkish (`tr`) +- Upgraded the _Stripe_ dependencies + +### Fixed + +- Fixed a date offset issue with account balances +- Fixed missing `/.well-known/assetlinks.json` for TWA + +## 2.170.0 - 2025-06-11 + +### Added + +- Included quick links in the search results of the assistant +- Added a skeleton loader to the changelog page +- Extended the content of the _Self-Hosting_ section by information about additional data providers on the Frequently Asked Questions (FAQ) page + +### Changed + +- Renamed `ApiKey` to `apiKeys` in the `User` database schema +- Improved the language localization for French (`fr`) +- Improved the language localization for Portuguese (`pt`) +- Upgraded `@keyv/redis` from version `4.3.4` to `4.4.0` +- Upgraded `prisma` from version `6.8.2` to `6.9.0` +- Upgraded `zone.js` from version `0.15.0` to `0.15.1` + +### Fixed + +- Restricted the date range change permission in the _Zen Mode_ + +## 2.169.0 - 2025-06-08 + +### Changed + +- Renamed the asset profile icon component to entity logo component and moved to `@ghostfolio/ui` +- Renamed `Account` to `accounts` in the `User` database schema +- Improved the cache verification in the health check endpoint (experimental) +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for French (`fr`) +- Improved the language localization for Polish (`pl`) + +### Fixed + +- Handled an exception in the get keys function of the _Redis_ cache service +- Fixed missing `/.well-known/assetlinks.json` for TWA + +## 2.168.0 - 2025-06-07 + +### Added + +- Added a background gradient to the sidebar navigation + +### Changed + +- Migrated the `i18n` service to use `@Injectable()` +- Improved the language localization for German (`de`) +- Upgraded `nestjs` from version `11.1.0` to `11.1.3` + +## 2.167.0 - 2025-06-07 + +### Added + +- Added support for column sorting to the markets overview +- Added support for column sorting to the watchlist +- Set up the language localization for the static portfolio analysis rule: _Emergency Fund_ (Setup) +- Set up the language localization for the static portfolio analysis rule: _Fees_ (Fee Ratio) + +### Changed + +- Extended the symbol search component by default options +- Renamed `Tag` to `tags` in the `User` database schema +- Improved the language localization for German (`de`) +- Improved the language localization for Spanish (`es`) +- Improved the language localization for Turkish (`tr`) +- Upgraded `ng-extract-i18n-merge` from version `2.15.0` to `2.15.1` +- Upgraded `Nx` from version `20.8.1` to `21.1.2` + +### Fixed + +- Fixed an issue where the import button was not correctly enabled in the import activities dialog +- Fixed an issue with empty account balances in the import activities dialog +- Fixed an issue in the annualized performance calculation + +## 2.166.0 - 2025-06-05 + +### Added + +- Added support to create custom tags in the create or update activity dialog (experimental) + +### Changed + +- Improved the style of the card components +- Improved the style of the system message +- Improved the language localization for German (`de`) +- Improved the language localization for Spanish (`es`) +- Improved the language localization for Turkish (`tr`) +- Improved the language localization for Ukrainian (`uk`) +- Upgraded the _Stripe_ dependencies +- Upgraded `ngx-stripe` from version `19.0.0` to `19.7.0` + +### Fixed + +- Respected the filter by holding when deleting activities on the portfolio activities page +- Respected the filter by holding when exporting activities on the portfolio activities page +- Fixed an exception with currencies in the historical market data editor of the admin control panel + +## 2.165.0 - 2025-05-31 + +### Added + +- Extended the content of the _General_ section by the performance calculation method on the Frequently Asked Questions (FAQ) page + +### Changed + +- Improved the _Live Demo_ setup by syncing activities based on tags +- Renamed `orders` to `activities` in the `Tag` database schema +- Modularized the cron service +- Refreshed the cryptocurrencies list +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for Polish (`pl`) +- Improved the language localization for Spanish (`es`) +- Upgraded `big.js` from version `6.2.2` to `7.0.1` +- Upgraded `ng-extract-i18n-merge` from version `2.14.3` to `2.15.0` + +### Fixed + +- Changed the investment value to take the currency effects into account in the holding detail dialog + +## 2.164.0 - 2025-05-28 + +### Changed + +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for French (`fr`) +- Improved the language localization for Polish (`pl`) +- Improved the language localization for Spanish (`es`) +- Upgraded `Node.js` from version `20` to `22` (`Dockerfile`) +- Upgraded `yahoo-finance2` from version `3.3.4` to `3.3.5` + +## 2.163.0 - 2025-05-26 + +### Changed + +- Improved the language localization for Italian (`it`) +- Improved the language localization for Turkish (`tr`) +- Upgraded `yahoo-finance2` from version `3.3.3` to `3.3.4` + +## 2.162.1 - 2025-05-24 + +### Added + +- Added a hint about delayed market data to the markets overview +- Added the asset profile count per data provider to the endpoint `GET api/v1/admin` + +### Changed + +- Increased the robustness of the search in the _Yahoo Finance_ service by catching schema validation errors +- Improved the symbol lookup results by removing the currency from the name of cryptocurrencies (experimental) +- Harmonized the data providers management style of the admin control panel +- Extended the data providers management of the admin control panel by the asset profile count +- Restricted the permissions of the demo user +- Renamed `Order` to `activities` in the `User` database schema +- Removed the deprecated endpoint `GET api/v1/admin/market-data/:dataSource/:symbol` +- Removed the deprecated endpoint `POST api/v1/admin/market-data/:dataSource/:symbol` +- Removed the deprecated endpoint `PUT api/v1/admin/market-data/:dataSource/:symbol/:dateString` +- Improved the language localization for Catalan (`ca`) +- Improved the language localization for Chinese (`zh`) +- Improved the language localization for Dutch (`nl`) +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Improved the language localization for Italian (`it`) +- Improved the language localization for Polish (`pl`) +- Improved the language localization for Portuguese (`pt`) +- Improved the language localization for Spanish (`es`) +- Upgraded `countup.js` from version `2.8.0` to `2.8.2` +- Upgraded `nestjs` from version `10.4.15` to `11.0.12` +- Upgraded `prisma` from version `6.7.0` to `6.8.2` +- Upgraded `twitter-api-v2` from version `1.14.2` to `1.23.0` +- Upgraded `yahoo-finance2` from version `2.11.3` to `3.3.3` + +### Fixed + +- Displayed the button to fetch the current market price only if the activity is not in a custom currency +- Fixed an issue in the watchlist endpoint (`POST`) related to the `HasPermissionGuard` +- Improved the text alignment of the allocations by ETF holding on the allocations page (experimental) + +## 2.161.0 - 2025-05-06 + +### Added + +- Extended the endpoint to get a holding by the date of the last all time high and the current change to the all time high + +### Changed + +- Renamed `Order` to `activities` in the `SymbolProfile` database schema +- Improved the language localization for Turkish (`tr`) + +### Fixed + +- Fixed an issue in the performance calculation on the date of an activity when the unit price differs from the market price +- Fixed the horizontal overflow in the table of the benchmark component + +## 2.160.0 - 2025-05-04 + +### Added + +- Added the watchlist to the features page +- Extended the content of the Frequently Asked Questions (FAQ) pages + +### Changed + +- Moved the watchlist from experimental to general availability +- Deprecated the endpoint to get a portfolio position in favor of get a holding +- Deprecated the endpoint to update portfolio position tags in favor of update holding tags +- Renamed `Account` to `accounts` in the `Platform` database schema +- Upgraded `prisma` from version `6.6.0` to `6.7.0` + +### Fixed + +- Fixed an issue with the fee calculations related to activities in a custom currency + +## 2.159.0 - 2025-05-02 + +### Added + +- Extended the watchlist by the date of the last all time high, the current change to the all time high and the current market condition (experimental) +- Added support for the impersonation mode in the watchlist (experimental) + +### Changed + +- Improved the language localization for French (`fr`) +- Upgraded `bootstrap` from version `4.6.0` to `4.6.2` + +### Fixed + +- Fixed the currency code validation by allowing `GBp` + +## 2.158.0 - 2025-04-30 + +### Added + +- Added support to delete an asset from the watchlist (experimental) + +### Changed + +- Renamed `Order` to `activities` in the `Account` database schema +- Improved the language localization for German (`de`) + +### Fixed + +- Fixed an issue with the saving of activities with type `INTEREST`, `ITEM` and `LIABILITY` + +## 2.157.1 - 2025-04-29 + +### Added + +- Introduced a watchlist to follow assets (experimental) + +### Changed + +- Changed the column label from _Index_ to _Name_ in the benchmark component +- Extended the data providers management of the admin control panel +- Improved the language localization for German (`de`) + +## 2.156.0 - 2025-04-27 + +### Changed + +- Improved the error message of the currency code validation +- Tightened the currency code validation by requiring uppercase letters +- Respected the watcher count for the delete asset profiles checkbox in the historical market data table of the admin control panel +- Improved the language localization for French (`fr`) +- Upgraded `ngx-skeleton-loader` from version `10.0.0` to `11.0.0` +- Upgraded `Nx` from version `20.8.0` to `20.8.1` + +### Fixed + +- Fixed an issue with the investment calculation for activities in a custom currency +- Improved the file selector of the activities import functionality to accept case-insensitive file extensions (`.CSV` and `.JSON`) +- Fixed the missing localization for "someone" on the public page + +## 2.155.0 - 2025-04-23 + +### Added + +- Added the endpoints (`DELETE`, `GET` and `POST`) for the watchlist + +### Changed + +- Simplified the data source check in the DTO of the activity creation +- Simplified the data source check in the DTO of the asset profile update +- Renamed `User` to `user` in the `Subscription` database schema +- Migrated the `@ghostfolio/ui/assistant` component to control flow +- Migrated the `@ghostfolio/ui/value` component to control flow + +### Fixed + +- Fixed an issue in the settings dialog to customize the rule thresholds of the _X-ray_ page (experimental) + +## 2.154.0 - 2025-04-21 + +### Added + +- Extended the benchmark detail dialog by the current market price +- Added the performance calculation type to the user settings (experimental) +- Added `watchlist` to the `User` database schema as a preparation for watching assets + +### Changed + +- Made the historical market data editor expandable in the admin control panel +- Renamed `Subscription` to `subscriptions` in the `User` database schema +- Parallelized the requests in the get quotes functionality of the _Financial Modeling Prep_ service +- Migrated the lookup functionality by `isin` of the _Financial Modeling Prep_ service to its stable API version +- Improved the language localization for German (`de`) + +### Fixed + +- Fixed the word wrap in the menu of the historical market data table in the admin control panel + +## 2.153.0 - 2025-04-18 + +### Changed + +- Added support for activities in a custom currency +- Refreshed the cryptocurrencies list +- Upgraded `chart.js` from version `4.4.7` to `4.4.9` +- Upgraded `uuid` from version `11.0.5` to `11.1.0` + +### Fixed + +- Fixed the functionality to open an asset profile of a custom currency in the admin control panel +- Fixed the asset class parsing in the _Financial Modeling Prep_ service for exchange rates + +## 2.152.1 - 2025-04-17 + +### Changed + +- Deactivated asset profiles automatically on delisting in the _Yahoo Finance_ service +- Optimized the query of the data range functionality (`getRange()`) in the market data service +- Moved the subscription offer from the info to the user service +- Upgraded `Nx` from version `20.7.1` to `20.8.0` +- Upgraded `prisma` from version `6.5.0` to `6.6.0` +- Upgraded `storybook` from version `8.4.7` to `8.6.12` + +## 2.151.0 - 2025-04-11 + +### Added + +- Added the data gathering status column to the historical market data table of the admin control + +### Changed + +- Set the maximum number of symbols per request in the _Financial Modeling Prep_ service +- Migrated the get quotes functionality of the _Financial Modeling Prep_ service to its stable API version +- Improved the language localization for Enlish (`en`) +- Upgraded `eslint` dependencies +- Upgraded `Nx` from version `20.6.4` to `20.7.1` + +### Fixed + +- Fixed the link to the pricing page in the premium indicator component + +## 2.150.0 - 2025-04-05 + +### Added + +- Added support to toggle the data gathering for individual asset profiles in the asset profile details dialog of the admin control panel + +### Changed + +- Improved the check for duplicates in the preview step of the activities import (allow different comments) +- Improved the language localization for French (`fr`) +- Improved the language localization for German (`de`) +- Improved the language localization for Polish (`pl`) +- Upgraded `ng-extract-i18n-merge` from version `2.14.1` to `2.14.3` + +## 2.149.0 - 2025-03-30 + +### Added + +- Added support for changing the asset profile identifier (`dataSource` and `symbol`) in the asset profile details dialog of the admin control panel (experimental) +- Set up the terms of service for the _Ghostfolio_ SaaS (cloud) + +### Changed + +- Improved the static portfolio analysis rule: Emergency fund setup by supporting assets +- Restricted the historical market data gathering to active asset profiles +- Improved the language localization for German (`de`) +- Upgraded `Nx` from version `20.5.0` to `20.6.4` + +## 2.148.0 - 2025-03-24 + +### Added + +- Added the `isActive` flag to the asset profile model + +### Changed + +- Improved the language localization for German (`de`) +- Upgraded `ngx-skeleton-loader` from version `9.0.0` to `10.0.0` + +## 2.147.0 - 2025-03-22 + +### Added + +- Added support for filtering in the _Copy AI prompt to clipboard_ actions on the analysis page (experimental) +- Added support for generating a new _Security Token_ via the users table of the admin control panel +- Added an endpoint to localize the `site.webmanifest` +- Added the _Storybook_ path to the `sitemap.xml` file + +### Changed + +- Improved the export functionality by applying filters on accounts and tags +- Improved the symbol validation in the _Yahoo Finance_ service (get asset profiles) +- Eliminated `firstOrderDate` from the summary of the portfolio details endpoint in favor of using `dateOfFirstActivity` from the user endpoint +- Refactored `lodash.uniq` with `Array.from(new Set(...))` +- Refreshed the cryptocurrencies list +- Improved the language localization for German (`de`) +- Improved the language localization for Turkish (`tr`) + +### Fixed + +- Fixed an issue in the activities import functionality related to the account balances +- Changed client-side dates to be sent in UTC format to ensure date consistency + - Benchmark endpoint + - Exchange rate endpoint + +## 2.146.0 - 2025-03-15 + +### Changed + +- Improved the usability of the user account registration +- Improved the usability of the _Copy AI prompt to clipboard_ actions on the analysis page (experimental) +- Formatted the name in the _Financial Modeling Prep_ service +- Removed the exchange rates from the overview of the admin control panel +- Improved the language localization for German (`de`) +- Upgraded `angular` from version `19.0.5` to `19.2.1` +- Upgraded `Nx` from version `20.3.2` to `20.5.0` +- Upgraded `prettier` from version `3.5.1` to `3.5.3` +- Upgraded `prisma` from version `6.4.1` to `6.5.0` + +### Fixed + +- Fixed an issue with serving _Storybook_ related to the `contentSecurityPolicy` + +## 2.145.1 - 2025-03-10 + +### Added + +- Extended the export functionality by the account balances +- Added a _Copy portfolio data to clipboard for AI prompt_ action to the analysis page (experimental) + +### Changed + +- Improved the style of the summary on the _X-ray_ page +- Improved the language localization for German (`de`) +- Upgraded `@simplewebauthn/browser` and `@simplewebauthn/server` from version `9.0` to `13.1` + +### Fixed + +- Fixed an issue to get dividends in the _Financial Modeling Prep_ service +- Fixed an issue to get historical market data in the _Financial Modeling Prep_ service +- Fixed an issue with serving _Storybook_ + +## 2.144.0 - 2025-03-06 + +### Fixed + +- Fixed the missing import functionality on the non-empty activities page +- Fixed the functionality to delete an asset profile of a custom currency in the admin control panel + +## 2.143.0 - 2025-03-02 + +### Added + +- Added the Ghostfolio _LinkedIn_ page to the about page +- Added the Ghostfolio _LinkedIn_ page to the footer + +### Changed + +- Optimized the asynchronous operations using `Promise.all()` in the portfolio service (`getPerformance`) +- Improved the symbol lookup in the _Trackinsight_ data enhancer for asset profile data +- Removed the no transactions info component from the holdings table on the home page +- Refactored the show condition of the step by step introduction for new users using the activities count +- Upgraded `color` from version `4.2.3` to `5.0.0` +- Upgraded `prisma` from version `6.3.0` to `6.4.1` + +### Fixed + +- Handled an exception in the export functionality related to platforms +- Handled an exception in the benchmark service related to unnamed asset profiles + +## 2.142.0 - 2025-02-28 + +### Added + +- Extended the export functionality by the platforms +- Extended the portfolio snapshot in the portfolio calculator by the `createdAt` timestamp +- Extended the _Trackinsight_ data enhancer for asset profile data by `cusip` +- Added _Storybook_ to the build process + +### Changed + +- Upgraded `eslint` dependencies + +## 2.141.0 - 2025-02-25 + +### Added + +- Extended the export functionality by the tags +- Extended the portfolio snapshot in the portfolio calculator by the activities count +- Extended the user endpoint `GET api/v1/user` by the activities count +- Added `cusip` to the asset profile model + +### Changed + +- Upgraded `prettier` from version `3.4.2` to `3.5.1` + +### Fixed + +- Improved the numeric comparison of strings in the value component + +## 2.140.0 - 2025-02-20 + +### Changed + +- Reloaded the available tags after creating a custom tag in the holding detail dialog (experimental) +- Improved the validation of the currency management in the admin control panel +- Migrated the `@ghostfolio/client` components to control flow +- Migrated the `@ghostfolio/ui` components to control flow +- Improved the language localization for German (`de`) + +### Fixed + +- Improved the error handling in the `HttpResponseInterceptor` +- Fixed an issue while using symbol profile overrides in the historical market data table of the admin control panel +- Added missing assets in _Storybook_ setup + +## 2.139.1 - 2025-02-15 + +### Added + +- Extended the tooltip in the chart of the holdings tab on the home page by the allocation, change and performance +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Asia-Pacific Markets) +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Japan) +- Added support to create custom tags in the holding detail dialog (experimental) +- Extended the tags selector component by a `readonly` attribute +- Extended the tags selector component to support creating custom tags +- Extended the holding detail dialog by the historical market data editor (experimental) +- Added global styles to the _Storybook_ setup + +### Changed + +- Improved the symbol lookup in the _Trackinsight_ data enhancer for asset profile data +- Improved the language localization for German (`de`) +- Upgraded `@trivago/prettier-plugin-sort-imports` from version `5.2.1` to `5.2.2` + +### Fixed + +- Fixed the gaps in the chart of the benchmark comparator + +## 2.138.0 - 2025-02-08 + +### Added + +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Emerging Markets) +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Europe) +- Added a link to _Duck.ai_ to the _Copy AI prompt to clipboard_ action on the analysis page (experimental) +- Extracted the tags selector to a reusable component used in the create or update activity dialog and holding detail dialog +- Added stories for the tags selector component + +### Changed + +- Improved the caching of the portfolio snapshot in the portfolio calculator by expiring cache entries when a user changes tags in the holding detail dialog +- Improved the error handling in the _CoinGecko_ service +- Improved the language localization for German (`de`) +- Upgraded `svgmap` from version `2.6.0` to `2.12.2` + +## 2.137.1 - 2025-02-01 + +### Added + +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (North America) +- Added support for ETF sector data in the _Yahoo Finance_ data enhancer + +### Changed + +- Extracted the scraper configuration to a sub form in the asset profile details dialog of the admin control +- Migrated the database seeding to _TypeScript_ +- Improved the language localization for German (`de`) +- Upgraded `@trivago/prettier-plugin-sort-imports` from version `4.3.0` to `5.2.1` +- Upgraded `bull` from version `4.16.4` to `4.16.5` +- Upgraded `ng-extract-i18n-merge` from version `2.13.1` to `2.14.1` +- Upgraded `prisma` from version `6.2.1` to `6.3.0` + +### Fixed + +- Fixed the dynamic numerical precision for cryptocurrencies in the holding detail dialog + +## 2.136.0 - 2025-01-24 + +### Added + +- Set up a _GitHub Action_ to automatically extract locales when the `main` branch changes + +### Changed + +- Extended the _Financial Modeling Prep_ service +- Improved the language localization for Ukrainian (`uk`) +- Refreshed the cryptocurrencies list +- Upgraded `date-fns` from version `3.6.0` to `4.1.0` +- Upgraded `rxjs` from version `7.5.6` to `7.8.1` + +### Fixed + +- Fixed an issue with the detection of the thousand separator by locale +- Fixed an issue with holdings and sectors while using symbol profile overrides +- Fixed an issue with the MIME type detection in the scraper configuration + +## 2.135.0 - 2025-01-19 + +### Changed + +- Moved the language localization for Polski (`pl`) from experimental to general availability +- Extended the _Financial Modeling Prep_ service +- Switched to _ESLint_’s flat config format +- Upgraded `bull` from version `4.16.2` to `4.16.4` +- Upgraded `chart.js` from version `4.2.0` to `4.4.7` +- Upgraded `chartjs-chart-treemap` from version `2.3.1` to `3.1.0` +- Upgraded `chartjs-plugin-annotation` from version `2.1.2` to `3.1.0` +- Upgraded `eslint` dependencies +- Upgraded `nestjs` from version `10.1.3` to `10.4.15` +- Upgraded `Nx` from version `20.3.0` to `20.3.2` +- Upgraded `reflect-metadata` from version `0.1.13` to `0.2.2` +- Upgraded `uuid` from version `11.0.2` to `11.0.5` + +## 2.134.0 - 2025-01-15 + +### Added + +- Set up the language localization for Українська (`uk`) + +### Changed + +- Extended the health check endpoint to include database and cache operations (experimental) +- Refactored various `lodash` functions with native JavaScript equivalents +- Improved the language localization for German (`de`) +- Upgraded `prisma` from version `6.1.0` to `6.2.1` + +### Fixed + +- Fixed an issue with the import of activities with type `FEE` (where unit price is `0`) +- Fixed an issue with the renaming of activities with type `FEE`, `INTEREST`, `ITEM` or `LIABILITY` +- Handled an exception in the scraper configuration introduced by the migration from `got` to `fetch` + +## 2.133.1 - 2025-01-09 + +### Added + +- Added a _Copy AI prompt to clipboard_ action to the analysis page (experimental) + +### Changed + +- Improved the usability of the _Copy link to clipboard_ action by adding a confirmation on success in the access table to share the portfolio +- Improved the endpoint to fetch the logo of an asset or a platform by sending the original MIME type +- Eliminated `got` in favor of using `fetch` +- Changed the `REDIS_HOST` from `localhost` to `redis` in `.env.example` +- Changed the _Postgres_ host from `localhost` to `postgres` in `.env.example` +- Changed the _Postgres_ image from `postgres:15` to `postgres:15-alpine` in the `docker-compose` files +- Introduced `extends` in the `docker-compose` files +- Improved the language localization for German (`de`) +- Refreshed the cryptocurrencies list +- Upgraded `envalid` from version `7.3.1` to `8.0.0` +- Upgraded `replace-in-file` from version `7.0.1` to `8.3.0` + +### Fixed + +- Improved the handling of a missing url in the endpoint to fetch the logo of an asset or a platform +- Fixed the _Storybook_ setup + ## 2.132.0 - 2024-12-30 ### Added @@ -27,6 +1075,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `ngx-markdown` from version `18.0.0` to `19.0.0` - Upgraded `Nx` from version `20.1.2` to `20.3.0` - Upgraded `prisma` from version `6.0.1` to `6.1.0` +- Upgraded `storybook` from version `8.2.5` to `8.4.7` - Upgraded `zone.js` from version `0.14.10` to `0.15.0` ### Fixed @@ -3151,7 +4200,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Added the language localization for Français (`fr`) +- Added the language localization for French (`fr`) - Extended the landing page by a global heat map of subscribers - Added support for the thousand separator in the global heat map component @@ -3180,7 +4229,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for the dividend timeline grouped by year - Added support for the investment timeline grouped by year -- Set up the language localization for Français (`fr`) +- Set up the language localization for French (`fr`) ### Changed @@ -3289,7 +4338,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Improved the value redaction interceptor (including `comment`) -- Improved the language localization for Español (`es`) +- Improved the language localization for Spanish (`es`) - Upgraded `cheerio` from version `1.0.0-rc.6` to `1.0.0-rc.12` - Upgraded `prisma` from version `4.6.1` to `4.7.1` @@ -3518,7 +4567,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Improved the usage of the value component in the admin control panel -- Improved the language localization for Español (`es`) +- Improved the language localization for Spanish (`es`) ### Fixed @@ -3540,7 +4589,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Set up the language localization for Español (`es`) +- Set up the language localization for Spanish (`es`) - Added support for sectors in mutual funds ## 1.198.0 - 25.09.2022 @@ -5323,7 +6372,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Changed the navigation to always show the portfolio page - Migrated the data type of currencies from `enum` to `string` in the database - Supported unlimited currencies (instead of `CHF`, `EUR`, `GBP` and `USD`) -- Respected the accounts' currencies in the exchange rate service +- Respected the accounts’ currencies in the exchange rate service ### Fixed diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index b009679ac..31b0507bb 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -5,14 +5,14 @@ ### Prerequisites - [Docker](https://www.docker.com/products/docker-desktop) -- [Node.js](https://nodejs.org/en/download) (version 20+) +- [Node.js](https://nodejs.org/en/download) (version 22+) - Create a local copy of this Git repository (clone) - Copy the file `.env.dev` to `.env` and populate it with your data (`cp .env.dev .env`) ### Setup 1. Run `npm install` -1. Run `docker compose --env-file ./.env -f docker/docker-compose.dev.yml up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io) +1. Run `docker compose -f docker/docker-compose.dev.yml up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io) 1. Run `npm run database:setup` to initialize the database schema 1. Start the [server](#start-server) and the [client](#start-client) 1. Open https://localhost:4200/en in your browser @@ -30,7 +30,13 @@ Run `npm run start:server` ### Start Client -Run `npm run start:client` and open https://localhost:4200/en in your browser +#### English (Default) + +Run `npm run start:client` and open https://localhost:4200/en in your browser. + +#### Other Languages + +To start the client in a different language, such as German (`de`), adapt the `start:client` script in the `package.json` file by changing `--configuration=development-en` to `--configuration=development-de`. Then, run `npm run start:client` and open https://localhost:4200/de in your browser. ### Start _Storybook_ @@ -60,6 +66,10 @@ Remove permission in `UserService` using `without()` Use `@if (user?.settings?.isExperimentalFeatures) {}` in HTML template +## Component Library (_Storybook_) + +https://ghostfol.io/development/storybook + ## Git ### Rebase @@ -101,3 +111,12 @@ https://www.prisma.io/docs/concepts/components/prisma-migrate/db-push Run `npm run prisma migrate dev --name added_job_title` https://www.prisma.io/docs/concepts/components/prisma-migrate#getting-started-with-prisma-migrate + +## SSL + +Generate `localhost.cert` and `localhost.pem` files. + +``` +openssl req -x509 -newkey rsa:2048 -nodes -keyout apps/client/localhost.pem -out apps/client/localhost.cert -days 365 \ + -subj "/C=CH/ST=State/L=City/O=Organization/OU=Unit/CN=localhost" +``` diff --git a/Dockerfile b/Dockerfile index e6c38f273..c740413ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM node:20-slim AS builder +FROM --platform=$BUILDPLATFORM node:22-slim AS builder # Build application and add additional files WORKDIR /ghostfolio @@ -25,32 +25,33 @@ RUN npm install COPY ./decorate-angular-cli.js decorate-angular-cli.js RUN node decorate-angular-cli.js -COPY ./nx.json nx.json -COPY ./replace.build.js replace.build.js -COPY ./jest.preset.js jest.preset.js +COPY ./apps apps +COPY ./libs libs COPY ./jest.config.ts jest.config.ts +COPY ./jest.preset.js jest.preset.js +COPY ./nx.json nx.json +COPY ./replace.build.mjs replace.build.mjs COPY ./tsconfig.base.json tsconfig.base.json -COPY ./libs libs -COPY ./apps apps +ENV NX_DAEMON=false RUN npm run build:production # Prepare the dist image with additional node_modules WORKDIR /ghostfolio/dist/apps/api # package.json was generated by the build process, however the original -# package-lock.json needs to be used to ensure the same versions +# package-lock.json needs to be used to ensure the same versions COPY ./package-lock.json /ghostfolio/dist/apps/api/package-lock.json RUN npm install COPY prisma /ghostfolio/dist/apps/api/prisma # Overwrite the generated package.json with the original one to ensure having -# all the scripts +# all the scripts COPY package.json /ghostfolio/dist/apps/api RUN npm run database:generate-typings # Image to run, copy everything needed from builder -FROM node:20-slim +FROM node:22-slim LABEL org.opencontainers.image.source="https://github.com/ghostfolio/ghostfolio" ENV NODE_ENV=production diff --git a/README.md b/README.md index dca360c39..02f17fe49 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ **Open Source Wealth Management Software** [**Ghostfol.io**](https://ghostfol.io) | [**Live Demo**](https://ghostfol.io/en/demo) | [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) | [**FAQ**](https://ghostfol.io/en/faq) | -[**Blog**](https://ghostfol.io/en/blog) | [**Slack**](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) | [**X**](https://x.com/ghostfolio_) +[**Blog**](https://ghostfol.io/en/blog) | [**LinkedIn**](https://www.linkedin.com/company/ghostfolio) | [**Slack**](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) | [**X**](https://x.com/ghostfolio_) [![Shield: Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-Support-yellow?logo=buymeacoffee)](https://www.buymeacoffee.com/ghostfolio) [![Shield: Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-limegreen.svg)](#contributing) [![Shield: Docker Pulls](https://img.shields.io/docker/pulls/ghostfolio/ghostfolio?label=Docker%20Pulls)](https://hub.docker.com/r/ghostfolio/ghostfolio) @@ -25,7 +25,7 @@ ## Ghostfolio Premium -Our official **[Ghostfolio Premium](https://ghostfol.io/en/pricing)** cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. +Our official **[Ghostfolio Premium](https://ghostfol.io/en/pricing)** cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. If you prefer to run Ghostfolio on your own infrastructure, please find further instructions in the [Self-hosting](#self-hosting) section. @@ -47,7 +47,7 @@ Ghostfolio is for you if you are... - ✅ Create, update and delete transactions - ✅ Multi account management -- ✅ Portfolio performance: Time-weighted rate of return (TWR) for `Today`, `WTD`, `MTD`, `YTD`, `1Y`, `5Y`, `Max` +- ✅ Portfolio performance: Return on Average Investment (ROAI) for `Today`, `WTD`, `MTD`, `YTD`, `1Y`, `5Y`, `Max` - ✅ Various charts - ✅ Static analysis to identify potential risks in your portfolio - ✅ Import and export transactions @@ -118,7 +118,7 @@ We provide official container images hosted on [Docker Hub](https://hub.docker.c Run the following command to start the Docker images from [Docker Hub](https://hub.docker.com/r/ghostfolio/ghostfolio): ```bash -docker compose --env-file ./.env -f docker/docker-compose.yml up -d +docker compose -f docker/docker-compose.yml up -d ``` #### b. Build and run environment @@ -126,8 +126,8 @@ docker compose --env-file ./.env -f docker/docker-compose.yml up -d Run the following commands to build and start the Docker images: ```bash -docker compose --env-file ./.env -f docker/docker-compose.build.yml build -docker compose --env-file ./.env -f docker/docker-compose.build.yml up -d +docker compose -f docker/docker-compose.build.yml build +docker compose -f docker/docker-compose.build.yml up -d ``` #### Setup @@ -137,9 +137,18 @@ docker compose --env-file ./.env -f docker/docker-compose.build.yml up -d #### Upgrade Version -1. Increase the version of the `ghostfolio/ghostfolio` Docker image in `docker/docker-compose.yml` -1. Run the following command to start the new Docker image: `docker compose --env-file ./.env -f docker/docker-compose.yml up -d` - At each start, the container will automatically apply the database schema migrations if needed. +1. Update the _Ghostfolio_ Docker image + - Increase the version of the `ghostfolio/ghostfolio` Docker image in `docker/docker-compose.yml` + - Run the following command if `ghostfolio:latest` is set: + ```bash + docker compose -f docker/docker-compose.yml pull + ``` + +1. Run the following command to start the new Docker image: + ```bash + docker compose -f docker/docker-compose.yml up -d + ``` + The container will automatically apply any required database schema migrations during startup. ### Home Server Systems (Community) @@ -212,18 +221,18 @@ Deprecated: `GET http://localhost:3333/api/v1/auth/anonymous/ { const accessesWithGranteeUser = await this.accessService.accesses({ include: { - GranteeUser: true + granteeUser: true }, orderBy: { granteeUserId: 'asc' }, where: { userId: this.request.user.id } }); return accessesWithGranteeUser.map( - ({ alias, GranteeUser, id, permissions }) => { - if (GranteeUser) { + ({ alias, granteeUser, id, permissions }) => { + if (granteeUser) { return { alias, id, permissions, - grantee: GranteeUser?.id, + grantee: granteeUser?.id, type: 'PRIVATE' }; } @@ -85,11 +85,11 @@ export class AccessController { try { return this.accessService.createAccess({ alias: data.alias || undefined, - GranteeUser: data.granteeUserId + granteeUser: data.granteeUserId ? { connect: { id: data.granteeUserId } } : undefined, permissions: data.permissions, - User: { connect: { id: this.request.user.id } } + user: { connect: { id: this.request.user.id } } }); } catch { throw new HttpException( diff --git a/apps/api/src/app/access/access.service.ts b/apps/api/src/app/access/access.service.ts index ccba595e3..8403cdc09 100644 --- a/apps/api/src/app/access/access.service.ts +++ b/apps/api/src/app/access/access.service.ts @@ -13,7 +13,7 @@ export class AccessService { ): Promise { return this.prismaService.access.findFirst({ include: { - GranteeUser: true + granteeUser: true }, where: accessWhereInput }); diff --git a/apps/api/src/app/account-balance/account-balance.service.ts b/apps/api/src/app/account-balance/account-balance.service.ts index 34d98d266..10353f4ca 100644 --- a/apps/api/src/app/account-balance/account-balance.service.ts +++ b/apps/api/src/app/account-balance/account-balance.service.ts @@ -30,7 +30,7 @@ export class AccountBalanceService { ): Promise { return this.prismaService.accountBalance.findFirst({ include: { - Account: true + account: true }, where: accountBalanceWhereInput }); @@ -46,7 +46,7 @@ export class AccountBalanceService { }): Promise { const accountBalance = await this.prismaService.accountBalance.upsert({ create: { - Account: { + account: { connect: { id_userId: { userId, @@ -154,7 +154,7 @@ export class AccountBalanceService { } if (withExcludedAccounts === false) { - where.Account = { isExcluded: false }; + where.account = { isExcluded: false }; } const balances = await this.prismaService.accountBalance.findMany({ @@ -163,7 +163,7 @@ export class AccountBalanceService { date: 'asc' }, select: { - Account: true, + account: true, date: true, id: true, value: true @@ -174,10 +174,10 @@ export class AccountBalanceService { balances: balances.map((balance) => { return { ...balance, - accountId: balance.Account.id, + accountId: balance.account.id, valueInBaseCurrency: this.exchangeRateDataService.toCurrency( balance.value, - balance.Account.currency, + balance.account.currency, userCurrency ) }; diff --git a/apps/api/src/app/account/account.controller.ts b/apps/api/src/app/account/account.controller.ts index c0f4dac6a..51a33fa9e 100644 --- a/apps/api/src/app/account/account.controller.ts +++ b/apps/api/src/app/account/account.controller.ts @@ -9,7 +9,7 @@ import { ImpersonationService } from '@ghostfolio/api/services/impersonation/imp import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import { AccountBalancesResponse, - Accounts + AccountsResponse } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import type { @@ -57,17 +57,17 @@ export class AccountController { @HasPermission(permissions.deleteAccount) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async deleteAccount(@Param('id') id: string): Promise { - const account = await this.accountService.accountWithOrders( + const account = await this.accountService.accountWithActivities( { id_userId: { id, userId: this.request.user.id } }, - { Order: true } + { activities: true } ); - if (!account || account?.Order.length > 0) { + if (!account || account?.activities.length > 0) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN @@ -87,10 +87,10 @@ export class AccountController { @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getAllAccounts( - @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId, + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Query('dataSource') filterByDataSource?: string, @Query('symbol') filterBySymbol?: string - ): Promise { + ): Promise { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); @@ -110,7 +110,7 @@ export class AccountController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(RedactValuesInResponseInterceptor) public async getAccountById( - @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId, + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('id') id: string ): Promise { const impersonationUserId = @@ -134,7 +134,7 @@ export class AccountController { ): Promise { return this.accountBalanceService.getAccountBalances({ filters: [{ id, type: 'ACCOUNT' }], - userCurrency: this.request.user.Settings.settings.baseCurrency, + userCurrency: this.request.user.settings.settings.baseCurrency, userId: this.request.user.id }); } @@ -152,8 +152,8 @@ export class AccountController { return this.accountService.createAccount( { ...data, - Platform: { connect: { id: platformId } }, - User: { connect: { id: this.request.user.id } } + platform: { connect: { id: platformId } }, + user: { connect: { id: this.request.user.id } } }, this.request.user.id ); @@ -163,7 +163,7 @@ export class AccountController { return this.accountService.createAccount( { ...data, - User: { connect: { id: this.request.user.id } } + user: { connect: { id: this.request.user.id } } }, this.request.user.id ); @@ -250,8 +250,8 @@ export class AccountController { { data: { ...data, - Platform: { connect: { id: platformId } }, - User: { connect: { id: this.request.user.id } } + platform: { connect: { id: platformId } }, + user: { connect: { id: this.request.user.id } } }, where: { id_userId: { @@ -270,10 +270,10 @@ export class AccountController { { data: { ...data, - Platform: originalAccount.platformId + platform: originalAccount.platformId ? { disconnect: true } : undefined, - User: { connect: { id: this.request.user.id } } + user: { connect: { id: this.request.user.id } } }, where: { id_userId: { diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts index df369859b..1c8adbd16 100644 --- a/apps/api/src/app/account/account.service.ts +++ b/apps/api/src/app/account/account.service.ts @@ -7,7 +7,13 @@ import { Filter } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; -import { Account, Order, Platform, Prisma } from '@prisma/client'; +import { + Account, + AccountBalance, + Order, + Platform, + Prisma +} from '@prisma/client'; import { Big } from 'big.js'; import { format } from 'date-fns'; import { groupBy } from 'lodash'; @@ -33,12 +39,12 @@ export class AccountService { return account; } - public async accountWithOrders( + public async accountWithActivities( accountWhereUniqueInput: Prisma.AccountWhereUniqueInput, accountInclude: Prisma.AccountInclude ): Promise< Account & { - Order?: Order[]; + activities?: Order[]; } > { return this.prismaService.account.findUnique({ @@ -56,13 +62,19 @@ export class AccountService { orderBy?: Prisma.AccountOrderByWithRelationInput; }): Promise< (Account & { - Order?: Order[]; - Platform?: Platform; + activities?: Order[]; + balances?: AccountBalance[]; + platform?: Platform; })[] > { const { include = {}, skip, take, cursor, where, orderBy } = params; - include.balances = { orderBy: { date: 'desc' }, take: 1 }; + const isBalancesIncluded = !!include.balances; + + include.balances = { + orderBy: { date: 'desc' }, + ...(isBalancesIncluded ? {} : { take: 1 }) + }; const accounts = await this.prismaService.account.findMany({ cursor, @@ -76,7 +88,9 @@ export class AccountService { return accounts.map((account) => { account = { ...account, balance: account.balances[0]?.value ?? 0 }; - delete account.balances; + if (!isBalancesIncluded) { + delete account.balances; + } return account; }); @@ -126,7 +140,10 @@ export class AccountService { public async getAccounts(aUserId: string): Promise { const accounts = await this.accounts({ - include: { Order: true, Platform: true }, + include: { + activities: true, + platform: true + }, orderBy: { name: 'asc' }, where: { userId: aUserId } }); @@ -134,15 +151,15 @@ export class AccountService { return accounts.map((account) => { let transactionCount = 0; - for (const order of account.Order) { - if (!order.isDraft) { + for (const { isDraft } of account.activities) { + if (!isDraft) { transactionCount += 1; } } const result = { ...account, transactionCount }; - delete result.Order; + delete result.activities; return result; }); diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index a761bbbae..8b2118ab1 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -3,22 +3,22 @@ import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard' import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { ManualService } from '@ghostfolio/api/services/data-provider/manual/manual.service'; -import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { DemoService } from '@ghostfolio/api/services/demo/demo.service'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, DATA_GATHERING_QUEUE_PRIORITY_MEDIUM, - GATHER_ASSET_PROFILE_PROCESS, - GATHER_ASSET_PROFILE_PROCESS_OPTIONS + GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, + GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS } from '@ghostfolio/common/config'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { AdminData, AdminMarketData, - AdminMarketDataDetails, AdminUsers, - EnhancedSymbolProfile + EnhancedSymbolProfile, + ScraperConfiguration } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import type { @@ -50,8 +50,6 @@ import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { AdminService } from './admin.service'; import { UpdateAssetProfileDto } from './update-asset-profile.dto'; -import { UpdateBulkMarketDataDto } from './update-bulk-market-data.dto'; -import { UpdateMarketDataDto } from './update-market-data.dto'; @Controller('admin') export class AdminController { @@ -59,8 +57,8 @@ export class AdminController { private readonly adminService: AdminService, private readonly apiService: ApiService, private readonly dataGatheringService: DataGatheringService, + private readonly demoService: DemoService, private readonly manualService: ManualService, - private readonly marketDataService: MarketDataService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -68,7 +66,14 @@ export class AdminController { @HasPermission(permissions.accessAdminControl) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async getAdminData(): Promise { - return this.adminService.get(); + return this.adminService.get({ user: this.request.user }); + } + + @Get('demo-user/sync') + @HasPermission(permissions.syncDemoUserAccount) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async syncDemoUserAccount(): Promise { + return this.demoService.syncDemoUserAccount(); } @HasPermission(permissions.accessAdminControl) @@ -83,7 +88,7 @@ export class AdminController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async gatherMax(): Promise { const assetProfileIdentifiers = - await this.dataGatheringService.getAllAssetProfileIdentifiers(); + await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { @@ -92,9 +97,9 @@ export class AdminController { dataSource, symbol }, - name: GATHER_ASSET_PROFILE_PROCESS, + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, opts: { - ...GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + ...GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, jobId: getAssetProfileIdentifier({ dataSource, symbol }), priority: DATA_GATHERING_QUEUE_PRIORITY_MEDIUM } @@ -110,7 +115,7 @@ export class AdminController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async gatherProfileData(): Promise { const assetProfileIdentifiers = - await this.dataGatheringService.getAllAssetProfileIdentifiers(); + await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { @@ -119,9 +124,9 @@ export class AdminController { dataSource, symbol }, - name: GATHER_ASSET_PROFILE_PROCESS, + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, opts: { - ...GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + ...GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, jobId: getAssetProfileIdentifier({ dataSource, symbol }), priority: DATA_GATHERING_QUEUE_PRIORITY_MEDIUM } @@ -142,9 +147,9 @@ export class AdminController { dataSource, symbol }, - name: GATHER_ASSET_PROFILE_PROCESS, + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, opts: { - ...GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + ...GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, jobId: getAssetProfileIdentifier({ dataSource, symbol }), priority: DATA_GATHERING_QUEUE_PRIORITY_HIGH } @@ -214,30 +219,16 @@ export class AdminController { }); } - /** - * @deprecated - */ - @Get('market-data/:dataSource/:symbol') - @HasPermission(permissions.accessAdminControl) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getMarketDataBySymbol( - @Param('dataSource') dataSource: DataSource, - @Param('symbol') symbol: string - ): Promise { - return this.adminService.getMarketDataBySymbol({ dataSource, symbol }); - } - @HasPermission(permissions.accessAdminControl) @Post('market-data/:dataSource/:symbol/test') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async testMarketData( - @Body() data: { scraperConfiguration: string }, + @Body() data: { scraperConfiguration: ScraperConfiguration }, @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise<{ price: number }> { try { - const scraperConfiguration = JSON.parse(data.scraperConfiguration); - const price = await this.manualService.test(scraperConfiguration); + const price = await this.manualService.test(data.scraperConfiguration); if (price) { return { price }; @@ -253,58 +244,6 @@ export class AdminController { } } - /** - * @deprecated - */ - @HasPermission(permissions.accessAdminControl) - @Post('market-data/:dataSource/:symbol') - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async updateMarketData( - @Body() data: UpdateBulkMarketDataDto, - @Param('dataSource') dataSource: DataSource, - @Param('symbol') symbol: string - ) { - const dataBulkUpdate: Prisma.MarketDataUpdateInput[] = data.marketData.map( - ({ date, marketPrice }) => ({ - dataSource, - marketPrice, - symbol, - date: parseISO(date), - state: 'CLOSE' - }) - ); - - return this.marketDataService.updateMany({ - data: dataBulkUpdate - }); - } - - /** - * @deprecated - */ - @HasPermission(permissions.accessAdminControl) - @Put('market-data/:dataSource/:symbol/:dateString') - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async update( - @Param('dataSource') dataSource: DataSource, - @Param('dateString') dateString: string, - @Param('symbol') symbol: string, - @Body() data: UpdateMarketDataDto - ) { - const date = parseISO(dateString); - - return this.marketDataService.updateMarketData({ - data: { marketPrice: data.marketPrice, state: 'CLOSE' }, - where: { - dataSource_date_symbol: { - dataSource, - date, - symbol - } - } - }); - } - @HasPermission(permissions.accessAdminControl) @Post('profile-data/:dataSource/:symbol') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @@ -316,7 +255,7 @@ export class AdminController { return this.adminService.addAssetProfile({ dataSource, symbol, - currency: this.request.user.Settings.settings.baseCurrency + currency: this.request.user.settings.settings.baseCurrency }); } @@ -334,15 +273,14 @@ export class AdminController { @Patch('profile-data/:dataSource/:symbol') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async patchAssetProfileData( - @Body() assetProfileData: UpdateAssetProfileDto, + @Body() assetProfile: UpdateAssetProfileDto, @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise { - return this.adminService.patchAssetProfileData({ - ...assetProfileData, - dataSource, - symbol - }); + return this.adminService.patchAssetProfileData( + { dataSource, symbol }, + assetProfile + ); } @HasPermission(permissions.accessAdminControl) diff --git a/apps/api/src/app/admin/admin.module.ts b/apps/api/src/app/admin/admin.module.ts index 81c58ff03..598b68f17 100644 --- a/apps/api/src/app/admin/admin.module.ts +++ b/apps/api/src/app/admin/admin.module.ts @@ -1,10 +1,10 @@ -import { BenchmarkModule } from '@ghostfolio/api/app/benchmark/benchmark.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module'; -import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; +import { DemoModule } from '@ghostfolio/api/services/demo/demo.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -25,13 +25,13 @@ import { QueueModule } from './queue/queue.module'; ConfigurationModule, DataGatheringModule, DataProviderModule, + DemoModule, ExchangeRateDataModule, MarketDataModule, OrderModule, PrismaModule, PropertyModule, QueueModule, - SubscriptionModule, SymbolProfileModule, TransformDataSourceInRequestModule ], diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index fb6e90f5d..9e645c059 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -1,7 +1,6 @@ -import { BenchmarkService } from '@ghostfolio/api/app/benchmark/benchmark.service'; import { OrderService } from '@ghostfolio/api/app/order/order.service'; -import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service'; import { environment } from '@ghostfolio/api/environments/environment'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -10,7 +9,6 @@ import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { - DEFAULT_CURRENCY, PROPERTY_CURRENCIES, PROPERTY_IS_READ_ONLY_MODE, PROPERTY_IS_USER_SIGNUP_ENABLED @@ -30,9 +28,15 @@ import { EnhancedSymbolProfile, Filter } from '@ghostfolio/common/interfaces'; -import { MarketDataPreset } from '@ghostfolio/common/types'; +import { Sector } from '@ghostfolio/common/interfaces/sector.interface'; +import { MarketDataPreset, UserWithSettings } from '@ghostfolio/common/types'; -import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { + BadRequestException, + HttpException, + Injectable, + Logger +} from '@nestjs/common'; import { AssetClass, AssetSubClass, @@ -43,6 +47,7 @@ import { SymbolProfile } from '@prisma/client'; import { differenceInDays } from 'date-fns'; +import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { groupBy } from 'lodash'; @Injectable() @@ -56,7 +61,6 @@ export class AdminService { private readonly orderService: OrderService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, - private readonly subscriptionService: SubscriptionService, private readonly symbolProfileService: SymbolProfileService ) {} @@ -108,34 +112,32 @@ export class AdminService { symbol }: AssetProfileIdentifier) { await this.marketDataService.deleteMany({ dataSource, symbol }); - await this.symbolProfileService.delete({ dataSource, symbol }); - } - public async get(): Promise { - const exchangeRates = this.exchangeRateDataService - .getCurrencies() - .filter((currency) => { - return currency !== DEFAULT_CURRENCY; - }) - .map((currency) => { - const label1 = DEFAULT_CURRENCY; - const label2 = currency; + const currency = getCurrencyFromSymbol(symbol); + const customCurrencies = + await this.propertyService.getByKey(PROPERTY_CURRENCIES); - return { - label1, - label2, - dataSource: - DataSource[ - this.configurationService.get('DATA_SOURCE_EXCHANGE_RATES') - ], - symbol: `${label1}${label2}`, - value: this.exchangeRateDataService.toCurrency( - 1, - DEFAULT_CURRENCY, - currency - ) - }; - }); + if (customCurrencies.includes(currency)) { + const updatedCustomCurrencies = customCurrencies.filter( + (customCurrency) => { + return customCurrency !== currency; + } + ); + + await this.putSetting( + PROPERTY_CURRENCIES, + JSON.stringify(updatedCustomCurrencies) + ); + } else { + await this.symbolProfileService.delete({ dataSource, symbol }); + } + } + + public async get({ user }: { user: UserWithSettings }): Promise { + const dataSources = await this.dataProviderService.getDataSources({ + user, + includeGhostfolio: true + }); const [settings, transactionCount, userCount] = await Promise.all([ this.propertyService.get(), @@ -143,8 +145,27 @@ export class AdminService { this.countUsersWithAnalytics() ]); + const dataProviders = await Promise.all( + dataSources.map(async (dataSource) => { + const dataProviderInfo = this.dataProviderService + .getDataProvider(dataSource) + .getDataProviderInfo(); + + const assetProfileCount = await this.prismaService.symbolProfile.count({ + where: { + dataSource + } + }); + + return { + ...dataProviderInfo, + assetProfileCount + }; + }) + ); + return { - exchangeRates, + dataProviders, settings, transactionCount, userCount, @@ -223,7 +244,7 @@ export class AdminService { if (sortColumn === 'activitiesCount') { orderBy = { - Order: { + activities: { _count: sortDirection } }; @@ -241,7 +262,15 @@ export class AdminService { where, select: { _count: { - select: { Order: true } + select: { + activities: true, + watchedBy: true + } + }, + activities: { + orderBy: [{ date: 'asc' }], + select: { date: true }, + take: 1 }, assetClass: true, assetSubClass: true, @@ -250,16 +279,13 @@ export class AdminService { currency: true, dataSource: true, id: true, + isActive: true, isUsedByUsersWithSubscription: true, name: true, - Order: { - orderBy: [{ date: 'asc' }], - select: { date: true }, - take: 1 - }, scraperConfiguration: true, sectors: true, - symbol: true + symbol: true, + SymbolProfileOverrides: true } }), this.prismaService.symbolProfile.count({ where }) @@ -302,6 +328,7 @@ export class AdminService { assetProfiles.map( async ({ _count, + activities, assetClass, assetSubClass, comment, @@ -309,15 +336,14 @@ export class AdminService { currency, dataSource, id, + isActive, isUsedByUsersWithSubscription, name, - Order, sectors, - symbol + symbol, + SymbolProfileOverrides }) => { - const countriesCount = countries - ? Object.keys(countries).length - : 0; + let countriesCount = countries ? Object.keys(countries).length : 0; const lastMarketPrice = lastMarketPriceMap.get( getAssetProfileIdentifier({ dataSource, symbol }) @@ -331,7 +357,34 @@ export class AdminService { ); })?._count ?? 0; - const sectorsCount = sectors ? Object.keys(sectors).length : 0; + let sectorsCount = sectors ? Object.keys(sectors).length : 0; + + if (SymbolProfileOverrides) { + assetClass = SymbolProfileOverrides.assetClass ?? assetClass; + assetSubClass = + SymbolProfileOverrides.assetSubClass ?? assetSubClass; + + if ( + ( + SymbolProfileOverrides.countries as unknown as Prisma.JsonArray + )?.length > 0 + ) { + countriesCount = ( + SymbolProfileOverrides.countries as unknown as Prisma.JsonArray + ).length; + } + + name = SymbolProfileOverrides.name ?? name; + + if ( + (SymbolProfileOverrides.sectors as unknown as Sector[]) + ?.length > 0 + ) { + sectorsCount = ( + SymbolProfileOverrides.sectors as unknown as Prisma.JsonArray + ).length; + } + } return { assetClass, @@ -341,14 +394,17 @@ export class AdminService { countriesCount, dataSource, id, + isActive, lastMarketPrice, name, symbol, marketDataItemCount, sectorsCount, - activitiesCount: _count.Order, - date: Order?.[0]?.date, - isUsedByUsersWithSubscription: await isUsedByUsersWithSubscription + activitiesCount: _count.activities, + date: activities?.[0]?.date, + isUsedByUsersWithSubscription: + await isUsedByUsersWithSubscription, + watchedByCount: _count.watchedBy }; } ) @@ -424,7 +480,8 @@ export class AdminService { currency, dataSource, dateOfFirstActivity, - symbol + symbol, + isActive: true } }; } @@ -444,61 +501,126 @@ export class AdminService { return { count, users }; } - public async patchAssetProfileData({ - assetClass, - assetSubClass, - comment, - countries, - currency, - dataSource, - holdings, - name, - scraperConfiguration, - sectors, - symbol, - symbolMapping, - url - }: AssetProfileIdentifier & Prisma.SymbolProfileUpdateInput) { - const symbolProfileOverrides = { - assetClass: assetClass as AssetClass, - assetSubClass: assetSubClass as AssetSubClass, - name: name as string, - url: url as string - }; - - const updatedSymbolProfile: AssetProfileIdentifier & - Prisma.SymbolProfileUpdateInput = { + public async patchAssetProfileData( + { dataSource, symbol }: AssetProfileIdentifier, + { + assetClass, + assetSubClass, comment, countries, currency, - dataSource, + dataSource: newDataSource, holdings, + isActive, + name, scraperConfiguration, sectors, - symbol, + symbol: newSymbol, symbolMapping, - ...(dataSource === 'MANUAL' - ? { assetClass, assetSubClass, name, url } - : { - SymbolProfileOverrides: { - upsert: { - create: symbolProfileOverrides, - update: symbolProfileOverrides - } + url + }: Prisma.SymbolProfileUpdateInput + ) { + if ( + newSymbol && + newDataSource && + (newSymbol !== symbol || newDataSource !== dataSource) + ) { + const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([ + { + dataSource: DataSource[newDataSource.toString()], + symbol: newSymbol as string + } + ]); + + if (assetProfile) { + throw new HttpException( + getReasonPhrase(StatusCodes.CONFLICT), + StatusCodes.CONFLICT + ); + } + + try { + Promise.all([ + await this.symbolProfileService.updateAssetProfileIdentifier( + { + dataSource, + symbol + }, + { + dataSource: DataSource[newDataSource.toString()], + symbol: newSymbol as string } - }) - }; + ), + await this.marketDataService.updateAssetProfileIdentifier( + { + dataSource, + symbol + }, + { + dataSource: DataSource[newDataSource.toString()], + symbol: newSymbol as string + } + ) + ]); - await this.symbolProfileService.updateSymbolProfile(updatedSymbolProfile); + return this.symbolProfileService.getSymbolProfiles([ + { + dataSource: DataSource[newDataSource.toString()], + symbol: newSymbol as string + } + ])?.[0]; + } catch { + throw new HttpException( + getReasonPhrase(StatusCodes.BAD_REQUEST), + StatusCodes.BAD_REQUEST + ); + } + } else { + const symbolProfileOverrides = { + assetClass: assetClass as AssetClass, + assetSubClass: assetSubClass as AssetSubClass, + name: name as string, + url: url as string + }; - const [symbolProfile] = await this.symbolProfileService.getSymbolProfiles([ - { + const updatedSymbolProfile: Prisma.SymbolProfileUpdateInput = { + comment, + countries, + currency, dataSource, - symbol - } - ]); + holdings, + isActive, + scraperConfiguration, + sectors, + symbol, + symbolMapping, + ...(dataSource === 'MANUAL' + ? { assetClass, assetSubClass, name, url } + : { + SymbolProfileOverrides: { + upsert: { + create: symbolProfileOverrides, + update: symbolProfileOverrides + } + } + }) + }; + + await this.symbolProfileService.updateSymbolProfile( + { + dataSource, + symbol + }, + updatedSymbolProfile + ); - return symbolProfile; + return this.symbolProfileService.getSymbolProfiles([ + { + dataSource: dataSource as DataSource, + symbol: symbol as string + } + ])?.[0]; + } } public async putSetting(key: string, value: string) { @@ -525,7 +647,7 @@ export class AdminService { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { where = { NOT: { - Analytics: null + analytics: null } }; } @@ -549,10 +671,10 @@ export class AdminService { select: { _count: { select: { - Order: { + activities: { where: { - User: { - Subscription: { + user: { + subscriptions: { some: { expiresAt: { gt: new Date() @@ -570,7 +692,7 @@ export class AdminService { } }); - return _count.Order > 0; + return _count.activities > 0; } } } @@ -657,8 +779,10 @@ export class AdminService { countriesCount: 0, date: dateOfFirstActivity, id: undefined, + isActive: true, name: symbol, - sectorsCount: 0 + sectorsCount: 0, + watchedByCount: 0 }; } ); @@ -681,13 +805,13 @@ export class AdminService { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { orderBy = { - Analytics: { + analytics: { lastRequestAt: 'desc' } }; where = { NOT: { - Analytics: null + analytics: null } }; } @@ -699,9 +823,9 @@ export class AdminService { where, select: { _count: { - select: { Account: true, Order: true } + select: { accounts: true, activities: true } }, - Analytics: { + analytics: { select: { activityCount: true, country: true, @@ -712,26 +836,33 @@ export class AdminService { createdAt: true, id: true, role: true, - Subscription: true + subscriptions: { + orderBy: { + expiresAt: 'desc' + }, + take: 1, + where: { + expiresAt: { + gt: new Date() + } + } + } } }); return usersWithAnalytics.map( - ({ _count, Analytics, createdAt, id, role, Subscription }) => { + ({ _count, analytics, createdAt, id, role, subscriptions }) => { const daysSinceRegistration = differenceInDays(new Date(), createdAt) + 1; - const engagement = Analytics - ? Analytics.activityCount / daysSinceRegistration + const engagement = analytics + ? analytics.activityCount / daysSinceRegistration : undefined; - const subscription = this.configurationService.get( - 'ENABLE_FEATURE_SUBSCRIPTION' - ) - ? this.subscriptionService.getSubscription({ - createdAt, - subscriptions: Subscription - }) - : undefined; + const subscription = + this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && + subscriptions?.length > 0 + ? subscriptions[0] + : undefined; return { createdAt, @@ -739,11 +870,11 @@ export class AdminService { id, role, subscription, - accountCount: _count.Account || 0, - country: Analytics?.country, - dailyApiRequests: Analytics?.dataProviderGhostfolioDailyRequests || 0, - lastActivity: Analytics?.updatedAt, - transactionCount: _count.Order || 0 + accountCount: _count.accounts || 0, + activityCount: _count.activities || 0, + country: analytics?.country, + dailyApiRequests: analytics?.dataProviderGhostfolioDailyRequests || 0, + lastActivity: analytics?.updatedAt }; } ); diff --git a/apps/api/src/app/admin/create-asset-profile.dto.ts b/apps/api/src/app/admin/create-asset-profile.dto.ts new file mode 100644 index 000000000..8041b0f0e --- /dev/null +++ b/apps/api/src/app/admin/create-asset-profile.dto.ts @@ -0,0 +1,92 @@ +import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code'; + +import { AssetClass, AssetSubClass, DataSource, Prisma } from '@prisma/client'; +import { + IsArray, + IsBoolean, + IsEnum, + IsObject, + IsOptional, + IsString, + IsUrl +} from 'class-validator'; + +export class CreateAssetProfileDto { + @IsEnum(AssetClass, { each: true }) + @IsOptional() + assetClass?: AssetClass; + + @IsEnum(AssetSubClass, { each: true }) + @IsOptional() + assetSubClass?: AssetSubClass; + + @IsOptional() + @IsString() + comment?: string; + + @IsArray() + @IsOptional() + countries?: Prisma.InputJsonArray; + + @IsCurrencyCode() + currency: string; + + @IsOptional() + @IsString() + cusip?: string; + + @IsEnum(DataSource) + dataSource: DataSource; + + @IsOptional() + @IsString() + figi?: string; + + @IsOptional() + @IsString() + figiComposite?: string; + + @IsOptional() + @IsString() + figiShareClass?: string; + + @IsArray() + @IsOptional() + holdings?: Prisma.InputJsonArray; + + @IsBoolean() + @IsOptional() + isActive?: boolean; + + @IsOptional() + @IsString() + isin?: string; + + @IsOptional() + @IsString() + name?: string; + + @IsObject() + @IsOptional() + scraperConfiguration?: Prisma.InputJsonObject; + + @IsArray() + @IsOptional() + sectors?: Prisma.InputJsonArray; + + @IsString() + symbol: string; + + @IsObject() + @IsOptional() + symbolMapping?: { + [dataProvider: string]: string; + }; + + @IsOptional() + @IsUrl({ + protocols: ['https'], + require_protocol: true + }) + url?: string; +} diff --git a/apps/api/src/app/admin/update-asset-profile.dto.ts b/apps/api/src/app/admin/update-asset-profile.dto.ts index 8c9ae220b..5056dccdb 100644 --- a/apps/api/src/app/admin/update-asset-profile.dto.ts +++ b/apps/api/src/app/admin/update-asset-profile.dto.ts @@ -1,8 +1,9 @@ import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code'; -import { AssetClass, AssetSubClass, Prisma } from '@prisma/client'; +import { AssetClass, AssetSubClass, DataSource, Prisma } from '@prisma/client'; import { IsArray, + IsBoolean, IsEnum, IsObject, IsOptional, @@ -19,8 +20,8 @@ export class UpdateAssetProfileDto { @IsOptional() assetSubClass?: AssetSubClass; - @IsString() @IsOptional() + @IsString() comment?: string; @IsArray() @@ -31,8 +32,16 @@ export class UpdateAssetProfileDto { @IsOptional() currency?: string; - @IsString() + @IsEnum(DataSource) @IsOptional() + dataSource?: DataSource; + + @IsBoolean() + @IsOptional() + isActive?: boolean; + + @IsOptional() + @IsString() name?: string; @IsObject() @@ -43,6 +52,10 @@ export class UpdateAssetProfileDto { @IsOptional() sectors?: Prisma.InputJsonArray; + @IsOptional() + @IsString() + symbol?: string; + @IsObject() @IsOptional() symbolMapping?: { diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 7ac2c5915..1c48b9702 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -1,20 +1,21 @@ import { EventsModule } from '@ghostfolio/api/events/events.module'; +import { HtmlTemplateMiddleware } from '@ghostfolio/api/middlewares/html-template.middleware'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; -import { CronService } from '@ghostfolio/api/services/cron.service'; +import { CronModule } from '@ghostfolio/api/services/cron/cron.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; import { PortfolioSnapshotQueueModule } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.module'; -import { TwitterBotModule } from '@ghostfolio/api/services/twitter-bot/twitter-bot.module'; import { DEFAULT_LANGUAGE_CODE, SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config'; import { BullModule } from '@nestjs/bull'; -import { Module } from '@nestjs/common'; +import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { ScheduleModule } from '@nestjs/schedule'; @@ -29,12 +30,17 @@ import { AppController } from './app.controller'; import { AssetModule } from './asset/asset.module'; import { AuthDeviceModule } from './auth-device/auth-device.module'; import { AuthModule } from './auth/auth.module'; -import { BenchmarkModule } from './benchmark/benchmark.module'; import { CacheModule } from './cache/cache.module'; +import { AiModule } from './endpoints/ai/ai.module'; import { ApiKeysModule } from './endpoints/api-keys/api-keys.module'; +import { AssetsModule } from './endpoints/assets/assets.module'; +import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module'; import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module'; import { MarketDataModule } from './endpoints/market-data/market-data.module'; import { PublicModule } from './endpoints/public/public.module'; +import { SitemapModule } from './endpoints/sitemap/sitemap.module'; +import { TagsModule } from './endpoints/tags/tags.module'; +import { WatchlistModule } from './endpoints/watchlist/watchlist.module'; import { ExchangeRateModule } from './exchange-rate/exchange-rate.module'; import { ExportModule } from './export/export.module'; import { HealthModule } from './health/health.module'; @@ -45,10 +51,8 @@ import { OrderModule } from './order/order.module'; import { PlatformModule } from './platform/platform.module'; import { PortfolioModule } from './portfolio/portfolio.module'; import { RedisCacheModule } from './redis-cache/redis-cache.module'; -import { SitemapModule } from './sitemap/sitemap.module'; import { SubscriptionModule } from './subscription/subscription.module'; import { SymbolModule } from './symbol/symbol.module'; -import { TagModule } from './tag/tag.module'; import { UserModule } from './user/user.module'; @Module({ @@ -57,11 +61,13 @@ import { UserModule } from './user/user.module'; AdminModule, AccessModule, AccountModule, + AiModule, ApiKeysModule, AssetModule, + AssetsModule, AuthDeviceModule, AuthModule, - BenchmarkModule, + BenchmarksModule, BullModule.forRoot({ redis: { db: parseInt(process.env.REDIS_DB ?? '0', 10), @@ -73,6 +79,7 @@ import { UserModule } from './user/user.module'; CacheModule, ConfigModule.forRoot(), ConfigurationModule, + CronModule, DataGatheringModule, DataProviderModule, EventEmitterModule.forRoot(), @@ -96,7 +103,7 @@ import { UserModule } from './user/user.module'; RedisCacheModule, ScheduleModule.forRoot(), ServeStaticModule.forRoot({ - exclude: ['/api*', '/sitemap.xml'], + exclude: ['/.well-known/*wildcard', '/api/*wildcard', '/sitemap.xml'], rootPath: join(__dirname, '..', 'client'), serveStaticOptions: { setHeaders: (res) => { @@ -119,13 +126,21 @@ import { UserModule } from './user/user.module'; } } }), + ServeStaticModule.forRoot({ + rootPath: join(__dirname, '..', 'client', '.well-known'), + serveRoot: '/.well-known' + }), SitemapModule, SubscriptionModule, SymbolModule, - TagModule, - TwitterBotModule, - UserModule + TagsModule, + UserModule, + WatchlistModule ], - providers: [CronService] + providers: [I18nService] }) -export class AppModule {} +export class AppModule implements NestModule { + public configure(consumer: MiddlewareConsumer) { + consumer.apply(HtmlTemplateMiddleware).forRoutes('*wildcard'); + } +} diff --git a/apps/api/src/app/auth/api-key.strategy.ts b/apps/api/src/app/auth/api-key.strategy.ts index ace7fb245..f9937aaa7 100644 --- a/apps/api/src/app/auth/api-key.strategy.ts +++ b/apps/api/src/app/auth/api-key.strategy.ts @@ -21,37 +21,31 @@ export class ApiKeyStrategy extends PassportStrategy( private readonly prismaService: PrismaService, private readonly userService: UserService ) { - super( - { header: HEADER_KEY_TOKEN, prefix: 'Api-Key ' }, - true, - async (apiKey: string, done: (error: any, user?: any) => void) => { - try { - const user = await this.validateApiKey(apiKey); - - if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - if (hasRole(user, 'INACTIVE')) { - throw new HttpException( - getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), - StatusCodes.TOO_MANY_REQUESTS - ); - } + super({ header: HEADER_KEY_TOKEN, prefix: 'Api-Key ' }, false); + } - await this.prismaService.analytics.upsert({ - create: { User: { connect: { id: user.id } } }, - update: { - activityCount: { increment: 1 }, - lastRequestAt: new Date() - }, - where: { userId: user.id } - }); - } + public async validate(apiKey: string) { + const user = await this.validateApiKey(apiKey); - done(null, user); - } catch (error) { - done(error, null); - } + if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { + if (hasRole(user, 'INACTIVE')) { + throw new HttpException( + getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), + StatusCodes.TOO_MANY_REQUESTS + ); } - ); + + await this.prismaService.analytics.upsert({ + create: { user: { connect: { id: user.id } } }, + update: { + activityCount: { increment: 1 }, + lastRequestAt: new Date() + }, + where: { userId: user.id } + }); + } + + return user; } private async validateApiKey(apiKey: string) { diff --git a/apps/api/src/app/auth/auth.controller.ts b/apps/api/src/app/auth/auth.controller.ts index a91525269..13d8e37f6 100644 --- a/apps/api/src/app/auth/auth.controller.ts +++ b/apps/api/src/app/auth/auth.controller.ts @@ -133,17 +133,19 @@ export class AuthController { return this.webAuthService.verifyAttestation(body.credential); } - @Post('webauthn/generate-assertion-options') - public async generateAssertionOptions(@Body() body: { deviceId: string }) { - return this.webAuthService.generateAssertionOptions(body.deviceId); + @Post('webauthn/generate-authentication-options') + public async generateAuthenticationOptions( + @Body() body: { deviceId: string } + ) { + return this.webAuthService.generateAuthenticationOptions(body.deviceId); } - @Post('webauthn/verify-assertion') - public async verifyAssertion( + @Post('webauthn/verify-authentication') + public async verifyAuthentication( @Body() body: { deviceId: string; credential: AssertionCredentialJSON } ) { try { - const authToken = await this.webAuthService.verifyAssertion( + const authToken = await this.webAuthService.verifyAuthentication( body.deviceId, body.credential ); diff --git a/apps/api/src/app/auth/auth.service.ts b/apps/api/src/app/auth/auth.service.ts index edfb22b6f..ceff492a0 100644 --- a/apps/api/src/app/auth/auth.service.ts +++ b/apps/api/src/app/auth/auth.service.ts @@ -20,10 +20,10 @@ export class AuthService { public async validateAnonymousLogin(accessToken: string): Promise { return new Promise(async (resolve, reject) => { try { - const hashedAccessToken = this.userService.createAccessToken( - accessToken, - this.configurationService.get('ACCESS_TOKEN_SALT') - ); + const hashedAccessToken = this.userService.createAccessToken({ + password: accessToken, + salt: this.configurationService.get('ACCESS_TOKEN_SALT') + }); const [user] = await this.userService.users({ where: { accessToken: hashedAccessToken } diff --git a/apps/api/src/app/auth/jwt.strategy.ts b/apps/api/src/app/auth/jwt.strategy.ts index 7a3fb224b..c70e8fb60 100644 --- a/apps/api/src/app/auth/jwt.strategy.ts +++ b/apps/api/src/app/auth/jwt.strategy.ts @@ -1,7 +1,11 @@ import { UserService } from '@ghostfolio/api/app/user/user.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; -import { HEADER_KEY_TIMEZONE } from '@ghostfolio/common/config'; +import { + DEFAULT_CURRENCY, + DEFAULT_LANGUAGE_CODE, + HEADER_KEY_TIMEZONE +} from '@ghostfolio/common/config'; import { hasRole } from '@ghostfolio/common/permissions'; import { HttpException, Injectable } from '@nestjs/common'; @@ -42,7 +46,7 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { countriesAndTimezones.getCountryForTimezone(timezone)?.id; await this.prismaService.analytics.upsert({ - create: { country, User: { connect: { id: user.id } } }, + create: { country, user: { connect: { id: user.id } } }, update: { country, activityCount: { increment: 1 }, @@ -52,6 +56,14 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { }); } + if (!user.settings.settings.baseCurrency) { + user.settings.settings.baseCurrency = DEFAULT_CURRENCY; + } + + if (!user.settings.settings.language) { + user.settings.settings.language = DEFAULT_LANGUAGE_CODE; + } + return user; } else { throw new HttpException( diff --git a/apps/api/src/app/auth/web-auth.service.ts b/apps/api/src/app/auth/web-auth.service.ts index 2f8dd1018..d14ef7798 100644 --- a/apps/api/src/app/auth/web-auth.service.ts +++ b/apps/api/src/app/auth/web-auth.service.ts @@ -24,6 +24,8 @@ import { verifyRegistrationResponse, VerifyRegistrationResponseOpts } from '@simplewebauthn/server'; +import { isoBase64URL, isoUint8Array } from '@simplewebauthn/server/helpers'; +import ms from 'ms'; import { AssertionCredentialJSON, @@ -40,43 +42,42 @@ export class WebAuthService { @Inject(REQUEST) private readonly request: RequestWithUser ) {} - get rpID() { - return new URL(this.configurationService.get('ROOT_URL')).hostname; + private get expectedOrigin() { + return this.configurationService.get('ROOT_URL'); } - get expectedOrigin() { - return this.configurationService.get('ROOT_URL'); + private get rpID() { + return new URL(this.configurationService.get('ROOT_URL')).hostname; } public async generateRegistrationOptions() { const user = this.request.user; const opts: GenerateRegistrationOptionsOpts = { - rpName: 'Ghostfolio', - rpID: this.rpID, - userID: user.id, - userName: '', - timeout: 60000, - attestationType: 'indirect', authenticatorSelection: { authenticatorAttachment: 'platform', - requireResidentKey: false, - userVerification: 'required' - } + residentKey: 'required', + userVerification: 'preferred' + }, + rpID: this.rpID, + rpName: 'Ghostfolio', + timeout: ms('60 seconds'), + userID: isoUint8Array.fromUTF8String(user.id), + userName: '' }; - const options = await generateRegistrationOptions(opts); + const registrationOptions = await generateRegistrationOptions(opts); await this.userService.updateUser({ data: { - authChallenge: options.challenge + authChallenge: registrationOptions.challenge }, where: { id: user.id } }); - return options; + return registrationOptions; } public async verifyAttestation( @@ -84,13 +85,14 @@ export class WebAuthService { ): Promise { const user = this.request.user; const expectedChallenge = user.authChallenge; - let verification: VerifiedRegistrationResponse; + try { const opts: VerifyRegistrationResponseOpts = { expectedChallenge, expectedOrigin: this.expectedOrigin, expectedRPID: this.rpID, + requireUserVerification: false, response: { clientExtensionResults: credential.clientExtensionResults, id: credential.id, @@ -99,6 +101,7 @@ export class WebAuthService { type: 'public-key' } }; + verification = await verifyRegistrationResponse(opts); } catch (error) { Logger.error(error, 'WebAuthService'); @@ -111,11 +114,17 @@ export class WebAuthService { where: { userId: user.id } }); if (registrationInfo && verified) { - const { counter, credentialID, credentialPublicKey } = registrationInfo; + const { + credential: { + counter, + id: credentialId, + publicKey: credentialPublicKey + } + } = registrationInfo; - let existingDevice = devices.find( - (device) => device.credentialId === credentialID - ); + let existingDevice = devices.find((device) => { + return isoBase64URL.fromBuffer(device.credentialId) === credentialId; + }); if (!existingDevice) { /** @@ -123,9 +132,9 @@ export class WebAuthService { */ existingDevice = await this.deviceService.createAuthDevice({ counter, - credentialId: Buffer.from(credentialID), + credentialId: Buffer.from(credentialId), credentialPublicKey: Buffer.from(credentialPublicKey), - User: { connect: { id: user.id } } + user: { connect: { id: user.id } } }); } @@ -138,7 +147,7 @@ export class WebAuthService { throw new InternalServerErrorException('An unknown error occurred'); } - public async generateAssertionOptions(deviceId: string) { + public async generateAuthenticationOptions(deviceId: string) { const device = await this.deviceService.authDevice({ id: deviceId }); if (!device) { @@ -146,33 +155,27 @@ export class WebAuthService { } const opts: GenerateAuthenticationOptionsOpts = { - allowCredentials: [ - { - id: device.credentialId, - transports: ['internal'], - type: 'public-key' - } - ], + allowCredentials: [], rpID: this.rpID, - timeout: 60000, + timeout: ms('60 seconds'), userVerification: 'preferred' }; - const options = await generateAuthenticationOptions(opts); + const authenticationOptions = await generateAuthenticationOptions(opts); await this.userService.updateUser({ data: { - authChallenge: options.challenge + authChallenge: authenticationOptions.challenge }, where: { id: device.userId } }); - return options; + return authenticationOptions; } - public async verifyAssertion( + public async verifyAuthentication( deviceId: string, credential: AssertionCredentialJSON ) { @@ -185,16 +188,18 @@ export class WebAuthService { const user = await this.userService.user({ id: device.userId }); let verification: VerifiedAuthenticationResponse; + try { const opts: VerifyAuthenticationResponseOpts = { - authenticator: { - credentialID: device.credentialId, - credentialPublicKey: device.credentialPublicKey, - counter: device.counter + credential: { + counter: device.counter, + id: isoBase64URL.fromBuffer(device.credentialId), + publicKey: device.credentialPublicKey }, expectedChallenge: `${user.authChallenge}`, expectedOrigin: this.expectedOrigin, expectedRPID: this.rpID, + requireUserVerification: false, response: { clientExtensionResults: credential.clientExtensionResults, id: credential.id, @@ -203,13 +208,14 @@ export class WebAuthService { type: 'public-key' } }; + verification = await verifyAuthenticationResponse(opts); } catch (error) { Logger.error(error, 'WebAuthService'); throw new InternalServerErrorException({ error: error.message }); } - const { verified, authenticationInfo } = verification; + const { authenticationInfo, verified } = verification; if (verified) { device.counter = authenticationInfo.newCounter; diff --git a/apps/api/src/app/endpoints/ai/ai.controller.ts b/apps/api/src/app/endpoints/ai/ai.controller.ts new file mode 100644 index 000000000..b1607b53b --- /dev/null +++ b/apps/api/src/app/endpoints/ai/ai.controller.ts @@ -0,0 +1,59 @@ +import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; +import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; +import { ApiService } from '@ghostfolio/api/services/api/api.service'; +import { AiPromptResponse } from '@ghostfolio/common/interfaces'; +import { permissions } from '@ghostfolio/common/permissions'; +import type { AiPromptMode, RequestWithUser } from '@ghostfolio/common/types'; + +import { + Controller, + Get, + Inject, + Param, + Query, + UseGuards +} from '@nestjs/common'; +import { REQUEST } from '@nestjs/core'; +import { AuthGuard } from '@nestjs/passport'; + +import { AiService } from './ai.service'; + +@Controller('ai') +export class AiController { + public constructor( + private readonly aiService: AiService, + private readonly apiService: ApiService, + @Inject(REQUEST) private readonly request: RequestWithUser + ) {} + + @Get('prompt/:mode') + @HasPermission(permissions.readAiPrompt) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async getPrompt( + @Param('mode') mode: AiPromptMode, + @Query('accounts') filterByAccounts?: string, + @Query('assetClasses') filterByAssetClasses?: string, + @Query('dataSource') filterByDataSource?: string, + @Query('symbol') filterBySymbol?: string, + @Query('tags') filterByTags?: string + ): Promise { + const filters = this.apiService.buildFiltersFromQueryParams({ + filterByAccounts, + filterByAssetClasses, + filterByDataSource, + filterBySymbol, + filterByTags + }); + + const prompt = await this.aiService.getPrompt({ + filters, + mode, + impersonationId: undefined, + languageCode: this.request.user.settings.settings.language, + userCurrency: this.request.user.settings.settings.baseCurrency, + userId: this.request.user.id + }); + + return { prompt }; + } +} diff --git a/apps/api/src/app/endpoints/ai/ai.module.ts b/apps/api/src/app/endpoints/ai/ai.module.ts new file mode 100644 index 000000000..8a441fde7 --- /dev/null +++ b/apps/api/src/app/endpoints/ai/ai.module.ts @@ -0,0 +1,59 @@ +import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; +import { AccountService } from '@ghostfolio/api/app/account/account.service'; +import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service'; +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { ApiModule } from '@ghostfolio/api/services/api/api.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; +import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; +import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; +import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { PortfolioSnapshotQueueModule } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.module'; +import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; + +import { Module } from '@nestjs/common'; + +import { AiController } from './ai.controller'; +import { AiService } from './ai.service'; + +@Module({ + controllers: [AiController], + imports: [ + ApiModule, + BenchmarkModule, + ConfigurationModule, + DataProviderModule, + ExchangeRateDataModule, + I18nModule, + ImpersonationModule, + MarketDataModule, + OrderModule, + PortfolioSnapshotQueueModule, + PrismaModule, + PropertyModule, + RedisCacheModule, + SymbolProfileModule, + UserModule + ], + providers: [ + AccountBalanceService, + AccountService, + AiService, + CurrentRateService, + MarketDataService, + PortfolioCalculatorFactory, + PortfolioService, + RulesService + ] +}) +export class AiModule {} diff --git a/apps/api/src/app/endpoints/ai/ai.service.ts b/apps/api/src/app/endpoints/ai/ai.service.ts new file mode 100644 index 000000000..b479d74ea --- /dev/null +++ b/apps/api/src/app/endpoints/ai/ai.service.ts @@ -0,0 +1,100 @@ +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { + PROPERTY_API_KEY_OPENROUTER, + PROPERTY_OPENROUTER_MODEL +} from '@ghostfolio/common/config'; +import { Filter } from '@ghostfolio/common/interfaces'; +import type { AiPromptMode } from '@ghostfolio/common/types'; + +import { Injectable } from '@nestjs/common'; +import { createOpenRouter } from '@openrouter/ai-sdk-provider'; +import { generateText } from 'ai'; + +@Injectable() +export class AiService { + public constructor( + private readonly portfolioService: PortfolioService, + private readonly propertyService: PropertyService + ) {} + + public async generateText({ prompt }: { prompt: string }) { + const openRouterApiKey = await this.propertyService.getByKey( + PROPERTY_API_KEY_OPENROUTER + ); + + const openRouterModel = await this.propertyService.getByKey( + PROPERTY_OPENROUTER_MODEL + ); + + const openRouterService = createOpenRouter({ + apiKey: openRouterApiKey + }); + + return generateText({ + prompt, + model: openRouterService.chat(openRouterModel) + }); + } + + public async getPrompt({ + filters, + impersonationId, + languageCode, + mode, + userCurrency, + userId + }: { + filters?: Filter[]; + impersonationId: string; + languageCode: string; + mode: AiPromptMode; + userCurrency: string; + userId: string; + }) { + const { holdings } = await this.portfolioService.getDetails({ + filters, + impersonationId, + userId + }); + + const holdingsTable = [ + '| Name | Symbol | Currency | Asset Class | Asset Sub Class | Allocation in Percentage |', + '| --- | --- | --- | --- | --- | --- |', + ...Object.values(holdings) + .sort((a, b) => { + return b.allocationInPercentage - a.allocationInPercentage; + }) + .map( + ({ + allocationInPercentage, + assetClass, + assetSubClass, + currency, + name, + symbol + }) => { + return `| ${name} | ${symbol} | ${currency} | ${assetClass} | ${assetSubClass} | ${(allocationInPercentage * 100).toFixed(3)}% |`; + } + ) + ]; + + if (mode === 'portfolio') { + return holdingsTable.join('\n'); + } + + return [ + `You are a neutral financial assistant. Please analyze the following investment portfolio (base currency being ${userCurrency}) in simple words.`, + ...holdingsTable, + 'Structure your answer with these sections:', + 'Overview: Briefly summarize the portfolio’s composition and allocation rationale.', + 'Risk Assessment: Identify potential risks, including market volatility, concentration, and sectoral imbalances.', + 'Advantages: Highlight strengths, focusing on growth potential, diversification, or other benefits.', + 'Disadvantages: Point out weaknesses, such as overexposure or lack of defensive assets.', + 'Target Group: Discuss who this portfolio might suit (e.g., risk tolerance, investment goals, life stages, and experience levels).', + 'Optimization Ideas: Offer ideas to complement the portfolio, ensuring they are constructive and neutral in tone.', + 'Conclusion: Provide a concise summary highlighting key insights.', + `Provide your answer in the following language: ${languageCode}.` + ].join('\n'); + } +} diff --git a/apps/api/src/app/endpoints/assets/assets.controller.ts b/apps/api/src/app/endpoints/assets/assets.controller.ts new file mode 100644 index 000000000..1735cc594 --- /dev/null +++ b/apps/api/src/app/endpoints/assets/assets.controller.ts @@ -0,0 +1,46 @@ +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { interpolate } from '@ghostfolio/common/helper'; + +import { + Controller, + Get, + Param, + Res, + Version, + VERSION_NEUTRAL +} from '@nestjs/common'; +import { Response } from 'express'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +@Controller('assets') +export class AssetsController { + private webManifest = ''; + + public constructor( + public readonly configurationService: ConfigurationService + ) { + try { + this.webManifest = readFileSync( + join(__dirname, 'assets', 'site.webmanifest'), + 'utf8' + ); + } catch {} + } + + @Get('/:languageCode/site.webmanifest') + @Version(VERSION_NEUTRAL) + public getWebManifest( + @Param('languageCode') languageCode: string, + @Res() response: Response + ): void { + const rootUrl = this.configurationService.get('ROOT_URL'); + const webManifest = interpolate(this.webManifest, { + languageCode, + rootUrl + }); + + response.setHeader('Content-Type', 'application/json'); + response.send(webManifest); + } +} diff --git a/apps/api/src/app/endpoints/assets/assets.module.ts b/apps/api/src/app/endpoints/assets/assets.module.ts new file mode 100644 index 000000000..51d330e50 --- /dev/null +++ b/apps/api/src/app/endpoints/assets/assets.module.ts @@ -0,0 +1,11 @@ +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; + +import { Module } from '@nestjs/common'; + +import { AssetsController } from './assets.controller'; + +@Module({ + controllers: [AssetsController], + providers: [ConfigurationService] +}) +export class AssetsModule {} diff --git a/apps/api/src/app/benchmark/benchmark.controller.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.controller.ts similarity index 72% rename from apps/api/src/app/benchmark/benchmark.controller.ts rename to apps/api/src/app/endpoints/benchmarks/benchmarks.controller.ts index 66c268b9b..69383a30d 100644 --- a/apps/api/src/app/benchmark/benchmark.controller.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.controller.ts @@ -2,7 +2,10 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; +import { ApiService } from '@ghostfolio/api/services/api/api.service'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; +import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import type { AssetProfileIdentifier, BenchmarkMarketDataDetails, @@ -16,6 +19,7 @@ import { Controller, Delete, Get, + Headers, HttpException, Inject, Param, @@ -29,12 +33,14 @@ import { AuthGuard } from '@nestjs/passport'; import { DataSource } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { BenchmarkService } from './benchmark.service'; +import { BenchmarksService } from './benchmarks.service'; -@Controller('benchmark') -export class BenchmarkController { +@Controller('benchmarks') +export class BenchmarksController { public constructor( + private readonly apiService: ApiService, private readonly benchmarkService: BenchmarkService, + private readonly benchmarksService: BenchmarksService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -108,23 +114,43 @@ export class BenchmarkController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getBenchmarkMarketDataForUser( + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('dataSource') dataSource: DataSource, @Param('startDateString') startDateString: string, @Param('symbol') symbol: string, - @Query('range') dateRange: DateRange = 'max' + @Query('range') dateRange: DateRange = 'max', + @Query('accounts') filterByAccounts?: string, + @Query('assetClasses') filterByAssetClasses?: string, + @Query('dataSource') filterByDataSource?: string, + @Query('symbol') filterBySymbol?: string, + @Query('tags') filterByTags?: string, + @Query('withExcludedAccounts') withExcludedAccountsParam = 'false' ): Promise { const { endDate, startDate } = getIntervalFromDateRange( dateRange, new Date(startDateString) ); - const userCurrency = this.request.user.Settings.settings.baseCurrency; - return this.benchmarkService.getMarketDataForUser({ + const filters = this.apiService.buildFiltersFromQueryParams({ + filterByAccounts, + filterByAssetClasses, + filterByDataSource, + filterBySymbol, + filterByTags + }); + + const withExcludedAccounts = withExcludedAccountsParam === 'true'; + + return this.benchmarksService.getMarketDataForUser({ dataSource, + dateRange, endDate, + filters, + impersonationId, startDate, symbol, - userCurrency + withExcludedAccounts, + user: this.request.user }); } } diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts new file mode 100644 index 000000000..8bdf79035 --- /dev/null +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts @@ -0,0 +1,65 @@ +import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; +import { AccountService } from '@ghostfolio/api/app/account/account.service'; +import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service'; +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; +import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; +import { ApiModule } from '@ghostfolio/api/services/api/api.module'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; +import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; +import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; +import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { PortfolioSnapshotQueueModule } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.module'; +import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; + +import { Module } from '@nestjs/common'; + +import { BenchmarksController } from './benchmarks.controller'; +import { BenchmarksService } from './benchmarks.service'; + +@Module({ + controllers: [BenchmarksController], + imports: [ + ApiModule, + ConfigurationModule, + DataProviderModule, + ExchangeRateDataModule, + I18nModule, + ImpersonationModule, + MarketDataModule, + OrderModule, + PortfolioSnapshotQueueModule, + PrismaModule, + PropertyModule, + RedisCacheModule, + SymbolModule, + SymbolProfileModule, + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule, + UserModule + ], + providers: [ + AccountBalanceService, + AccountService, + BenchmarkService, + BenchmarksService, + CurrentRateService, + MarketDataService, + PortfolioCalculatorFactory, + PortfolioService, + RulesService + ] +}) +export class BenchmarksModule {} diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts new file mode 100644 index 000000000..aa53564b7 --- /dev/null +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts @@ -0,0 +1,163 @@ +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; +import { + AssetProfileIdentifier, + BenchmarkMarketDataDetails, + Filter +} from '@ghostfolio/common/interfaces'; +import { DateRange, UserWithSettings } from '@ghostfolio/common/types'; + +import { Injectable, Logger } from '@nestjs/common'; +import { format, isSameDay } from 'date-fns'; +import { isNumber } from 'lodash'; + +@Injectable() +export class BenchmarksService { + public constructor( + private readonly benchmarkService: BenchmarkService, + private readonly exchangeRateDataService: ExchangeRateDataService, + private readonly marketDataService: MarketDataService, + private readonly portfolioService: PortfolioService, + private readonly symbolService: SymbolService + ) {} + + public async getMarketDataForUser({ + dataSource, + dateRange, + endDate = new Date(), + filters, + impersonationId, + startDate, + symbol, + user, + withExcludedAccounts + }: { + dateRange: DateRange; + endDate?: Date; + filters?: Filter[]; + impersonationId: string; + startDate: Date; + user: UserWithSettings; + withExcludedAccounts?: boolean; + } & AssetProfileIdentifier): Promise { + const marketData: { date: string; value: number }[] = []; + const userCurrency = user.settings.settings.baseCurrency; + const userId = user.id; + + const { chart } = await this.portfolioService.getPerformance({ + dateRange, + filters, + impersonationId, + userId, + withExcludedAccounts + }); + + const [currentSymbolItem, marketDataItems] = await Promise.all([ + this.symbolService.get({ + dataGatheringItem: { + dataSource, + symbol + } + }), + this.marketDataService.marketDataItems({ + orderBy: { + date: 'asc' + }, + where: { + dataSource, + symbol, + date: { + in: chart.map(({ date }) => { + return resetHours(parseDate(date)); + }) + } + } + }) + ]); + + const exchangeRates = + await this.exchangeRateDataService.getExchangeRatesByCurrency({ + startDate, + currencies: [currentSymbolItem.currency], + targetCurrency: userCurrency + }); + + const exchangeRateAtStartDate = + exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ + format(startDate, DATE_FORMAT) + ]; + + const marketPriceAtStartDate = marketDataItems?.find(({ date }) => { + return isSameDay(date, startDate); + })?.marketPrice; + + if (!marketPriceAtStartDate) { + Logger.error( + `No historical market data has been found for ${symbol} (${dataSource}) at ${format( + startDate, + DATE_FORMAT + )}`, + 'BenchmarkService' + ); + + return { marketData }; + } + + for (const marketDataItem of marketDataItems) { + const exchangeRate = + exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ + format(marketDataItem.date, DATE_FORMAT) + ]; + + const exchangeRateFactor = + isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate) + ? exchangeRate / exchangeRateAtStartDate + : 1; + + marketData.push({ + date: format(marketDataItem.date, DATE_FORMAT), + value: + marketPriceAtStartDate === 0 + ? 0 + : this.benchmarkService.calculateChangeInPercentage( + marketPriceAtStartDate, + marketDataItem.marketPrice * exchangeRateFactor + ) * 100 + }); + } + + const includesEndDate = isSameDay( + parseDate(marketData.at(-1).date), + endDate + ); + + if (currentSymbolItem?.marketPrice && !includesEndDate) { + const exchangeRate = + exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ + format(endDate, DATE_FORMAT) + ]; + + const exchangeRateFactor = + isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate) + ? exchangeRate / exchangeRateAtStartDate + : 1; + + marketData.push({ + date: format(endDate, DATE_FORMAT), + value: + this.benchmarkService.calculateChangeInPercentage( + marketPriceAtStartDate, + currentSymbolItem.marketPrice * exchangeRateFactor + ) * 100 + }); + } + + return { + marketData + }; + } +} diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts index f3386f8a7..7cb2520bb 100644 --- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts +++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts @@ -2,6 +2,7 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { parseDate } from '@ghostfolio/common/helper'; import { + DataProviderGhostfolioAssetProfileResponse, DataProviderGhostfolioStatusResponse, DividendsResponse, HistoricalResponse, @@ -23,6 +24,7 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; +import { isISIN } from 'class-validator'; import { getReasonPhrase, StatusCodes } from 'http-status-codes'; import { GetDividendsDto } from './get-dividends.dto'; @@ -37,16 +39,12 @@ export class GhostfolioController { @Inject(REQUEST) private readonly request: RequestWithUser ) {} - /** - * @deprecated - */ - @Get('dividends/:symbol') + @Get('asset-profile/:symbol') @HasPermission(permissions.enableDataProviderGhostfolio) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getDividendsV1( - @Param('symbol') symbol: string, - @Query() query: GetDividendsDto - ): Promise { + @UseGuards(AuthGuard('api-key'), HasPermissionGuard) + public async getAssetProfile( + @Param('symbol') symbol: string + ): Promise { const maxDailyRequests = await this.ghostfolioService.getMaxDailyRequests(); if ( @@ -59,18 +57,15 @@ export class GhostfolioController { } try { - const dividends = await this.ghostfolioService.getDividends({ - symbol, - from: parseDate(query.from), - granularity: query.granularity, - to: parseDate(query.to) + const assetProfile = await this.ghostfolioService.getAssetProfile({ + symbol }); await this.ghostfolioService.incrementDailyRequests({ userId: this.request.user.id }); - return dividends; + return assetProfile; } catch { throw new HttpException( getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), @@ -119,48 +114,6 @@ export class GhostfolioController { } } - /** - * @deprecated - */ - @Get('historical/:symbol') - @HasPermission(permissions.enableDataProviderGhostfolio) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getHistoricalV1( - @Param('symbol') symbol: string, - @Query() query: GetHistoricalDto - ): Promise { - const maxDailyRequests = await this.ghostfolioService.getMaxDailyRequests(); - - if ( - this.request.user.dataProviderGhostfolioDailyRequests > maxDailyRequests - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), - StatusCodes.TOO_MANY_REQUESTS - ); - } - - try { - const historicalData = await this.ghostfolioService.getHistorical({ - symbol, - from: parseDate(query.from), - granularity: query.granularity, - to: parseDate(query.to) - }); - - await this.ghostfolioService.incrementDailyRequests({ - userId: this.request.user.id - }); - - return historicalData; - } catch { - throw new HttpException( - getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), - StatusCodes.INTERNAL_SERVER_ERROR - ); - } - } - @Get('historical/:symbol') @HasPermission(permissions.enableDataProviderGhostfolio) @UseGuards(AuthGuard('api-key'), HasPermissionGuard) @@ -201,47 +154,6 @@ export class GhostfolioController { } } - /** - * @deprecated - */ - @Get('lookup') - @HasPermission(permissions.enableDataProviderGhostfolio) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async lookupSymbolV1( - @Query('includeIndices') includeIndicesParam = 'false', - @Query('query') query = '' - ): Promise { - const includeIndices = includeIndicesParam === 'true'; - const maxDailyRequests = await this.ghostfolioService.getMaxDailyRequests(); - - if ( - this.request.user.dataProviderGhostfolioDailyRequests > maxDailyRequests - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), - StatusCodes.TOO_MANY_REQUESTS - ); - } - - try { - const result = await this.ghostfolioService.lookup({ - includeIndices, - query: query.toLowerCase() - }); - - await this.ghostfolioService.incrementDailyRequests({ - userId: this.request.user.id - }); - - return result; - } catch { - throw new HttpException( - getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), - StatusCodes.INTERNAL_SERVER_ERROR - ); - } - } - @Get('lookup') @HasPermission(permissions.enableDataProviderGhostfolio) @UseGuards(AuthGuard('api-key'), HasPermissionGuard) @@ -265,7 +177,9 @@ export class GhostfolioController { try { const result = await this.ghostfolioService.lookup({ includeIndices, - query: query.toLowerCase() + query: isISIN(query.toUpperCase()) + ? query.toUpperCase() + : query.toLowerCase() }); await this.ghostfolioService.incrementDailyRequests({ @@ -281,44 +195,6 @@ export class GhostfolioController { } } - /** - * @deprecated - */ - @Get('quotes') - @HasPermission(permissions.enableDataProviderGhostfolio) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getQuotesV1( - @Query() query: GetQuotesDto - ): Promise { - const maxDailyRequests = await this.ghostfolioService.getMaxDailyRequests(); - - if ( - this.request.user.dataProviderGhostfolioDailyRequests > maxDailyRequests - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), - StatusCodes.TOO_MANY_REQUESTS - ); - } - - try { - const quotes = await this.ghostfolioService.getQuotes({ - symbols: query.symbols - }); - - await this.ghostfolioService.incrementDailyRequests({ - userId: this.request.user.id - }); - - return quotes; - } catch { - throw new HttpException( - getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), - StatusCodes.INTERNAL_SERVER_ERROR - ); - } - } - @Get('quotes') @HasPermission(permissions.enableDataProviderGhostfolio) @UseGuards(AuthGuard('api-key'), HasPermissionGuard) @@ -355,16 +231,6 @@ export class GhostfolioController { } } - /** - * @deprecated - */ - @Get('status') - @HasPermission(permissions.enableDataProviderGhostfolio) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getStatusV1(): Promise { - return this.ghostfolioService.getStatus({ user: this.request.user }); - } - @Get('status') @HasPermission(permissions.enableDataProviderGhostfolio) @UseGuards(AuthGuard('api-key'), HasPermissionGuard) diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts index 78685a61b..f80633f87 100644 --- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts @@ -1,6 +1,8 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; +import { GhostfolioService as GhostfolioDataProviderService } from '@ghostfolio/api/services/data-provider/ghostfolio/ghostfolio.service'; import { + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -15,6 +17,7 @@ import { } from '@ghostfolio/common/config'; import { PROPERTY_DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER_MAX_REQUESTS } from '@ghostfolio/common/config'; import { + DataProviderGhostfolioAssetProfileResponse, DataProviderInfo, DividendsResponse, HistoricalResponse, @@ -25,7 +28,7 @@ import { import { UserWithSettings } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; -import { DataSource } from '@prisma/client'; +import { DataSource, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; @Injectable() @@ -37,6 +40,44 @@ export class GhostfolioService { private readonly propertyService: PropertyService ) {} + public async getAssetProfile({ + requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'), + symbol + }: GetAssetProfileParams) { + let result: DataProviderGhostfolioAssetProfileResponse = {}; + + try { + const promises: Promise>[] = []; + + for (const dataProviderService of this.getDataProviderServices()) { + promises.push( + dataProviderService + .getAssetProfile({ + requestTimeout, + symbol + }) + .then((assetProfile) => { + result = { + ...result, + ...assetProfile, + dataSource: DataSource.GHOSTFOLIO + }; + + return assetProfile; + }) + ); + } + + await Promise.all(promises); + + return result; + } catch (error) { + Logger.error(error, 'GhostfolioService'); + + throw error; + } + } + public async getDividends({ from, granularity, @@ -123,9 +164,9 @@ export class GhostfolioService { public async getMaxDailyRequests() { return parseInt( - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER_MAX_REQUESTS - )) as string) || '0', + )) || '0', 10 ); } @@ -277,6 +318,7 @@ export class GhostfolioService { }); results.items = filteredItems; + return results; } catch (error) { Logger.error(error, 'GhostfolioService'); @@ -286,10 +328,15 @@ export class GhostfolioService { } private getDataProviderInfo(): DataProviderInfo { + const ghostfolioDataProviderService = new GhostfolioDataProviderService( + this.configurationService, + this.propertyService + ); + return { + ...ghostfolioDataProviderService.getDataProviderInfo(), isPremium: false, - name: 'Ghostfolio Premium', - url: 'https://ghostfol.io' + name: 'Ghostfolio Premium' }; } diff --git a/apps/api/src/app/endpoints/market-data/market-data.controller.ts b/apps/api/src/app/endpoints/market-data/market-data.controller.ts index b4aef807a..4843536da 100644 --- a/apps/api/src/app/endpoints/market-data/market-data.controller.ts +++ b/apps/api/src/app/endpoints/market-data/market-data.controller.ts @@ -1,7 +1,20 @@ import { AdminService } from '@ghostfolio/api/app/admin/admin.service'; +import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; +import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; +import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; -import { MarketDataDetailsResponse } from '@ghostfolio/common/interfaces'; +import { + ghostfolioFearAndGreedIndexDataSourceCryptocurrencies, + ghostfolioFearAndGreedIndexDataSourceStocks, + ghostfolioFearAndGreedIndexSymbolCryptocurrencies, + ghostfolioFearAndGreedIndexSymbolStocks +} from '@ghostfolio/common/config'; +import { getCurrencyFromSymbol, isCurrency } from '@ghostfolio/common/helper'; +import { + MarketDataDetailsResponse, + MarketDataOfMarketsResponse +} from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { RequestWithUser } from '@ghostfolio/common/types'; @@ -13,6 +26,7 @@ import { Inject, Param, Post, + Query, UseGuards } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; @@ -29,9 +43,48 @@ export class MarketDataController { private readonly adminService: AdminService, private readonly marketDataService: MarketDataService, @Inject(REQUEST) private readonly request: RequestWithUser, - private readonly symbolProfileService: SymbolProfileService + private readonly symbolProfileService: SymbolProfileService, + private readonly symbolService: SymbolService ) {} + @Get('markets') + @HasPermission(permissions.readMarketDataOfMarkets) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async getMarketDataOfMarkets( + @Query('includeHistoricalData') includeHistoricalData = 0 + ): Promise { + const [ + marketDataFearAndGreedIndexCryptocurrencies, + marketDataFearAndGreedIndexStocks + ] = await Promise.all([ + this.symbolService.get({ + includeHistoricalData, + dataGatheringItem: { + dataSource: ghostfolioFearAndGreedIndexDataSourceCryptocurrencies, + symbol: ghostfolioFearAndGreedIndexSymbolCryptocurrencies + } + }), + this.symbolService.get({ + includeHistoricalData, + dataGatheringItem: { + dataSource: ghostfolioFearAndGreedIndexDataSourceStocks, + symbol: ghostfolioFearAndGreedIndexSymbolStocks + } + }) + ]); + + return { + fearAndGreedIndex: { + CRYPTOCURRENCIES: { + ...marketDataFearAndGreedIndexCryptocurrencies + }, + STOCKS: { + ...marketDataFearAndGreedIndexStocks + } + } + }; + } + @Get(':dataSource/:symbol') @UseGuards(AuthGuard('jwt')) public async getMarketDataBySymbol( @@ -42,7 +95,7 @@ export class MarketDataController { { dataSource, symbol } ]); - if (!assetProfile) { + if (!assetProfile && !isCurrency(getCurrencyFromSymbol(symbol))) { throw new HttpException( getReasonPhrase(StatusCodes.NOT_FOUND), StatusCodes.NOT_FOUND @@ -55,7 +108,7 @@ export class MarketDataController { ); const canReadOwnAssetProfile = - assetProfile.userId === this.request.user.id && + assetProfile?.userId === this.request.user.id && hasPermission( this.request.user.permissions, permissions.readMarketDataOfOwnAssetProfile @@ -84,7 +137,7 @@ export class MarketDataController { { dataSource, symbol } ]); - if (!assetProfile) { + if (!assetProfile && !isCurrency(getCurrencyFromSymbol(symbol))) { throw new HttpException( getReasonPhrase(StatusCodes.NOT_FOUND), StatusCodes.NOT_FOUND @@ -102,7 +155,7 @@ export class MarketDataController { ); const canUpsertOwnAssetProfile = - assetProfile.userId === this.request.user.id && + assetProfile?.userId === this.request.user.id && hasPermission( this.request.user.permissions, permissions.createMarketDataOfOwnAssetProfile diff --git a/apps/api/src/app/endpoints/market-data/market-data.module.ts b/apps/api/src/app/endpoints/market-data/market-data.module.ts index 2050889fd..a8b355de3 100644 --- a/apps/api/src/app/endpoints/market-data/market-data.module.ts +++ b/apps/api/src/app/endpoints/market-data/market-data.module.ts @@ -1,4 +1,5 @@ import { AdminModule } from '@ghostfolio/api/app/admin/admin.module'; +import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; import { MarketDataModule as MarketDataServiceModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; @@ -8,6 +9,11 @@ import { MarketDataController } from './market-data.controller'; @Module({ controllers: [MarketDataController], - imports: [AdminModule, MarketDataServiceModule, SymbolProfileModule] + imports: [ + AdminModule, + MarketDataServiceModule, + SymbolModule, + SymbolProfileModule + ] }) export class MarketDataModule {} diff --git a/apps/api/src/app/endpoints/public/public.controller.ts b/apps/api/src/app/endpoints/public/public.controller.ts index 7488e4201..0175b6ce8 100644 --- a/apps/api/src/app/endpoints/public/public.controller.ts +++ b/apps/api/src/app/endpoints/public/public.controller.ts @@ -57,7 +57,7 @@ export class PublicController { } const [ - { holdings, markets }, + { createdAt, holdings, markets }, { performance: performance1d }, { performance: performanceMax }, { performance: performanceYtd } @@ -81,6 +81,7 @@ export class PublicController { }); const publicPortfolioResponse: PublicPortfolioResponse = { + createdAt, hasDetails, markets, alias: access.alias, @@ -107,7 +108,7 @@ export class PublicController { this.exchangeRateDataService.toCurrency( quantity * marketPrice, currency, - this.request.user?.Settings?.settings.baseCurrency ?? + this.request.user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY ) ); diff --git a/apps/api/src/app/endpoints/public/public.module.ts b/apps/api/src/app/endpoints/public/public.module.ts index 9b43522c1..19e281dde 100644 --- a/apps/api/src/app/endpoints/public/public.module.ts +++ b/apps/api/src/app/endpoints/public/public.module.ts @@ -9,8 +9,10 @@ import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -25,8 +27,10 @@ import { PublicController } from './public.controller'; controllers: [PublicController], imports: [ AccessModule, + BenchmarkModule, DataProviderModule, ExchangeRateDataModule, + I18nModule, ImpersonationModule, MarketDataModule, OrderModule, diff --git a/apps/api/src/app/endpoints/sitemap/sitemap.controller.ts b/apps/api/src/app/endpoints/sitemap/sitemap.controller.ts new file mode 100644 index 000000000..f10f0bfd8 --- /dev/null +++ b/apps/api/src/app/endpoints/sitemap/sitemap.controller.ts @@ -0,0 +1,51 @@ +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { + DATE_FORMAT, + getYesterday, + interpolate +} from '@ghostfolio/common/helper'; + +import { Controller, Get, Res, VERSION_NEUTRAL, Version } from '@nestjs/common'; +import { format } from 'date-fns'; +import { Response } from 'express'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +import { SitemapService } from './sitemap.service'; + +@Controller('sitemap.xml') +export class SitemapController { + public sitemapXml = ''; + + public constructor( + private readonly configurationService: ConfigurationService, + private readonly sitemapService: SitemapService + ) { + try { + this.sitemapXml = readFileSync( + join(__dirname, 'assets', 'sitemap.xml'), + 'utf8' + ); + } catch {} + } + + @Get() + @Version(VERSION_NEUTRAL) + public getSitemapXml(@Res() response: Response) { + const currentDate = format(getYesterday(), DATE_FORMAT); + + response.setHeader('content-type', 'application/xml'); + response.send( + interpolate(this.sitemapXml, { + personalFinanceTools: this.configurationService.get( + 'ENABLE_FEATURE_SUBSCRIPTION' + ) + ? this.sitemapService.getPersonalFinanceTools({ currentDate }) + : '', + publicRoutes: this.sitemapService.getPublicRoutes({ + currentDate + }) + }) + ); + } +} diff --git a/apps/api/src/app/sitemap/sitemap.module.ts b/apps/api/src/app/endpoints/sitemap/sitemap.module.ts similarity index 58% rename from apps/api/src/app/sitemap/sitemap.module.ts rename to apps/api/src/app/endpoints/sitemap/sitemap.module.ts index d1059d408..73b5d78b0 100644 --- a/apps/api/src/app/sitemap/sitemap.module.ts +++ b/apps/api/src/app/endpoints/sitemap/sitemap.module.ts @@ -1,11 +1,14 @@ import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { Module } from '@nestjs/common'; import { SitemapController } from './sitemap.controller'; +import { SitemapService } from './sitemap.service'; @Module({ controllers: [SitemapController], - imports: [ConfigurationModule] + imports: [ConfigurationModule, I18nModule], + providers: [SitemapService] }) export class SitemapModule {} diff --git a/apps/api/src/app/endpoints/sitemap/sitemap.service.ts b/apps/api/src/app/endpoints/sitemap/sitemap.service.ts new file mode 100644 index 000000000..d18fe884a --- /dev/null +++ b/apps/api/src/app/endpoints/sitemap/sitemap.service.ts @@ -0,0 +1,116 @@ +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config'; +import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; +import { PublicRoute } from '@ghostfolio/common/routes/interfaces/public-route.interface'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class SitemapService { + private static readonly TRANSLATION_TAGGED_MESSAGE_REGEX = + /:.*@@(?[a-zA-Z0-9.]+):(?.+)/; + + public constructor( + private readonly configurationService: ConfigurationService, + private readonly i18nService: I18nService + ) {} + + public getPersonalFinanceTools({ currentDate }: { currentDate: string }) { + const rootUrl = this.configurationService.get('ROOT_URL'); + + return SUPPORTED_LANGUAGE_CODES.flatMap((languageCode) => { + return personalFinanceTools.map(({ alias, key }) => { + const route = + publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes + .product; + const params = { + currentDate, + languageCode, + rootUrl, + urlPostfix: alias ?? key + }; + + return this.createRouteSitemapUrl({ ...params, route }); + }); + }).join('\n'); + } + + public getPublicRoutes({ currentDate }: { currentDate: string }) { + const rootUrl = this.configurationService.get('ROOT_URL'); + + return SUPPORTED_LANGUAGE_CODES.flatMap((languageCode) => { + const params = { + currentDate, + languageCode, + rootUrl + }; + + return [ + this.createRouteSitemapUrl(params), + ...this.createSitemapUrls(params, publicRoutes) + ]; + }).join('\n'); + } + + private createRouteSitemapUrl({ + currentDate, + languageCode, + rootUrl, + route, + urlPostfix + }: { + currentDate: string; + languageCode: string; + rootUrl: string; + route?: PublicRoute; + urlPostfix?: string; + }): string { + const segments = + route?.routerLink.map((link) => { + const match = link.match( + SitemapService.TRANSLATION_TAGGED_MESSAGE_REGEX + ); + + const segment = match + ? (this.i18nService.getTranslation({ + languageCode, + id: match.groups.id + }) ?? match.groups.message) + : link; + + return segment.replace(/^\/+|\/+$/, ''); + }) ?? []; + + const location = + [rootUrl, languageCode, ...segments].join('/') + + (urlPostfix ? `-${urlPostfix}` : ''); + + return [ + ' ', + ` ${location}`, + ` ${currentDate}T00:00:00+00:00`, + ' ' + ].join('\n'); + } + + private createSitemapUrls( + params: { currentDate: string; languageCode: string; rootUrl: string }, + routes: Record + ): string[] { + return Object.values(routes).flatMap((route) => { + if (route.excludeFromSitemap) { + return []; + } + + const urls = [this.createRouteSitemapUrl({ ...params, route })]; + + if (route.subRoutes) { + urls.push(...this.createSitemapUrls(params, route.subRoutes)); + } + + return urls; + }); + } +} diff --git a/apps/api/src/app/endpoints/tags/create-tag.dto.ts b/apps/api/src/app/endpoints/tags/create-tag.dto.ts new file mode 100644 index 000000000..09c29d25a --- /dev/null +++ b/apps/api/src/app/endpoints/tags/create-tag.dto.ts @@ -0,0 +1,10 @@ +import { IsOptional, IsString } from 'class-validator'; + +export class CreateTagDto { + @IsString() + name: string; + + @IsOptional() + @IsString() + userId?: string; +} diff --git a/apps/api/src/app/tag/tag.controller.ts b/apps/api/src/app/endpoints/tags/tags.controller.ts similarity index 62% rename from apps/api/src/app/tag/tag.controller.ts rename to apps/api/src/app/endpoints/tags/tags.controller.ts index 6198a0bf5..bf216bb21 100644 --- a/apps/api/src/app/tag/tag.controller.ts +++ b/apps/api/src/app/endpoints/tags/tags.controller.ts @@ -1,6 +1,8 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; -import { permissions } from '@ghostfolio/common/permissions'; +import { TagService } from '@ghostfolio/api/services/tag/tag.service'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { RequestWithUser } from '@ghostfolio/common/types'; import { Body, @@ -8,41 +10,63 @@ import { Delete, Get, HttpException, + Inject, Param, Post, Put, UseGuards } from '@nestjs/common'; +import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; import { Tag } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { CreateTagDto } from './create-tag.dto'; -import { TagService } from './tag.service'; import { UpdateTagDto } from './update-tag.dto'; -@Controller('tag') -export class TagController { - public constructor(private readonly tagService: TagService) {} - - @Get() - @HasPermission(permissions.readTags) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async getTags() { - return this.tagService.getTagsWithActivityCount(); - } +@Controller('tags') +export class TagsController { + public constructor( + @Inject(REQUEST) private readonly request: RequestWithUser, + private readonly tagService: TagService + ) {} @Post() - @HasPermission(permissions.createTag) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseGuards(AuthGuard('jwt')) public async createTag(@Body() data: CreateTagDto): Promise { + const canCreateOwnTag = hasPermission( + this.request.user.permissions, + permissions.createOwnTag + ); + + const canCreateTag = hasPermission( + this.request.user.permissions, + permissions.createTag + ); + + if (!canCreateOwnTag && !canCreateTag) { + throw new HttpException( + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN + ); + } + + if (canCreateOwnTag && !canCreateTag) { + if (data.userId !== this.request.user.id) { + throw new HttpException( + getReasonPhrase(StatusCodes.BAD_REQUEST), + StatusCodes.BAD_REQUEST + ); + } + } + return this.tagService.createTag(data); } - @HasPermission(permissions.updateTag) - @Put(':id') + @Delete(':id') + @HasPermission(permissions.deleteTag) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async updateTag(@Param('id') id: string, @Body() data: UpdateTagDto) { + public async deleteTag(@Param('id') id: string) { const originalTag = await this.tagService.getTag({ id }); @@ -54,20 +78,20 @@ export class TagController { ); } - return this.tagService.updateTag({ - data: { - ...data - }, - where: { - id - } - }); + return this.tagService.deleteTag({ id }); } - @Delete(':id') - @HasPermission(permissions.deleteTag) + @Get() + @HasPermission(permissions.readTags) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async deleteTag(@Param('id') id: string) { + public async getTags() { + return this.tagService.getTagsWithActivityCount(); + } + + @HasPermission(permissions.updateTag) + @Put(':id') + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async updateTag(@Param('id') id: string, @Body() data: UpdateTagDto) { const originalTag = await this.tagService.getTag({ id }); @@ -79,6 +103,13 @@ export class TagController { ); } - return this.tagService.deleteTag({ id }); + return this.tagService.updateTag({ + data: { + ...data + }, + where: { + id + } + }); } } diff --git a/apps/api/src/app/endpoints/tags/tags.module.ts b/apps/api/src/app/endpoints/tags/tags.module.ts new file mode 100644 index 000000000..a8a2f1c51 --- /dev/null +++ b/apps/api/src/app/endpoints/tags/tags.module.ts @@ -0,0 +1,12 @@ +import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; +import { TagModule } from '@ghostfolio/api/services/tag/tag.module'; + +import { Module } from '@nestjs/common'; + +import { TagsController } from './tags.controller'; + +@Module({ + controllers: [TagsController], + imports: [PrismaModule, TagModule] +}) +export class TagsModule {} diff --git a/apps/api/src/app/endpoints/tags/update-tag.dto.ts b/apps/api/src/app/endpoints/tags/update-tag.dto.ts new file mode 100644 index 000000000..5ae42dcc6 --- /dev/null +++ b/apps/api/src/app/endpoints/tags/update-tag.dto.ts @@ -0,0 +1,13 @@ +import { IsOptional, IsString } from 'class-validator'; + +export class UpdateTagDto { + @IsString() + id: string; + + @IsString() + name: string; + + @IsOptional() + @IsString() + userId?: string; +} diff --git a/apps/api/src/app/endpoints/watchlist/create-watchlist-item.dto.ts b/apps/api/src/app/endpoints/watchlist/create-watchlist-item.dto.ts new file mode 100644 index 000000000..663965ef1 --- /dev/null +++ b/apps/api/src/app/endpoints/watchlist/create-watchlist-item.dto.ts @@ -0,0 +1,10 @@ +import { DataSource } from '@prisma/client'; +import { IsEnum, IsString } from 'class-validator'; + +export class CreateWatchlistItemDto { + @IsEnum(DataSource) + dataSource: DataSource; + + @IsString() + symbol: string; +} diff --git a/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts b/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts new file mode 100644 index 000000000..2a8ea9875 --- /dev/null +++ b/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts @@ -0,0 +1,100 @@ +import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; +import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; +import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; +import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; +import { WatchlistResponse } from '@ghostfolio/common/interfaces'; +import { permissions } from '@ghostfolio/common/permissions'; +import { RequestWithUser } from '@ghostfolio/common/types'; + +import { + Body, + Controller, + Delete, + Get, + Headers, + HttpException, + Inject, + Param, + Post, + UseGuards, + UseInterceptors +} from '@nestjs/common'; +import { REQUEST } from '@nestjs/core'; +import { AuthGuard } from '@nestjs/passport'; +import { DataSource } from '@prisma/client'; +import { StatusCodes, getReasonPhrase } from 'http-status-codes'; + +import { CreateWatchlistItemDto } from './create-watchlist-item.dto'; +import { WatchlistService } from './watchlist.service'; + +@Controller('watchlist') +export class WatchlistController { + public constructor( + private readonly impersonationService: ImpersonationService, + @Inject(REQUEST) private readonly request: RequestWithUser, + private readonly watchlistService: WatchlistService + ) {} + + @Post() + @HasPermission(permissions.createWatchlistItem) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseInterceptors(TransformDataSourceInRequestInterceptor) + public async createWatchlistItem(@Body() data: CreateWatchlistItemDto) { + return this.watchlistService.createWatchlistItem({ + dataSource: data.dataSource, + symbol: data.symbol, + userId: this.request.user.id + }); + } + + @Delete(':dataSource/:symbol') + @HasPermission(permissions.deleteWatchlistItem) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseInterceptors(TransformDataSourceInRequestInterceptor) + public async deleteWatchlistItem( + @Param('dataSource') dataSource: DataSource, + @Param('symbol') symbol: string + ) { + const watchlistItems = await this.watchlistService.getWatchlistItems( + this.request.user.id + ); + + const watchlistItem = watchlistItems.find((item) => { + return item.dataSource === dataSource && item.symbol === symbol; + }); + + if (!watchlistItem) { + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + + return this.watchlistService.deleteWatchlistItem({ + dataSource, + symbol, + userId: this.request.user.id + }); + } + + @Get() + @HasPermission(permissions.readWatchlist) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseInterceptors(TransformDataSourceInResponseInterceptor) + public async getWatchlistItems( + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string + ): Promise { + const impersonationUserId = + await this.impersonationService.validateImpersonationId(impersonationId); + + const watchlist = await this.watchlistService.getWatchlistItems( + impersonationUserId || this.request.user.id + ); + + return { + watchlist + }; + } +} diff --git a/apps/api/src/app/benchmark/benchmark.module.ts b/apps/api/src/app/endpoints/watchlist/watchlist.module.ts similarity index 53% rename from apps/api/src/app/benchmark/benchmark.module.ts rename to apps/api/src/app/endpoints/watchlist/watchlist.module.ts index 4c5f4d58e..ce9ae12bb 100644 --- a/apps/api/src/app/benchmark/benchmark.module.ts +++ b/apps/api/src/app/endpoints/watchlist/watchlist.module.ts @@ -1,36 +1,31 @@ -import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; -import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; -import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; -import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; import { Module } from '@nestjs/common'; -import { BenchmarkController } from './benchmark.controller'; -import { BenchmarkService } from './benchmark.service'; +import { WatchlistController } from './watchlist.controller'; +import { WatchlistService } from './watchlist.service'; @Module({ - controllers: [BenchmarkController], - exports: [BenchmarkService], + controllers: [WatchlistController], imports: [ - ConfigurationModule, + BenchmarkModule, + DataGatheringModule, DataProviderModule, - ExchangeRateDataModule, + ImpersonationModule, MarketDataModule, PrismaModule, - PropertyModule, - RedisCacheModule, - SymbolModule, SymbolProfileModule, TransformDataSourceInRequestModule, TransformDataSourceInResponseModule ], - providers: [BenchmarkService] + providers: [WatchlistService] }) -export class BenchmarkModule {} +export class WatchlistModule {} diff --git a/apps/api/src/app/endpoints/watchlist/watchlist.service.ts b/apps/api/src/app/endpoints/watchlist/watchlist.service.ts new file mode 100644 index 000000000..36a498e1d --- /dev/null +++ b/apps/api/src/app/endpoints/watchlist/watchlist.service.ts @@ -0,0 +1,150 @@ +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; +import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; +import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; +import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; +import { WatchlistResponse } from '@ghostfolio/common/interfaces'; + +import { BadRequestException, Injectable } from '@nestjs/common'; +import { DataSource, Prisma } from '@prisma/client'; + +@Injectable() +export class WatchlistService { + public constructor( + private readonly benchmarkService: BenchmarkService, + private readonly dataGatheringService: DataGatheringService, + private readonly dataProviderService: DataProviderService, + private readonly marketDataService: MarketDataService, + private readonly prismaService: PrismaService, + private readonly symbolProfileService: SymbolProfileService + ) {} + + public async createWatchlistItem({ + dataSource, + symbol, + userId + }: { + dataSource: DataSource; + symbol: string; + userId: string; + }): Promise { + const symbolProfile = await this.prismaService.symbolProfile.findUnique({ + where: { + dataSource_symbol: { dataSource, symbol } + } + }); + + if (!symbolProfile) { + const assetProfiles = await this.dataProviderService.getAssetProfiles([ + { dataSource, symbol } + ]); + + if (!assetProfiles[symbol]?.currency) { + throw new BadRequestException( + `Asset profile not found for ${symbol} (${dataSource})` + ); + } + + await this.symbolProfileService.add( + assetProfiles[symbol] as Prisma.SymbolProfileCreateInput + ); + } + + await this.dataGatheringService.gatherSymbol({ + dataSource, + symbol + }); + + await this.prismaService.user.update({ + data: { + watchlist: { + connect: { + dataSource_symbol: { dataSource, symbol } + } + } + }, + where: { id: userId } + }); + } + + public async deleteWatchlistItem({ + dataSource, + symbol, + userId + }: { + dataSource: DataSource; + symbol: string; + userId: string; + }) { + await this.prismaService.user.update({ + data: { + watchlist: { + disconnect: { + dataSource_symbol: { dataSource, symbol } + } + } + }, + where: { id: userId } + }); + } + + public async getWatchlistItems( + userId: string + ): Promise { + const user = await this.prismaService.user.findUnique({ + select: { + watchlist: { + select: { dataSource: true, symbol: true } + } + }, + where: { id: userId } + }); + + const [assetProfiles, quotes] = await Promise.all([ + this.symbolProfileService.getSymbolProfiles(user.watchlist), + this.dataProviderService.getQuotes({ + items: user.watchlist.map(({ dataSource, symbol }) => { + return { dataSource, symbol }; + }) + }) + ]); + + const watchlist = await Promise.all( + user.watchlist.map(async ({ dataSource, symbol }) => { + const assetProfile = assetProfiles.find((profile) => { + return profile.dataSource === dataSource && profile.symbol === symbol; + }); + + const allTimeHigh = await this.marketDataService.getMax({ + dataSource, + symbol + }); + + const performancePercent = + this.benchmarkService.calculateChangeInPercentage( + allTimeHigh?.marketPrice, + quotes[symbol]?.marketPrice + ); + + return { + dataSource, + symbol, + marketCondition: + this.benchmarkService.getMarketCondition(performancePercent), + name: assetProfile?.name, + performances: { + allTimeHigh: { + performancePercent, + date: allTimeHigh?.date + } + } + }; + }) + ); + + return watchlist.sort((a, b) => { + return a.name.localeCompare(b.name); + }); + } +} diff --git a/apps/api/src/app/export/export.controller.ts b/apps/api/src/app/export/export.controller.ts index 551b3e489..8fa2baa43 100644 --- a/apps/api/src/app/export/export.controller.ts +++ b/apps/api/src/app/export/export.controller.ts @@ -1,9 +1,17 @@ import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { Export } from '@ghostfolio/common/interfaces'; import type { RequestWithUser } from '@ghostfolio/common/types'; -import { Controller, Get, Inject, Query, UseGuards } from '@nestjs/common'; +import { + Controller, + Get, + Inject, + Query, + UseGuards, + UseInterceptors +} from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; @@ -19,22 +27,28 @@ export class ExportController { @Get() @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseInterceptors(TransformDataSourceInRequestInterceptor) public async export( @Query('accounts') filterByAccounts?: string, - @Query('activityIds') activityIds?: string[], + @Query('activityIds') filterByActivityIds?: string, @Query('assetClasses') filterByAssetClasses?: string, + @Query('dataSource') filterByDataSource?: string, + @Query('symbol') filterBySymbol?: string, @Query('tags') filterByTags?: string ): Promise { + const activityIds = filterByActivityIds?.split(',') ?? []; const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, + filterByDataSource, + filterBySymbol, filterByTags }); return this.exportService.export({ activityIds, filters, - userCurrency: this.request.user.Settings.settings.baseCurrency, + userCurrency: this.request.user.settings.settings.baseCurrency, userId: this.request.user.id }); } diff --git a/apps/api/src/app/export/export.module.ts b/apps/api/src/app/export/export.module.ts index 048c60359..4f40cc417 100644 --- a/apps/api/src/app/export/export.module.ts +++ b/apps/api/src/app/export/export.module.ts @@ -1,6 +1,9 @@ import { AccountModule } from '@ghostfolio/api/app/account/account.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; +import { TagModule } from '@ghostfolio/api/services/tag/tag.module'; import { Module } from '@nestjs/common'; @@ -8,8 +11,15 @@ import { ExportController } from './export.controller'; import { ExportService } from './export.service'; @Module({ - imports: [AccountModule, ApiModule, OrderModule], controllers: [ExportController], + imports: [ + AccountModule, + ApiModule, + MarketDataModule, + OrderModule, + TagModule, + TransformDataSourceInRequestModule + ], providers: [ExportService] }) export class ExportModule {} diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index 1ff18ce9c..54fd0763d 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -1,15 +1,21 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { environment } from '@ghostfolio/api/environments/environment'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { Filter, Export } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; +import { Platform, Prisma } from '@prisma/client'; +import { groupBy, uniqBy } from 'lodash'; @Injectable() export class ExportService { public constructor( private readonly accountService: AccountService, - private readonly orderService: OrderService + private readonly marketDataService: MarketDataService, + private readonly orderService: OrderService, + private readonly tagService: TagService ) {} public async export({ @@ -23,55 +29,198 @@ export class ExportService { userCurrency: string; userId: string; }): Promise { + const { ACCOUNT: filtersByAccount } = groupBy(filters, ({ type }) => { + return type; + }); + const platformsMap: { [platformId: string]: Platform } = {}; + + let { activities } = await this.orderService.getOrders({ + filters, + userCurrency, + userId, + includeDrafts: true, + sortColumn: 'date', + sortDirection: 'asc', + withExcludedAccounts: true + }); + + if (activityIds?.length > 0) { + activities = activities.filter(({ id }) => { + return activityIds.includes(id); + }); + } + + const where: Prisma.AccountWhereInput = { userId }; + + if (filtersByAccount?.length > 0) { + where.id = { + in: filtersByAccount.map(({ id }) => { + return id; + }) + }; + } + const accounts = ( await this.accountService.accounts({ + where, + include: { + balances: true, + platform: true + }, orderBy: { name: 'asc' - }, - where: { userId } + } }) - ).map( - ({ balance, comment, currency, id, isExcluded, name, platformId }) => { - return { + ) + .filter(({ id }) => { + return activityIds?.length > 0 + ? activities.some(({ accountId }) => { + return accountId === id; + }) + : true; + }) + .map( + ({ balance, + balances, comment, currency, id, isExcluded, name, + platform, platformId - }; + }) => { + if (platformId) { + platformsMap[platformId] = platform; + } + + return { + balance, + balances: balances.map(({ date, value }) => { + return { date: date.toISOString(), value }; + }), + comment, + currency, + id, + isExcluded, + name, + platformId + }; + } + ); + + const customAssetProfiles = uniqBy( + activities + .map(({ SymbolProfile }) => { + return SymbolProfile; + }) + .filter(({ userId: assetProfileUserId }) => { + return assetProfileUserId === userId; + }), + ({ id }) => { + return id; } ); - let { activities } = await this.orderService.getOrders({ - filters, - userCurrency, - userId, - includeDrafts: true, - sortColumn: 'date', - sortDirection: 'asc', - withExcludedAccounts: true - }); + const marketDataByAssetProfile = Object.fromEntries( + await Promise.all( + customAssetProfiles.map(async ({ dataSource, id, symbol }) => { + const marketData = ( + await this.marketDataService.marketDataItems({ + where: { dataSource, symbol } + }) + ).map(({ date, marketPrice }) => ({ + date: date.toISOString(), + marketPrice + })); - if (activityIds) { - activities = activities.filter((activity) => { - return activityIds.includes(activity.id); + return [id, marketData] as const; + }) + ) + ); + + const tags = (await this.tagService.getTagsForUser(userId)) + .filter( + ({ id, isUsed }) => + isUsed && + activities.some((activity) => { + return activity.tags.some(({ id: tagId }) => { + return tagId === id; + }); + }) + ) + .map(({ id, name }) => { + return { + id, + name + }; }); - } return { meta: { date: new Date().toISOString(), version: environment.version }, accounts, + assetProfiles: customAssetProfiles.map( + ({ + assetClass, + assetSubClass, + comment, + countries, + currency, + cusip, + dataSource, + figi, + figiComposite, + figiShareClass, + holdings, + id, + isActive, + isin, + name, + scraperConfiguration, + sectors, + symbol, + symbolMapping, + url + }) => { + return { + assetClass, + assetSubClass, + comment, + countries: countries as unknown as Prisma.JsonArray, + currency, + cusip, + dataSource, + figi, + figiComposite, + figiShareClass, + holdings: holdings as unknown as Prisma.JsonArray, + isActive, + isin, + marketData: marketDataByAssetProfile[id], + name, + scraperConfiguration: + scraperConfiguration as unknown as Prisma.JsonArray, + sectors: sectors as unknown as Prisma.JsonArray, + symbol, + symbolMapping, + url + }; + } + ), + platforms: Object.values(platformsMap), + tags, activities: activities.map( ({ accountId, comment, + currency, date, fee, id, quantity, SymbolProfile, + tags: currentTags, type, unitPrice }) => { @@ -83,16 +232,13 @@ export class ExportService { quantity, type, unitPrice, - currency: SymbolProfile.currency, + currency: currency ?? SymbolProfile.currency, dataSource: SymbolProfile.dataSource, date: date.toISOString(), - symbol: - type === 'FEE' || - type === 'INTEREST' || - type === 'ITEM' || - type === 'LIABILITY' - ? SymbolProfile.name - : SymbolProfile.symbol + symbol: SymbolProfile.symbol, + tags: currentTags.map(({ id: tagId }) => { + return tagId; + }) }; } ), diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index 62ee20419..5542ae933 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -1,15 +1,20 @@ import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { + DataEnhancerHealthResponse, + DataProviderHealthResponse +} from '@ghostfolio/common/interfaces'; import { Controller, Get, - HttpCode, HttpException, HttpStatus, Param, + Res, UseInterceptors } from '@nestjs/common'; import { DataSource } from '@prisma/client'; +import { Response } from 'express'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { HealthService } from './health.service'; @@ -19,29 +24,47 @@ export class HealthController { public constructor(private readonly healthService: HealthService) {} @Get() - @HttpCode(HttpStatus.OK) - public getHealth() { - return { status: getReasonPhrase(StatusCodes.OK) }; + public async getHealth(@Res() response: Response) { + const databaseServiceHealthy = await this.healthService.isDatabaseHealthy(); + const redisCacheServiceHealthy = + await this.healthService.isRedisCacheHealthy(); + + if (databaseServiceHealthy && redisCacheServiceHealthy) { + return response + .status(HttpStatus.OK) + .json({ status: getReasonPhrase(StatusCodes.OK) }); + } else { + return response + .status(HttpStatus.SERVICE_UNAVAILABLE) + .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); + } } @Get('data-enhancer/:name') - public async getHealthOfDataEnhancer(@Param('name') name: string) { + public async getHealthOfDataEnhancer( + @Param('name') name: string, + @Res() response: Response + ): Promise> { const hasResponse = await this.healthService.hasResponseFromDataEnhancer(name); - if (hasResponse !== true) { - throw new HttpException( - getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE), - StatusCodes.SERVICE_UNAVAILABLE - ); + if (hasResponse) { + return response.status(HttpStatus.OK).json({ + status: getReasonPhrase(StatusCodes.OK) + }); + } else { + return response + .status(HttpStatus.SERVICE_UNAVAILABLE) + .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } } @Get('data-provider/:dataSource') @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getHealthOfDataProvider( - @Param('dataSource') dataSource: DataSource - ) { + @Param('dataSource') dataSource: DataSource, + @Res() response: Response + ): Promise> { if (!DataSource[dataSource]) { throw new HttpException( getReasonPhrase(StatusCodes.NOT_FOUND), @@ -52,11 +75,14 @@ export class HealthController { const hasResponse = await this.healthService.hasResponseFromDataProvider(dataSource); - if (hasResponse !== true) { - throw new HttpException( - getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE), - StatusCodes.SERVICE_UNAVAILABLE - ); + if (hasResponse) { + return response + .status(HttpStatus.OK) + .json({ status: getReasonPhrase(StatusCodes.OK) }); + } else { + return response + .status(HttpStatus.SERVICE_UNAVAILABLE) + .json({ status: getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE) }); } } } diff --git a/apps/api/src/app/health/health.module.ts b/apps/api/src/app/health/health.module.ts index 6ed464401..b8c4d5810 100644 --- a/apps/api/src/app/health/health.module.ts +++ b/apps/api/src/app/health/health.module.ts @@ -1,6 +1,8 @@ +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { DataEnhancerModule } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { Module } from '@nestjs/common'; @@ -12,6 +14,8 @@ import { HealthService } from './health.service'; imports: [ DataEnhancerModule, DataProviderModule, + PropertyModule, + RedisCacheModule, TransformDataSourceInRequestModule ], providers: [HealthService] diff --git a/apps/api/src/app/health/health.service.ts b/apps/api/src/app/health/health.service.ts index b0c811392..f08f33a1e 100644 --- a/apps/api/src/app/health/health.service.ts +++ b/apps/api/src/app/health/health.service.ts @@ -1,5 +1,8 @@ +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { DataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { PROPERTY_CURRENCIES } from '@ghostfolio/common/config'; import { Injectable } from '@nestjs/common'; import { DataSource } from '@prisma/client'; @@ -8,7 +11,9 @@ import { DataSource } from '@prisma/client'; export class HealthService { public constructor( private readonly dataEnhancerService: DataEnhancerService, - private readonly dataProviderService: DataProviderService + private readonly dataProviderService: DataProviderService, + private readonly propertyService: PropertyService, + private readonly redisCacheService: RedisCacheService ) {} public async hasResponseFromDataEnhancer(aName: string) { @@ -18,4 +23,24 @@ export class HealthService { public async hasResponseFromDataProvider(aDataSource: DataSource) { return this.dataProviderService.checkQuote(aDataSource); } + + public async isDatabaseHealthy() { + try { + await this.propertyService.getByKey(PROPERTY_CURRENCIES); + + return true; + } catch { + return false; + } + } + + public async isRedisCacheHealthy() { + try { + const isHealthy = await this.redisCacheService.isHealthy(); + + return isHealthy; + } catch { + return false; + } + } } diff --git a/apps/api/src/app/import/create-account-with-balances.dto.ts b/apps/api/src/app/import/create-account-with-balances.dto.ts new file mode 100644 index 000000000..6cf4057f8 --- /dev/null +++ b/apps/api/src/app/import/create-account-with-balances.dto.ts @@ -0,0 +1,10 @@ +import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; +import { AccountBalance } from '@ghostfolio/common/interfaces'; + +import { IsArray, IsOptional } from 'class-validator'; + +export class CreateAccountWithBalancesDto extends CreateAccountDto { + @IsArray() + @IsOptional() + balances?: AccountBalance[]; +} diff --git a/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts b/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts new file mode 100644 index 000000000..fd90ab1af --- /dev/null +++ b/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts @@ -0,0 +1,17 @@ +import { MarketData } from '@ghostfolio/common/interfaces'; + +import { DataSource } from '@prisma/client'; +import { IsArray, IsEnum, IsOptional } from 'class-validator'; + +import { CreateAssetProfileDto } from '../admin/create-asset-profile.dto'; + +export class CreateAssetProfileWithMarketDataDto extends CreateAssetProfileDto { + @IsEnum([DataSource.MANUAL], { + message: `dataSource must be '${DataSource.MANUAL}'` + }) + dataSource: DataSource; + + @IsArray() + @IsOptional() + marketData?: MarketData[]; +} diff --git a/apps/api/src/app/import/import-data.dto.ts b/apps/api/src/app/import/import-data.dto.ts index 715766821..138d16961 100644 --- a/apps/api/src/app/import/import-data.dto.ts +++ b/apps/api/src/app/import/import-data.dto.ts @@ -1,18 +1,26 @@ -import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Type } from 'class-transformer'; import { IsArray, IsOptional, ValidateNested } from 'class-validator'; +import { CreateAccountWithBalancesDto } from './create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from './create-asset-profile-with-market-data.dto'; + export class ImportDataDto { - @IsOptional() @IsArray() - @Type(() => CreateAccountDto) + @IsOptional() + @Type(() => CreateAccountWithBalancesDto) @ValidateNested({ each: true }) - accounts: CreateAccountDto[]; + accounts?: CreateAccountWithBalancesDto[]; @IsArray() @Type(() => CreateOrderDto) @ValidateNested({ each: true }) activities: CreateOrderDto[]; + + @IsArray() + @IsOptional() + @Type(() => CreateAssetProfileWithMarketDataDto) + @ValidateNested({ each: true }) + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; } diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index b276a3c3d..8c06bdc6d 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -71,8 +71,9 @@ export class ImportController { const activities = await this.importService.import({ isDryRun, maxActivitiesToImport, - accountsDto: importData.accounts ?? [], + accountsWithBalancesDto: importData.accounts ?? [], activitiesDto: importData.activities, + assetProfilesWithMarketDataDto: importData.assetProfiles ?? [], user: this.request.user }); @@ -98,12 +99,10 @@ export class ImportController { @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise { - const userCurrency = this.request.user.Settings.settings.baseCurrency; - const activities = await this.importService.getDividends({ dataSource, symbol, - userCurrency + userId: this.request.user.id }); return { activities }; diff --git a/apps/api/src/app/import/import.module.ts b/apps/api/src/app/import/import.module.ts index 142a939a6..fb6c29fc5 100644 --- a/apps/api/src/app/import/import.module.ts +++ b/apps/api/src/app/import/import.module.ts @@ -9,6 +9,7 @@ import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptor import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; @@ -27,6 +28,7 @@ import { ImportService } from './import.service'; DataGatheringModule, DataProviderModule, ExchangeRateDataModule, + MarketDataModule, OrderModule, PlatformModule, PortfolioModule, diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 3b7290b43..d23427616 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -10,12 +10,11 @@ import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; import { - DATE_FORMAT, getAssetProfileIdentifier, parseDate } from '@ghostfolio/common/helper'; @@ -29,10 +28,13 @@ import { import { Injectable } from '@nestjs/common'; import { DataSource, Prisma, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { endOfToday, format, isAfter, isSameSecond, parseISO } from 'date-fns'; -import { uniqBy } from 'lodash'; +import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; +import { omit, uniqBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; +import { CreateAssetProfileDto } from '../admin/create-asset-profile.dto'; +import { ImportDataDto } from './import-data.dto'; + @Injectable() export class ImportService { public constructor( @@ -40,7 +42,7 @@ export class ImportService { private readonly configurationService: ConfigurationService, private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, - private readonly exchangeRateDataService: ExchangeRateDataService, + private readonly marketDataService: MarketDataService, private readonly orderService: OrderService, private readonly platformService: PlatformService, private readonly portfolioService: PortfolioService, @@ -50,11 +52,16 @@ export class ImportService { public async getDividends({ dataSource, symbol, - userCurrency - }: AssetProfileIdentifier & { userCurrency: string }): Promise { + userId + }: AssetProfileIdentifier & { userId: string }): Promise { try { - const { firstBuyDate, historicalData, orders } = - await this.portfolioService.getPosition(dataSource, undefined, symbol); + const { activities, firstBuyDate, historicalData } = + await this.portfolioService.getHolding({ + dataSource, + symbol, + userId, + impersonationId: undefined + }); const [[assetProfile], dividends] = await Promise.all([ this.symbolProfileService.getSymbolProfiles([ @@ -72,15 +79,15 @@ export class ImportService { }) ]); - const accounts = orders - .filter(({ Account }) => { - return !!Account; + const accounts = activities + .filter(({ account }) => { + return !!account; }) - .map(({ Account }) => { - return Account; + .map(({ account }) => { + return account; }); - const Account = this.isUniqueAccount(accounts) ? accounts[0] : undefined; + const account = this.isUniqueAccount(accounts) ? accounts[0] : undefined; return await Promise.all( Object.entries(dividends).map(async ([dateString, { marketPrice }]) => { @@ -92,9 +99,9 @@ export class ImportService { const value = new Big(quantity).mul(marketPrice).toNumber(); const date = parseDate(dateString); - const isDuplicate = orders.some((activity) => { + const isDuplicate = activities.some((activity) => { return ( - activity.accountId === Account?.id && + activity.accountId === account?.id && activity.SymbolProfile.currency === assetProfile.currency && activity.SymbolProfile.dataSource === assetProfile.dataSource && isSameSecond(activity.date, date) && @@ -110,17 +117,18 @@ export class ImportService { : undefined; return { - Account, + account, date, error, quantity, value, - accountId: Account?.id, + accountId: account?.id, accountUserId: undefined, comment: undefined, currency: undefined, createdAt: undefined, fee: 0, + feeInAssetProfileCurrency: 0, feeInBaseCurrency: 0, id: assetProfile.id, isDraft: false, @@ -128,15 +136,10 @@ export class ImportService { symbolProfileId: assetProfile.id, type: 'DIVIDEND', unitPrice: marketPrice, + unitPriceInAssetProfileCurrency: marketPrice, updatedAt: undefined, - userId: Account?.userId, - valueInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - value, - assetProfile.currency, - userCurrency, - date - ) + userId: account?.userId, + valueInBaseCurrency: value }; }) ); @@ -146,27 +149,30 @@ export class ImportService { } public async import({ - accountsDto, + accountsWithBalancesDto, activitiesDto, + assetProfilesWithMarketDataDto, isDryRun = false, maxActivitiesToImport, user }: { - accountsDto: Partial[]; - activitiesDto: Partial[]; + accountsWithBalancesDto: ImportDataDto['accounts']; + activitiesDto: ImportDataDto['activities']; + assetProfilesWithMarketDataDto: ImportDataDto['assetProfiles']; isDryRun?: boolean; maxActivitiesToImport: number; user: UserWithSettings; }): Promise { const accountIdMapping: { [oldAccountId: string]: string } = {}; - const userCurrency = user.Settings.settings.baseCurrency; + const assetProfileSymbolMapping: { [oldSymbol: string]: string } = {}; + const userCurrency = user.settings.settings.baseCurrency; - if (!isDryRun && accountsDto?.length) { + if (!isDryRun && accountsWithBalancesDto?.length) { const [existingAccounts, existingPlatforms] = await Promise.all([ this.accountService.accounts({ where: { id: { - in: accountsDto.map(({ id }) => { + in: accountsWithBalancesDto.map(({ id }) => { return id; }) } @@ -175,14 +181,19 @@ export class ImportService { this.platformService.getPlatforms() ]); - for (const account of accountsDto) { + for (const accountWithBalances of accountsWithBalancesDto) { // Check if there is any existing account with the same ID - const accountWithSameId = existingAccounts.find( - (existingAccount) => existingAccount.id === account.id - ); + const accountWithSameId = existingAccounts.find((existingAccount) => { + return existingAccount.id === accountWithBalances.id; + }); // If there is no account or if the account belongs to a different user then create a new account if (!accountWithSameId || accountWithSameId.userId !== user.id) { + const account: CreateAccountDto = omit( + accountWithBalances, + 'balances' + ); + let oldAccountId: string; const platformId = account.platformId; @@ -195,7 +206,10 @@ export class ImportService { let accountObject: Prisma.AccountCreateInput = { ...account, - User: { connect: { id: user.id } } + balances: { + create: accountWithBalances.balances ?? [] + }, + user: { connect: { id: user.id } } }; if ( @@ -205,7 +219,7 @@ export class ImportService { ) { accountObject = { ...accountObject, - Platform: { connect: { id: platformId } } + platform: { connect: { id: platformId } } }; } @@ -222,9 +236,66 @@ export class ImportService { } } + if (!isDryRun && assetProfilesWithMarketDataDto?.length) { + const existingAssetProfiles = + await this.symbolProfileService.getSymbolProfiles( + assetProfilesWithMarketDataDto.map(({ dataSource, symbol }) => { + return { dataSource, symbol }; + }) + ); + + for (const assetProfileWithMarketData of assetProfilesWithMarketDataDto) { + // Check if there is any existing asset profile + const existingAssetProfile = existingAssetProfiles.find( + ({ dataSource, symbol }) => { + return ( + dataSource === assetProfileWithMarketData.dataSource && + symbol === assetProfileWithMarketData.symbol + ); + } + ); + + // If there is no asset profile or if the asset profile belongs to a different user, then create a new asset profile + if (!existingAssetProfile || existingAssetProfile.userId !== user.id) { + const assetProfile: CreateAssetProfileDto = omit( + assetProfileWithMarketData, + 'marketData' + ); + + // Asset profile belongs to a different user + if (existingAssetProfile) { + const symbol = uuidv4(); + assetProfileSymbolMapping[assetProfile.symbol] = symbol; + assetProfile.symbol = symbol; + } + + // Create a new asset profile + const assetProfileObject: Prisma.SymbolProfileCreateInput = { + ...assetProfile, + user: { connect: { id: user.id } } + }; + + await this.symbolProfileService.add(assetProfileObject); + } + + // Insert or update market data + const marketDataObjects = assetProfileWithMarketData.marketData.map( + (marketData) => { + return { + ...marketData, + dataSource: assetProfileWithMarketData.dataSource, + symbol: assetProfileWithMarketData.symbol + } as Prisma.MarketDataUpdateInput; + } + ); + + await this.marketDataService.updateMany({ data: marketDataObjects }); + } + } + for (const activity of activitiesDto) { if (!activity.dataSource) { - if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(activity.type)) { + if (['FEE', 'INTEREST', 'LIABILITY'].includes(activity.type)) { activity.dataSource = DataSource.MANUAL; } else { activity.dataSource = @@ -232,11 +303,16 @@ export class ImportService { } } - // If a new account is created, then update the accountId in all activities if (!isDryRun) { - if (Object.keys(accountIdMapping).includes(activity.accountId)) { + // If a new account is created, then update the accountId in all activities + if (accountIdMapping[activity.accountId]) { activity.accountId = accountIdMapping[activity.accountId]; } + + // If a new asset profile is created, then update the symbol in all activities + if (assetProfileSymbolMapping[activity.symbol]) { + activity.symbol = assetProfileSymbolMapping[activity.symbol]; + } } } @@ -259,24 +335,24 @@ export class ImportService { ); if (isDryRun) { - accountsDto.forEach(({ id, name }) => { + accountsWithBalancesDto.forEach(({ id, name }) => { accounts.push({ id, name }); }); } const activities: Activity[] = []; - for (const [index, activity] of activitiesExtendedWithErrors.entries()) { + for (const activity of activitiesExtendedWithErrors) { const accountId = activity.accountId; const comment = activity.comment; const currency = activity.currency; const date = activity.date; const error = activity.error; - let fee = activity.fee; + const fee = activity.fee; const quantity = activity.quantity; const SymbolProfile = activity.SymbolProfile; const type = activity.type; - let unitPrice = activity.unitPrice; + const unitPrice = activity.unitPrice; const assetProfile = assetProfiles[ getAssetProfileIdentifier({ @@ -284,7 +360,6 @@ export class ImportService { symbol: SymbolProfile.symbol }) ] ?? { - currency: SymbolProfile.currency, dataSource: SymbolProfile.dataSource, symbol: SymbolProfile.symbol }; @@ -293,12 +368,14 @@ export class ImportService { assetSubClass, countries, createdAt, + cusip, dataSource, figi, figiComposite, figiShareClass, holdings, id, + isActive, isin, name, scraperConfiguration, @@ -318,35 +395,6 @@ export class ImportService { Account?: { id: string; name: string }; }); - if (SymbolProfile.currency !== assetProfile.currency) { - // Convert the unit price and fee to the asset currency if the imported - // activity is in a different currency - unitPrice = await this.exchangeRateDataService.toCurrencyAtDate( - unitPrice, - SymbolProfile.currency, - assetProfile.currency, - date - ); - - if (!unitPrice) { - throw new Error( - `activities.${index} historical exchange rate at ${format( - date, - DATE_FORMAT - )} is not available from "${SymbolProfile.currency}" to "${ - assetProfile.currency - }"` - ); - } - - fee = await this.exchangeRateDataService.toCurrencyAtDate( - fee, - SymbolProfile.currency, - assetProfile.currency, - date - ); - } - if (isDryRun) { order = { comment, @@ -367,12 +415,14 @@ export class ImportService { assetSubClass, countries, createdAt, + cusip, dataSource, figi, figiComposite, figiShareClass, holdings, id, + isActive, isin, name, scraperConfiguration, @@ -396,6 +446,7 @@ export class ImportService { order = await this.orderService.createOrder({ comment, + currency, date, fee, quantity, @@ -419,7 +470,7 @@ export class ImportService { } }, updateAccountBalance: false, - User: { connect: { id: user.id } }, + user: { connect: { id: user.id } }, userId: user.id }); @@ -435,21 +486,8 @@ export class ImportService { ...order, error, value, - feeInBaseCurrency: await this.exchangeRateDataService.toCurrencyAtDate( - fee, - assetProfile.currency, - userCurrency, - date - ), // @ts-ignore - SymbolProfile: assetProfile, - valueInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - value, - assetProfile.currency, - userCurrency, - date - ) + SymbolProfile: assetProfile }); } @@ -515,7 +553,9 @@ export class ImportService { const isDuplicate = existingActivities.some((activity) => { return ( activity.accountId === accountId && - activity.SymbolProfile.currency === currency && + activity.comment === comment && + (activity.currency === currency || + activity.SymbolProfile.currency === currency) && activity.SymbolProfile.dataSource === dataSource && isSameSecond(activity.date, date) && activity.fee === fee && @@ -533,6 +573,7 @@ export class ImportService { return { accountId, comment, + currency, date, error, fee, @@ -540,7 +581,6 @@ export class ImportService { type, unitPrice, SymbolProfile: { - currency, dataSource, symbol, activitiesCount: undefined, @@ -548,8 +588,10 @@ export class ImportService { assetSubClass: undefined, countries: undefined, createdAt: undefined, + currency: undefined, holdings: undefined, id: undefined, + isActive: true, sectors: undefined, updatedAt: undefined } @@ -584,12 +626,18 @@ export class ImportService { const assetProfiles: { [assetProfileIdentifier: string]: Partial; } = {}; - const dataSources = await this.dataProviderService.getDataSources(); + const dataSources = await this.dataProviderService.getDataSources({ user }); for (const [ index, { currency, dataSource, symbol, type } ] of activitiesDto.entries()) { + if (type === 'ITEM') { + throw new Error( + `activities.${index}.type ("${type}") is deprecated, please use "BUY" instead` + ); + } + if (!dataSources.includes(dataSource)) { throw new Error( `activities.${index}.dataSource ("${dataSource}") is not valid` @@ -621,18 +669,16 @@ export class ImportService { )?.[symbol] }; - if (type === 'BUY' || type === 'DIVIDEND' || type === 'SELL') { + if ( + (dataSource !== 'MANUAL' && type === 'BUY') || + type === 'DIVIDEND' || + type === 'SELL' + ) { if (!assetProfile?.name) { throw new Error( `activities.${index}.symbol ("${symbol}") is not valid for the specified data source ("${dataSource}")` ); } - - if (assetProfile.currency !== currency) { - throw new Error( - `activities.${index}.currency ("${currency}") does not match with currency of ${assetProfile.symbol} ("${assetProfile.currency}")` - ); - } } assetProfiles[getAssetProfileIdentifier({ dataSource, symbol })] = diff --git a/apps/api/src/app/info/info.module.ts b/apps/api/src/app/info/info.module.ts index 7903ac397..9ded44600 100644 --- a/apps/api/src/app/info/info.module.ts +++ b/apps/api/src/app/info/info.module.ts @@ -1,8 +1,9 @@ -import { BenchmarkModule } from '@ghostfolio/api/app/benchmark/benchmark.module'; import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; @@ -31,6 +32,7 @@ import { InfoService } from './info.service'; PlatformModule, PropertyModule, RedisCacheModule, + SubscriptionModule, SymbolProfileModule, TransformDataSourceInResponseModule, UserModule diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index cd4035164..c31f601e3 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -1,7 +1,8 @@ -import { BenchmarkService } from '@ghostfolio/api/app/benchmark/benchmark.service'; import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service'; import { UserService } from '@ghostfolio/api/app/user/user.service'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; @@ -13,27 +14,20 @@ import { PROPERTY_DEMO_USER_ID, PROPERTY_IS_READ_ONLY_MODE, PROPERTY_SLACK_COMMUNITY_USERS, - PROPERTY_STRIPE_CONFIG, - ghostfolioFearAndGreedIndexDataSource + ghostfolioFearAndGreedIndexDataSourceStocks } from '@ghostfolio/common/config'; import { DATE_FORMAT, encodeDataSource, extractNumberFromString } from '@ghostfolio/common/helper'; -import { - InfoItem, - Statistics, - SubscriptionOffer -} from '@ghostfolio/common/interfaces'; +import { InfoItem, Statistics } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; -import { SubscriptionOfferKey } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as cheerio from 'cheerio'; import { format, subDays } from 'date-fns'; -import got from 'got'; @Injectable() export class InfoService { @@ -47,6 +41,7 @@ export class InfoService { private readonly platformService: PlatformService, private readonly propertyService: PropertyService, private readonly redisCacheService: RedisCacheService, + private readonly subscriptionService: SubscriptionService, private readonly userService: UserService ) {} @@ -59,19 +54,20 @@ export class InfoService { if (this.configurationService.get('ENABLE_FEATURE_FEAR_AND_GREED_INDEX')) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { info.fearAndGreedDataSource = encodeDataSource( - ghostfolioFearAndGreedIndexDataSource + ghostfolioFearAndGreedIndexDataSourceStocks ); } else { - info.fearAndGreedDataSource = ghostfolioFearAndGreedIndexDataSource; + info.fearAndGreedDataSource = + ghostfolioFearAndGreedIndexDataSourceStocks; } globalPermissions.push(permissions.enableFearAndGreedIndex); } if (this.configurationService.get('ENABLE_FEATURE_READ_ONLY_MODE')) { - isReadOnlyMode = (await this.propertyService.getByKey( + isReadOnlyMode = await this.propertyService.getByKey( PROPERTY_IS_READ_ONLY_MODE - )) as boolean; + ); } if (this.configurationService.get('ENABLE_FEATURE_SOCIAL_LOGIN')) { @@ -86,9 +82,9 @@ export class InfoService { globalPermissions.push(permissions.enableSubscription); info.countriesOfSubscribers = - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_COUNTRIES_OF_SUBSCRIBERS - )) as string[]) ?? []; + )) ?? []; info.stripePublicKey = this.configurationService.get('STRIPE_PUBLIC_KEY'); } @@ -102,7 +98,7 @@ export class InfoService { isUserSignupEnabled, platforms, statistics, - subscriptionOffers + subscriptionOffer ] = await Promise.all([ this.benchmarkService.getBenchmarkAssetProfiles(), this.getDemoAuthToken(), @@ -111,7 +107,7 @@ export class InfoService { orderBy: { name: 'asc' } }), this.getStatistics(), - this.getSubscriptionOffers() + this.subscriptionService.getSubscriptionOffer({ key: 'default' }) ]); if (isUserSignupEnabled) { @@ -126,7 +122,7 @@ export class InfoService { isReadOnlyMode, platforms, statistics, - subscriptionOffers, + subscriptionOffer, baseCurrency: DEFAULT_CURRENCY, currencies: this.exchangeRateDataService.getCurrencies() }; @@ -138,11 +134,11 @@ export class InfoService { AND: [ { NOT: { - Analytics: null + analytics: null } }, { - Analytics: { + analytics: { lastRequestAt: { gt: subDays(new Date(), aDays) } @@ -155,16 +151,15 @@ export class InfoService { private async countDockerHubPulls(): Promise { try { - const { pull_count } = await got( - `https://hub.docker.com/v2/repositories/ghostfolio/ghostfolio`, + const { pull_count } = (await fetch( + 'https://hub.docker.com/v2/repositories/ghostfolio/ghostfolio', { headers: { 'User-Agent': 'request' }, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).json(); + ).then((res) => res.json())) as { pull_count: number }; return pull_count; } catch (error) { @@ -176,18 +171,17 @@ export class InfoService { private async countGitHubContributors(): Promise { try { - const { body } = await got('https://github.com/ghostfolio/ghostfolio', { - // @ts-ignore + const body = await fetch('https://github.com/ghostfolio/ghostfolio', { signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) - }); + }).then((res) => res.text()); const $ = cheerio.load(body); return extractNumberFromString({ value: $( - `a[href="/ghostfolio/ghostfolio/graphs/contributors"] .Counter` + 'a[href="/ghostfolio/ghostfolio/graphs/contributors"] .Counter' ).text() }); } catch (error) { @@ -199,16 +193,15 @@ export class InfoService { private async countGitHubStargazers(): Promise { try { - const { stargazers_count } = await got( - `https://api.github.com/repos/ghostfolio/ghostfolio`, + const { stargazers_count } = (await fetch( + 'https://api.github.com/repos/ghostfolio/ghostfolio', { headers: { 'User-Agent': 'request' }, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).json(); + ).then((res) => res.json())) as { stargazers_count: number }; return stargazers_count; } catch (error) { @@ -224,7 +217,7 @@ export class InfoService { AND: [ { NOT: { - Analytics: null + analytics: null } }, { @@ -238,15 +231,15 @@ export class InfoService { } private async countSlackCommunityUsers() { - return (await this.propertyService.getByKey( + return await this.propertyService.getByKey( PROPERTY_SLACK_COMMUNITY_USERS - )) as string; + ); } private async getDemoAuthToken() { - const demoUserId = (await this.propertyService.getByKey( + const demoUserId = await this.propertyService.getByKey( PROPERTY_DEMO_USER_ID - )) as string; + ); if (demoUserId) { return this.jwtService.sign({ @@ -303,27 +296,14 @@ export class InfoService { return statistics; } - private async getSubscriptionOffers(): Promise<{ - [offer in SubscriptionOfferKey]: SubscriptionOffer; - }> { - if (!this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - return undefined; - } - - return ( - ((await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) as any) ?? - {} - ); - } - private async getUptime(): Promise { { try { - const monitorId = (await this.propertyService.getByKey( + const monitorId = await this.propertyService.getByKey( PROPERTY_BETTER_UPTIME_MONITOR_ID - )) as string; + ); - const { data } = await got( + const { data } = await fetch( `https://uptime.betterstack.com/api/v2/monitors/${monitorId}/sla?from=${format( subDays(new Date(), 90), DATE_FORMAT @@ -334,12 +314,11 @@ export class InfoService { 'API_KEY_BETTER_UPTIME' )}` }, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).json(); + ).then((res) => res.json()); return data.attributes.availability / 100; } catch (error) { diff --git a/apps/api/src/app/logo/logo.controller.ts b/apps/api/src/app/logo/logo.controller.ts index 0982a793f..fdbe430c9 100644 --- a/apps/api/src/app/logo/logo.controller.ts +++ b/apps/api/src/app/logo/logo.controller.ts @@ -26,12 +26,13 @@ export class LogoController { @Res() response: Response ) { try { - const buffer = await this.logoService.getLogoByDataSourceAndSymbol({ - dataSource, - symbol - }); + const { buffer, type } = + await this.logoService.getLogoByDataSourceAndSymbol({ + dataSource, + symbol + }); - response.contentType('image/png'); + response.contentType(type); response.send(buffer); } catch { response.status(HttpStatus.NOT_FOUND).send(); @@ -44,9 +45,9 @@ export class LogoController { @Res() response: Response ) { try { - const buffer = await this.logoService.getLogoByUrl(url); + const { buffer, type } = await this.logoService.getLogoByUrl(url); - response.contentType('image/png'); + response.contentType(type); response.send(buffer); } catch { response.status(HttpStatus.NOT_FOUND).send(); diff --git a/apps/api/src/app/logo/logo.service.ts b/apps/api/src/app/logo/logo.service.ts index 759db2afb..ba1acdd29 100644 --- a/apps/api/src/app/logo/logo.service.ts +++ b/apps/api/src/app/logo/logo.service.ts @@ -4,7 +4,6 @@ import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { HttpException, Injectable } from '@nestjs/common'; import { DataSource } from '@prisma/client'; -import got from 'got'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; @Injectable() @@ -29,7 +28,7 @@ export class LogoService { { dataSource, symbol } ]); - if (!assetProfile) { + if (!assetProfile?.url) { throw new HttpException( getReasonPhrase(StatusCodes.NOT_FOUND), StatusCodes.NOT_FOUND @@ -39,20 +38,26 @@ export class LogoService { return this.getBuffer(assetProfile.url); } - public async getLogoByUrl(aUrl: string) { + public getLogoByUrl(aUrl: string) { return this.getBuffer(aUrl); } - private getBuffer(aUrl: string) { - return got( + private async getBuffer(aUrl: string) { + const blob = await fetch( `https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${aUrl}&size=64`, { headers: { 'User-Agent': 'request' }, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).buffer(); + ).then((res) => res.blob()); + + return { + buffer: await blob.arrayBuffer().then((arrayBuffer) => { + return Buffer.from(arrayBuffer); + }), + type: blob.type + }; } } diff --git a/apps/api/src/app/order/create-order.dto.ts b/apps/api/src/app/order/create-order.dto.ts index 6f52e7032..c2b10fd81 100644 --- a/apps/api/src/app/order/create-order.dto.ts +++ b/apps/api/src/app/order/create-order.dto.ts @@ -27,12 +27,12 @@ export class CreateOrderDto { @IsString() accountId?: string; - @IsOptional() @IsEnum(AssetClass, { each: true }) + @IsOptional() assetClass?: AssetClass; - @IsOptional() @IsEnum(AssetSubClass, { each: true }) + @IsOptional() assetSubClass?: AssetSubClass; @IsOptional() @@ -49,8 +49,8 @@ export class CreateOrderDto { @IsOptional() customCurrency?: string; + @IsEnum(DataSource) @IsOptional() - @IsEnum(DataSource, { each: true }) dataSource?: DataSource; @IsISO8601() diff --git a/apps/api/src/app/order/interfaces/activities.interface.ts b/apps/api/src/app/order/interfaces/activities.interface.ts index b16d10b7d..99dd87fea 100644 --- a/apps/api/src/app/order/interfaces/activities.interface.ts +++ b/apps/api/src/app/order/interfaces/activities.interface.ts @@ -9,11 +9,13 @@ export interface Activities { } export interface Activity extends Order { - Account?: AccountWithPlatform; + account?: AccountWithPlatform; error?: ActivityError; + feeInAssetProfileCurrency: number; feeInBaseCurrency: number; SymbolProfile?: EnhancedSymbolProfile; tags?: Tag[]; + unitPriceInAssetProfileCurrency: number; updateAccountBalance?: boolean; value: number; valueInBaseCurrency: number; diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index 907335aa0..cd8012cec 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -53,14 +53,19 @@ export class OrderController { @Delete() @HasPermission(permissions.deleteOrder) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @UseInterceptors(TransformDataSourceInRequestInterceptor) public async deleteOrders( @Query('accounts') filterByAccounts?: string, @Query('assetClasses') filterByAssetClasses?: string, + @Query('dataSource') filterByDataSource?: string, + @Query('symbol') filterBySymbol?: string, @Query('tags') filterByTags?: string ): Promise { const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, + filterByDataSource, + filterBySymbol, filterByTags }); @@ -97,7 +102,7 @@ export class OrderController { @UseInterceptors(TransformDataSourceInRequestInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getAllOrders( - @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId, + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Query('accounts') filterByAccounts?: string, @Query('assetClasses') filterByAssetClasses?: string, @Query('dataSource') filterByDataSource?: string, @@ -126,7 +131,7 @@ export class OrderController { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { activities, count } = await this.orderService.getOrders({ endDate, @@ -150,12 +155,12 @@ export class OrderController { @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getOrderById( - @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId, + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('id') id: string ): Promise { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { activities } = await this.orderService.getOrders({ userCurrency, @@ -184,6 +189,7 @@ export class OrderController { public async createOrder(@Body() data: CreateOrderDto): Promise { const currency = data.currency; const customCurrency = data.customCurrency; + const dataSource = data.dataSource; if (customCurrency) { data.currency = customCurrency; @@ -191,6 +197,8 @@ export class OrderController { delete data.customCurrency; } + delete data.dataSource; + const order = await this.orderService.createOrder({ ...data, date: parseISO(data.date), @@ -198,28 +206,28 @@ export class OrderController { connectOrCreate: { create: { currency, - dataSource: data.dataSource, + dataSource, symbol: data.symbol }, where: { dataSource_symbol: { - dataSource: data.dataSource, + dataSource, symbol: data.symbol } } } }, - User: { connect: { id: this.request.user.id } }, + user: { connect: { id: this.request.user.id } }, userId: this.request.user.id }); - if (data.dataSource && !order.isDraft) { + if (dataSource && !order.isDraft) { // Gather symbol data in the background, if data source is set // (not MANUAL) and not draft this.dataGatheringService.gatherSymbols({ dataGatheringItems: [ { - dataSource: data.dataSource, + dataSource, date: order.date, symbol: data.symbol } @@ -251,6 +259,7 @@ export class OrderController { const accountId = data.accountId; const customCurrency = data.customCurrency; + const dataSource = data.dataSource; delete data.accountId; @@ -260,11 +269,13 @@ export class OrderController { delete data.customCurrency; } + delete data.dataSource; + return this.orderService.updateOrder({ data: { ...data, date, - Account: { + account: { connect: { id_userId: { id: accountId, userId: this.request.user.id } } @@ -272,7 +283,7 @@ export class OrderController { SymbolProfile: { connect: { dataSource_symbol: { - dataSource: data.dataSource, + dataSource, symbol: data.symbol } }, @@ -282,7 +293,7 @@ export class OrderController { name: data.symbol } }, - User: { connect: { id: this.request.user.id } } + user: { connect: { id: this.request.user.id } } }, where: { id diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index e80811351..21fa0d076 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -7,8 +7,9 @@ import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathe import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, - GATHER_ASSET_PROFILE_PROCESS, - GATHER_ASSET_PROFILE_PROCESS_OPTIONS + GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, + GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, + ghostfolioPrefix } from '@ghostfolio/common/config'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { @@ -30,6 +31,7 @@ import { Type as ActivityType } from '@prisma/client'; import { Big } from 'big.js'; +import { isUUID } from 'class-validator'; import { endOfToday, isAfter } from 'date-fns'; import { groupBy, uniqBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; @@ -63,14 +65,14 @@ export class OrderService { } }); - return Promise.all( + await Promise.all( orders.map(({ id }) => this.prismaService.order.update({ data: { tags: { // The set operation replaces all existing connections with the provided ones - set: tags.map(({ id }) => { - return { id }; + set: tags.map((tag) => { + return { id: tag.id }; }) } }, @@ -78,6 +80,13 @@ export class OrderService { }) ) ); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId + }) + ); } public async createOrder( @@ -86,17 +95,16 @@ export class OrderService { assetClass?: AssetClass; assetSubClass?: AssetSubClass; currency?: string; - dataSource?: DataSource; symbol?: string; tags?: Tag[]; updateAccountBalance?: boolean; userId: string; } ): Promise { - let Account: Prisma.AccountCreateNestedOneWithoutOrderInput; + let account: Prisma.AccountCreateNestedOneWithoutActivitiesInput; if (data.accountId) { - Account = { + account = { connect: { id_userId: { userId: data.userId, @@ -111,23 +119,41 @@ export class OrderService { const updateAccountBalance = data.updateAccountBalance ?? false; const userId = data.userId; - if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) { + if ( + ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) || + (data.SymbolProfile.connectOrCreate.create.dataSource === 'MANUAL' && + data.type === 'BUY') + ) { const assetClass = data.assetClass; const assetSubClass = data.assetSubClass; const dataSource: DataSource = 'MANUAL'; - const id = uuidv4(); - const name = data.SymbolProfile.connectOrCreate.create.symbol; - data.id = id; + let name: string; + let symbol: string; + + if ( + data.SymbolProfile.connectOrCreate.create.symbol.startsWith( + `${ghostfolioPrefix}_` + ) || + isUUID(data.SymbolProfile.connectOrCreate.create.symbol) + ) { + // Connect custom asset profile (clone) + symbol = data.SymbolProfile.connectOrCreate.create.symbol; + } else { + // Create custom asset profile + name = data.SymbolProfile.connectOrCreate.create.symbol; + symbol = uuidv4(); + } + data.SymbolProfile.connectOrCreate.create.assetClass = assetClass; data.SymbolProfile.connectOrCreate.create.assetSubClass = assetSubClass; data.SymbolProfile.connectOrCreate.create.dataSource = dataSource; data.SymbolProfile.connectOrCreate.create.name = name; - data.SymbolProfile.connectOrCreate.create.symbol = id; + data.SymbolProfile.connectOrCreate.create.symbol = symbol; data.SymbolProfile.connectOrCreate.create.userId = userId; data.SymbolProfile.connectOrCreate.where.dataSource_symbol = { dataSource, - symbol: id + symbol }; } @@ -137,9 +163,9 @@ export class OrderService { dataSource: data.SymbolProfile.connectOrCreate.create.dataSource, symbol: data.SymbolProfile.connectOrCreate.create.symbol }, - name: GATHER_ASSET_PROFILE_PROCESS, + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, opts: { - ...GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + ...GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, jobId: getAssetProfileIdentifier({ dataSource: data.SymbolProfile.connectOrCreate.create.dataSource, symbol: data.SymbolProfile.connectOrCreate.create.symbol @@ -157,7 +183,6 @@ export class OrderService { delete data.comment; } - delete data.dataSource; delete data.symbol; delete data.tags; delete data.updateAccountBalance; @@ -165,14 +190,14 @@ export class OrderService { const orderData: Prisma.OrderCreateInput = data; - const isDraft = ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type) + const isDraft = ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) ? false : isAfter(data.date as Date, endOfToday()); const order = await this.prismaService.order.create({ data: { ...orderData, - Account, + account, isDraft, tags: { connect: tags.map(({ id }) => { @@ -468,8 +493,8 @@ export class OrderService { if (withExcludedAccounts === false) { where.OR = [ - { Account: null }, - { Account: { NOT: { isExcluded: true } } } + { account: null }, + { account: { NOT: { isExcluded: true } } } ]; } @@ -480,10 +505,9 @@ export class OrderService { take, where, include: { - // eslint-disable-next-line @typescript-eslint/naming-convention - Account: { + account: { include: { - Platform: true + platform: true } }, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -524,24 +548,46 @@ export class OrderService { const value = new Big(order.quantity).mul(order.unitPrice).toNumber(); + const [ + feeInAssetProfileCurrency, + feeInBaseCurrency, + unitPriceInAssetProfileCurrency, + valueInBaseCurrency + ] = await Promise.all([ + this.exchangeRateDataService.toCurrencyAtDate( + order.fee, + order.currency ?? order.SymbolProfile.currency, + order.SymbolProfile.currency, + order.date + ), + this.exchangeRateDataService.toCurrencyAtDate( + order.fee, + order.currency ?? order.SymbolProfile.currency, + userCurrency, + order.date + ), + this.exchangeRateDataService.toCurrencyAtDate( + order.unitPrice, + order.currency ?? order.SymbolProfile.currency, + order.SymbolProfile.currency, + order.date + ), + this.exchangeRateDataService.toCurrencyAtDate( + value, + order.currency ?? order.SymbolProfile.currency, + userCurrency, + order.date + ) + ]); + return { ...order, + feeInAssetProfileCurrency, + feeInBaseCurrency, + unitPriceInAssetProfileCurrency, value, - feeInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - order.fee, - order.SymbolProfile.currency, - userCurrency, - order.date - ), - SymbolProfile: assetProfile, - valueInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - value, - order.SymbolProfile.currency, - userCurrency, - order.date - ) + valueInBaseCurrency, + SymbolProfile: assetProfile }; }) ); @@ -603,7 +649,6 @@ export class OrderService { assetClass?: AssetClass; assetSubClass?: AssetSubClass; currency?: string; - dataSource?: DataSource; symbol?: string; tags?: Tag[]; type?: ActivityType; @@ -618,12 +663,17 @@ export class OrderService { let isDraft = false; - if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) { - delete data.SymbolProfile.connect; - - if (data.Account?.connect?.id_userId?.id === null) { - data.Account = { disconnect: true }; + if ( + ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) || + (data.SymbolProfile.connect.dataSource_symbol.dataSource === 'MANUAL' && + data.type === 'BUY') + ) { + if (data.account?.connect?.id_userId?.id === null) { + data.account = { disconnect: true }; } + + delete data.SymbolProfile.connect; + delete data.SymbolProfile.update.name; } else { delete data.SymbolProfile.update; @@ -647,17 +697,17 @@ export class OrderService { delete data.assetClass; delete data.assetSubClass; - delete data.dataSource; delete data.symbol; delete data.tags; // Remove existing tags await this.prismaService.order.update({ - data: { tags: { set: [] } }, - where + where, + data: { tags: { set: [] } } }); const order = await this.prismaService.order.update({ + where, data: { ...data, isDraft, @@ -666,8 +716,7 @@ export class OrderService { return { id }; }) } - }, - where + } }); this.eventEmitter.emit( diff --git a/apps/api/src/app/platform/platform.service.ts b/apps/api/src/app/platform/platform.service.ts index db827569d..200b4de00 100644 --- a/apps/api/src/app/platform/platform.service.ts +++ b/apps/api/src/app/platform/platform.service.ts @@ -54,7 +54,7 @@ export class PlatformService { await this.prismaService.platform.findMany({ include: { _count: { - select: { Account: true } + select: { accounts: true } } } }); @@ -64,7 +64,7 @@ export class PlatformService { id, name, url, - accountCount: _count.Account + accountCount: _count.accounts }; }); } diff --git a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts index e54f63422..1460892fa 100644 --- a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts @@ -4,12 +4,17 @@ import { SymbolMetrics } from '@ghostfolio/common/interfaces'; import { PortfolioSnapshot } from '@ghostfolio/common/models'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; -export class MWRPortfolioCalculator extends PortfolioCalculator { +export class MwrPortfolioCalculator extends PortfolioCalculator { protected calculateOverallPerformance(): PortfolioSnapshot { throw new Error('Method not implemented.'); } + protected getPerformanceCalculationType() { + return PerformanceCalculationType.MWR; + } + protected getSymbolMetrics({}: { end: Date; exchangeRates: { [dateString: string]: number }; diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts index 217ec499b..6208eb7d7 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts @@ -6,10 +6,14 @@ export const activityDummyData = { comment: undefined, createdAt: new Date(), currency: undefined, + fee: undefined, + feeInAssetProfileCurrency: undefined, feeInBaseCurrency: undefined, id: undefined, isDraft: false, symbolProfileId: undefined, + unitPrice: undefined, + unitPriceInAssetProfileCurrency: undefined, updatedAt: new Date(), userId: undefined, value: undefined, @@ -24,6 +28,7 @@ export const symbolProfileDummyData = { createdAt: undefined, holdings: [], id: undefined, + isActive: true, sectors: [], updatedAt: undefined }; diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts index 18738373e..24fe2b2f3 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts @@ -5,17 +5,15 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/con import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { Filter, HistoricalDataItem } from '@ghostfolio/common/interfaces'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Injectable } from '@nestjs/common'; -import { MWRPortfolioCalculator } from './mwr/portfolio-calculator'; +import { MwrPortfolioCalculator } from './mwr/portfolio-calculator'; import { PortfolioCalculator } from './portfolio-calculator'; -import { TWRPortfolioCalculator } from './twr/portfolio-calculator'; - -export enum PerformanceCalculationType { - MWR = 'MWR', // Money-Weighted Rate of Return - TWR = 'TWR' // Time-Weighted Rate of Return -} +import { RoaiPortfolioCalculator } from './roai/portfolio-calculator'; +import { RoiPortfolioCalculator } from './roi/portfolio-calculator'; +import { TwrPortfolioCalculator } from './twr/portfolio-calculator'; @Injectable() export class PortfolioCalculatorFactory { @@ -44,7 +42,7 @@ export class PortfolioCalculatorFactory { }): PortfolioCalculator { switch (calculationType) { case PerformanceCalculationType.MWR: - return new MWRPortfolioCalculator({ + return new MwrPortfolioCalculator({ accountBalanceItems, activities, currency, @@ -56,19 +54,49 @@ export class PortfolioCalculatorFactory { portfolioSnapshotService: this.portfolioSnapshotService, redisCacheService: this.redisCacheService }); - case PerformanceCalculationType.TWR: - return new TWRPortfolioCalculator({ + + case PerformanceCalculationType.ROAI: + return new RoaiPortfolioCalculator({ + accountBalanceItems, + activities, + currency, + filters, + userId, + configurationService: this.configurationService, + currentRateService: this.currentRateService, + exchangeRateDataService: this.exchangeRateDataService, + portfolioSnapshotService: this.portfolioSnapshotService, + redisCacheService: this.redisCacheService + }); + + case PerformanceCalculationType.ROI: + return new RoiPortfolioCalculator({ accountBalanceItems, activities, currency, + filters, + userId, + configurationService: this.configurationService, currentRateService: this.currentRateService, + exchangeRateDataService: this.exchangeRateDataService, + portfolioSnapshotService: this.portfolioSnapshotService, + redisCacheService: this.redisCacheService + }); + + case PerformanceCalculationType.TWR: + return new TwrPortfolioCalculator({ + accountBalanceItems, + activities, + currency, filters, userId, configurationService: this.configurationService, + currentRateService: this.currentRateService, exchangeRateDataService: this.exchangeRateDataService, portfolioSnapshotService: this.portfolioSnapshotService, redisCacheService: this.redisCacheService }); + default: throw new Error('Invalid calculation type'); } diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index eb18b3584..78323a332 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -13,6 +13,7 @@ import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfac import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { + INVESTMENT_ACTIVITY_TYPES, PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS, PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_HIGH, @@ -35,6 +36,7 @@ import { } from '@ghostfolio/common/interfaces'; import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; import { GroupBy } from '@ghostfolio/common/types'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; @@ -49,7 +51,7 @@ import { min, subDays } from 'date-fns'; -import { first, isNumber, last, sortBy, sum, uniq, uniqBy } from 'lodash'; +import { isNumber, sortBy, sum, uniqBy } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; @@ -112,12 +114,12 @@ export abstract class PortfolioCalculator { .map( ({ date, - fee, + feeInAssetProfileCurrency, quantity, SymbolProfile, tags = [], type, - unitPrice + unitPriceInAssetProfileCurrency }) => { if (isBefore(date, dateOfFirstActivity)) { dateOfFirstActivity = date; @@ -134,9 +136,9 @@ export abstract class PortfolioCalculator { tags, type, date: format(date, DATE_FORMAT), - fee: new Big(fee), + fee: new Big(feeInAssetProfileCurrency), quantity: new Big(quantity), - unitPrice: new Big(unitPrice) + unitPrice: new Big(unitPriceInAssetProfileCurrency) }; } ) @@ -167,7 +169,7 @@ export abstract class PortfolioCalculator { @LogPerformance public async computeSnapshot(): Promise { - const lastTransactionPoint = last(this.transactionPoints); + const lastTransactionPoint = this.transactionPoints.at(-1); const transactionPoints = this.transactionPoints?.filter(({ date }) => { return isBefore(parseDate(date), this.endDate); @@ -175,6 +177,8 @@ export abstract class PortfolioCalculator { if (!transactionPoints.length) { return { + activitiesCount: 0, + createdAt: new Date(), currentValueInBaseCurrency: new Big(0), errors: [], hasErrors: false, @@ -184,8 +188,7 @@ export abstract class PortfolioCalculator { totalInterestWithCurrencyEffect: new Big(0), totalInvestment: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0), - totalLiabilitiesWithCurrencyEffect: new Big(0), - totalValuablesWithCurrencyEffect: new Big(0) + totalLiabilitiesWithCurrencyEffect: new Big(0) }; } @@ -195,7 +198,6 @@ export abstract class PortfolioCalculator { let firstTransactionPoint: TransactionPoint = null; let totalInterestWithCurrencyEffect = new Big(0); let totalLiabilitiesWithCurrencyEffect = new Big(0); - let totalValuablesWithCurrencyEffect = new Big(0); for (const { currency, dataSource, symbol } of transactionPoints[ firstIndex - 1 @@ -220,7 +222,7 @@ export abstract class PortfolioCalculator { const exchangeRatesByCurrency = await this.exchangeRateDataService.getExchangeRatesByCurrency({ - currencies: uniq(Object.values(currencies)), + currencies: Array.from(new Set(Object.values(currencies))), endDate: endOfDay(this.endDate), startDate: this.startDate, targetCurrency: this.currency @@ -286,10 +288,12 @@ export abstract class PortfolioCalculator { firstIndex--; } - const positions: TimelinePosition[] = []; + const errors: ResponseError['errors'] = []; let hasAnySymbolMetricsErrors = false; - const errors: ResponseError['errors'] = []; + const positions: (TimelinePosition & { + includeInHoldings: boolean; + })[] = []; const accumulatedValuesByDate: { [date: string]: { @@ -361,8 +365,7 @@ export abstract class PortfolioCalculator { totalInterestInBaseCurrency, totalInvestment, totalInvestmentWithCurrencyEffect, - totalLiabilitiesInBaseCurrency, - totalValuablesInBaseCurrency + totalLiabilitiesInBaseCurrency } = this.getSymbolMetrics({ chartDateMap, marketSymbolMap, @@ -409,6 +412,7 @@ export abstract class PortfolioCalculator { grossPerformanceWithCurrencyEffect: !hasErrors ? (grossPerformanceWithCurrencyEffect ?? null) : null, + includeInHoldings: item.includeInHoldings, investment: totalInvestment, investmentWithCurrencyEffect: totalInvestmentWithCurrencyEffect, marketPrice: @@ -441,16 +445,13 @@ export abstract class PortfolioCalculator { totalLiabilitiesWithCurrencyEffect = totalLiabilitiesWithCurrencyEffect.plus(totalLiabilitiesInBaseCurrency); - totalValuablesWithCurrencyEffect = totalValuablesWithCurrencyEffect.plus( - totalValuablesInBaseCurrency - ); - if ( (hasErrors || currentRateErrors.find(({ dataSource, symbol }) => { return dataSource === item.dataSource && symbol === item.symbol; })) && - item.investment.gt(0) + item.investment.gt(0) && + item.skipErrors === false ) { errors.push({ dataSource: item.dataSource, symbol: item.symbol }); } @@ -594,7 +595,6 @@ export abstract class PortfolioCalculator { netPerformance: totalNetPerformanceValue.toNumber(), netPerformanceWithCurrencyEffect: totalNetPerformanceValueWithCurrencyEffect.toNumber(), - // TODO: Add valuables netWorth: totalCurrentValueWithCurrencyEffect .plus(totalAccountBalanceWithCurrencyEffect) .toNumber(), @@ -609,18 +609,28 @@ export abstract class PortfolioCalculator { const overall = this.calculateOverallPerformance(positions); + const positionsIncludedInHoldings = positions + .filter(({ includeInHoldings }) => { + return includeInHoldings; + }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ includeInHoldings, ...rest }) => { + return rest; + }); + return { ...overall, errors, historicalData, - positions, totalInterestWithCurrencyEffect, totalLiabilitiesWithCurrencyEffect, - totalValuablesWithCurrencyEffect, - hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors + hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors, + positions: positionsIncludedInHoldings }; } + protected abstract getPerformanceCalculationType(): PerformanceCalculationType; + public getDataProviderInfos() { return this.dataProviderInfos; } @@ -749,7 +759,7 @@ export abstract class PortfolioCalculator { ? 0 : netPerformanceWithCurrencyEffectSinceStartDate / timeWeightedInvestmentValue - // TODO: Add net worth with valuables + // TODO: Add net worth // netWorth: totalCurrentValueWithCurrencyEffect // .plus(totalAccountBalanceWithCurrencyEffect) // .toNumber() @@ -772,9 +782,7 @@ export abstract class PortfolioCalculator { let firstActivityDate: Date; try { - const firstAccountBalanceDateString = first( - this.accountBalanceItems - )?.date; + const firstAccountBalanceDateString = this.accountBalanceItems[0]?.date; firstAccountBalanceDate = firstAccountBalanceDateString ? parseDate(firstAccountBalanceDateString) : new Date(); @@ -816,12 +824,6 @@ export abstract class PortfolioCalculator { return this.transactionPoints; } - public async getValuablesInBaseCurrency() { - await this.snapshotPromise; - - return this.snapshot.totalValuablesWithCurrencyEffect; - } - private getChartDateMap({ endDate, startDate, @@ -899,8 +901,8 @@ export abstract class PortfolioCalculator { let lastTransactionPoint: TransactionPoint = null; for (const { - fee, date, + fee, quantity, SymbolProfile, tags, @@ -908,9 +910,14 @@ export abstract class PortfolioCalculator { unitPrice } of this.activities) { let currentTransactionPointItem: TransactionPointSymbol; - const oldAccumulatedSymbol = symbols[SymbolProfile.symbol]; + const currency = SymbolProfile.currency; + const dataSource = SymbolProfile.dataSource; const factor = getFactor(type); + const skipErrors = !!SymbolProfile.userId; // Skip errors for custom asset profiles + const symbol = SymbolProfile.symbol; + + const oldAccumulatedSymbol = symbols[symbol]; if (oldAccumulatedSymbol) { let investment = oldAccumulatedSymbol.investment; @@ -930,32 +937,36 @@ export abstract class PortfolioCalculator { } currentTransactionPointItem = { + currency, + dataSource, investment, + skipErrors, + symbol, averagePrice: newQuantity.gt(0) ? investment.div(newQuantity) : new Big(0), - currency: SymbolProfile.currency, - dataSource: SymbolProfile.dataSource, dividend: new Big(0), fee: oldAccumulatedSymbol.fee.plus(fee), firstBuyDate: oldAccumulatedSymbol.firstBuyDate, + includeInHoldings: oldAccumulatedSymbol.includeInHoldings, quantity: newQuantity, - symbol: SymbolProfile.symbol, tags: oldAccumulatedSymbol.tags.concat(tags), transactionCount: oldAccumulatedSymbol.transactionCount + 1 }; } else { currentTransactionPointItem = { + currency, + dataSource, fee, + skipErrors, + symbol, tags, averagePrice: unitPrice, - currency: SymbolProfile.currency, - dataSource: SymbolProfile.dataSource, dividend: new Big(0), firstBuyDate: date, + includeInHoldings: INVESTMENT_ACTIVITY_TYPES.includes(type), investment: unitPrice.mul(quantity).mul(factor), quantity: quantity.mul(factor), - symbol: SymbolProfile.symbol, transactionCount: 1 }; } @@ -997,19 +1008,12 @@ export abstract class PortfolioCalculator { liabilities = quantity.mul(unitPrice); } - let valuables = new Big(0); - - if (type === 'ITEM') { - valuables = quantity.mul(unitPrice); - } - if (lastDate !== date || lastTransactionPoint === null) { lastTransactionPoint = { date, fees, interest, liabilities, - valuables, items: newItems }; @@ -1021,8 +1025,6 @@ export abstract class PortfolioCalculator { lastTransactionPoint.items = newItems; lastTransactionPoint.liabilities = lastTransactionPoint.liabilities.plus(liabilities); - lastTransactionPoint.valuables = - lastTransactionPoint.valuables.plus(valuables); } lastDate = date; @@ -1073,6 +1075,7 @@ export abstract class PortfolioCalculator { // Compute in the background this.portfolioSnapshotService.addJobToQueue({ data: { + calculationType: this.getPerformanceCalculationType(), filters: this.filters, userCurrency: this.currency, userId: this.userId @@ -1089,6 +1092,7 @@ export abstract class PortfolioCalculator { // Wait for computation await this.portfolioSnapshotService.addJobToQueue({ data: { + calculationType: this.getPerformanceCalculationType(), filters: this.filters, userCurrency: this.currency, userId: this.userId diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts similarity index 88% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index 37499f0e3..ab8000702 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,9 +14,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -92,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-22'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -102,12 +99,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 142.9 + unitPriceInAssetProfileCurrency: 142.9 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.65, + feeInAssetProfileCurrency: 1.65, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -117,12 +114,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -132,13 +129,13 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -197,11 +194,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: -15.8, netPerformanceInPercentage: -0.05528341497550734703, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts similarity index 92% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts index 23c594e5b..cc65fa8a2 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,9 +14,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -92,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-22'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -102,12 +99,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 142.9 + unitPriceInAssetProfileCurrency: 142.9 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.65, + feeInAssetProfileCurrency: 1.65, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -117,13 +114,13 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -182,11 +179,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: -15.8, netPerformanceInPercentage: -0.05528341497550734703, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts similarity index 69% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts index 90f6a59d1..7d9544666 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,9 +14,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -92,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -102,13 +99,13 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -173,11 +170,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('273.2'), totalInvestmentWithCurrencyEffect: new Big('273.2'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 23.05, netPerformanceInPercentage: 0.08437042459736457, @@ -196,5 +192,83 @@ describe('PortfolioCalculator', () => { { date: '2021-12-01', investment: 0 } ]); }); + + it.only('with BALN.SW buy (with unit price lower than closing price)', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2021-12-18').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + date: new Date('2021-11-30'), + feeInAssetProfileCurrency: 1.55, + quantity: 2, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'CHF', + dataSource: 'YAHOO', + name: 'Bâloise Holding AG', + symbol: 'BALN.SW' + }, + type: 'BUY', + unitPriceInAssetProfileCurrency: 135.0 + } + ]; + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'CHF', + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + const snapshotOnBuyDate = portfolioSnapshot.historicalData.find( + ({ date }) => { + return date === '2021-11-30'; + } + ); + + // Closing price on 2021-11-30: 136.6 + expect(snapshotOnBuyDate?.netPerformanceWithCurrencyEffect).toEqual(1.65); // 2 * (136.6 - 135.0) - 1.55 = 1.65 + }); + + it.only('with BALN.SW buy (with unit price lower than closing price), calculated on buy date', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2021-11-30').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + date: new Date('2021-11-30'), + feeInAssetProfileCurrency: 1.55, + quantity: 2, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'CHF', + dataSource: 'YAHOO', + name: 'Bâloise Holding AG', + symbol: 'BALN.SW' + }, + type: 'BUY', + unitPriceInAssetProfileCurrency: 135.0 + } + ]; + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'CHF', + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + const snapshotOnBuyDate = portfolioSnapshot.historicalData.find( + ({ date }) => { + return date === '2021-11-30'; + } + ); + + // Closing price on 2021-11-30: 136.6 + expect(snapshotOnBuyDate?.netPerformanceWithCurrencyEffect).toEqual(1.65); // 2 * (136.6 - 135.0) - 1.55 = 1.65 + }); }); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts new file mode 100644 index 000000000..3594b4427 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts @@ -0,0 +1,240 @@ +import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + loadActivityExportFile, + symbolProfileDummyData, + userDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; +import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; +import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +import { Big } from 'big.js'; +import { join } from 'path'; + +jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + CurrentRateService: jest.fn().mockImplementation(() => { + return CurrentRateServiceMock; + }) + }; +}); + +jest.mock( + '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service', + () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + PortfolioSnapshotService: jest.fn().mockImplementation(() => { + return PortfolioSnapshotServiceMock; + }) + }; + } +); + +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + +describe('PortfolioCalculator', () => { + let activityDtos: CreateOrderDto[]; + + let configurationService: ConfigurationService; + let currentRateService: CurrentRateService; + let exchangeRateDataService: ExchangeRateDataService; + let portfolioCalculatorFactory: PortfolioCalculatorFactory; + let portfolioSnapshotService: PortfolioSnapshotService; + let redisCacheService: RedisCacheService; + + beforeAll(() => { + activityDtos = loadActivityExportFile( + join(__dirname, '../../../../../../../test/import/ok/btceur.json') + ); + }); + + beforeEach(() => { + configurationService = new ConfigurationService(); + + currentRateService = new CurrentRateService(null, null, null, null); + + exchangeRateDataService = new ExchangeRateDataService( + null, + null, + null, + null + ); + + portfolioSnapshotService = new PortfolioSnapshotService(null); + + redisCacheService = new RedisCacheService(null, null); + + portfolioCalculatorFactory = new PortfolioCalculatorFactory( + configurationService, + currentRateService, + exchangeRateDataService, + portfolioSnapshotService, + redisCacheService + ); + }); + + describe('get current positions', () => { + it.only('with BTCUSD buy (in EUR)', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2022-01-14').getTime()); + + const activities: Activity[] = activityDtos.map((activity) => ({ + ...activityDummyData, + ...activity, + date: parseDate(activity.date), + feeInAssetProfileCurrency: 4.46, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'USD', + dataSource: activity.dataSource, + name: 'Bitcoin', + symbol: activity.symbol + }, + unitPriceInAssetProfileCurrency: 44558.42 + })); + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'USD', + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + + const investments = portfolioCalculator.getInvestments(); + + const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({ + data: portfolioSnapshot.historicalData, + groupBy: 'month' + }); + + expect(portfolioSnapshot.historicalData[0]).toEqual({ + date: '2021-12-11', + investmentValueWithCurrencyEffect: 0, + netPerformance: 0, + netPerformanceInPercentage: 0, + netPerformanceInPercentageWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, + netWorth: 0, + totalAccountBalance: 0, + totalInvestment: 0, + totalInvestmentValueWithCurrencyEffect: 0, + value: 0, + valueWithCurrencyEffect: 0 + }); + + /** + * Closing price on 2021-12-12: 50098.3 + */ + expect(portfolioSnapshot.historicalData[1]).toEqual({ + date: '2021-12-12', + investmentValueWithCurrencyEffect: 44558.42, + netPerformance: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 + netPerformanceInPercentage: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 + netPerformanceInPercentageWithCurrencyEffect: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 + netPerformanceWithCurrencyEffect: 5535.42, + netWorth: 50098.3, // 1 * 50098.3 = 50098.3 + totalAccountBalance: 0, + totalInvestment: 44558.42, + totalInvestmentValueWithCurrencyEffect: 44558.42, + value: 50098.3, // 1 * 50098.3 = 50098.3 + valueWithCurrencyEffect: 50098.3 + }); + + expect( + portfolioSnapshot.historicalData[ + portfolioSnapshot.historicalData.length - 1 + ] + ).toEqual({ + date: '2022-01-14', + investmentValueWithCurrencyEffect: 0, + netPerformance: -1463.18, + netPerformanceInPercentage: -0.032837340282712, + netPerformanceInPercentageWithCurrencyEffect: -0.032837340282712, + netPerformanceWithCurrencyEffect: -1463.18, + netWorth: 43099.7, + totalAccountBalance: 0, + totalInvestment: 44558.42, + totalInvestmentValueWithCurrencyEffect: 44558.42, + value: 43099.7, + valueWithCurrencyEffect: 43099.7 + }); + + expect(portfolioSnapshot).toMatchObject({ + currentValueInBaseCurrency: new Big('43099.7'), + errors: [], + hasErrors: false, + positions: [ + { + averagePrice: new Big('44558.42'), + currency: 'USD', + dataSource: 'YAHOO', + dividend: new Big('0'), + dividendInBaseCurrency: new Big('0'), + fee: new Big('4.46'), + feeInBaseCurrency: new Big('4.46'), + firstBuyDate: '2021-12-12', + grossPerformance: new Big('-1458.72'), + grossPerformancePercentage: new Big('-0.03273724696701543726'), + grossPerformancePercentageWithCurrencyEffect: new Big( + '-0.03273724696701543726' + ), + grossPerformanceWithCurrencyEffect: new Big('-1458.72'), + investment: new Big('44558.42'), + investmentWithCurrencyEffect: new Big('44558.42'), + netPerformance: new Big('-1463.18'), + netPerformancePercentage: new Big('-0.03283734028271199921'), + netPerformancePercentageWithCurrencyEffectMap: { + max: new Big('-0.03283734028271199921') + }, + netPerformanceWithCurrencyEffectMap: { + max: new Big('-1463.18') + }, + marketPrice: 43099.7, + marketPriceInBaseCurrency: 43099.7, + quantity: new Big('1'), + symbol: 'BTCUSD', + tags: [], + timeWeightedInvestment: new Big('44558.42'), + timeWeightedInvestmentWithCurrencyEffect: new Big('44558.42'), + transactionCount: 1, + valueInBaseCurrency: new Big('43099.7') + } + ], + totalFeesWithCurrencyEffect: new Big('4.46'), + totalInterestWithCurrencyEffect: new Big('0'), + totalInvestment: new Big('44558.42'), + totalInvestmentWithCurrencyEffect: new Big('44558.42'), + totalLiabilitiesWithCurrencyEffect: new Big('0') + }); + + expect(investments).toEqual([ + { date: '2021-12-12', investment: new Big('44558.42') } + ]); + + expect(investmentsByMonth).toEqual([ + { date: '2021-12-01', investment: 44558.42 }, + { date: '2022-01-01', investment: 0 } + ]); + }); + }); +}); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts similarity index 94% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index e232b42c4..de3f5d3cd 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -18,9 +15,9 @@ import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-r import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -106,7 +103,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2015-01-01'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -116,12 +113,12 @@ describe('PortfolioCalculator', () => { symbol: 'BTCUSD' }, type: 'BUY', - unitPrice: 320.43 + unitPriceInAssetProfileCurrency: 320.43 }, { ...activityDummyData, date: new Date('2017-12-31'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -131,13 +128,13 @@ describe('PortfolioCalculator', () => { symbol: 'BTCUSD' }, type: 'SELL', - unitPrice: 14156.4 + unitPriceInAssetProfileCurrency: 14156.4 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -201,11 +198,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('320.43').mul(0.97373), totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: new Big('27172.74').mul(0.97373).toNumber(), netPerformanceInPercentage: 42.41983590271396609433, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts new file mode 100644 index 000000000..d1d9fbd93 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts @@ -0,0 +1,240 @@ +import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + loadActivityExportFile, + symbolProfileDummyData, + userDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; +import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; +import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +import { Big } from 'big.js'; +import { join } from 'path'; + +jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + CurrentRateService: jest.fn().mockImplementation(() => { + return CurrentRateServiceMock; + }) + }; +}); + +jest.mock( + '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service', + () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + PortfolioSnapshotService: jest.fn().mockImplementation(() => { + return PortfolioSnapshotServiceMock; + }) + }; + } +); + +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + +describe('PortfolioCalculator', () => { + let activityDtos: CreateOrderDto[]; + + let configurationService: ConfigurationService; + let currentRateService: CurrentRateService; + let exchangeRateDataService: ExchangeRateDataService; + let portfolioCalculatorFactory: PortfolioCalculatorFactory; + let portfolioSnapshotService: PortfolioSnapshotService; + let redisCacheService: RedisCacheService; + + beforeAll(() => { + activityDtos = loadActivityExportFile( + join(__dirname, '../../../../../../../test/import/ok/btcusd.json') + ); + }); + + beforeEach(() => { + configurationService = new ConfigurationService(); + + currentRateService = new CurrentRateService(null, null, null, null); + + exchangeRateDataService = new ExchangeRateDataService( + null, + null, + null, + null + ); + + portfolioSnapshotService = new PortfolioSnapshotService(null); + + redisCacheService = new RedisCacheService(null, null); + + portfolioCalculatorFactory = new PortfolioCalculatorFactory( + configurationService, + currentRateService, + exchangeRateDataService, + portfolioSnapshotService, + redisCacheService + ); + }); + + describe('get current positions', () => { + it.only('with BTCUSD buy (in USD)', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2022-01-14').getTime()); + + const activities: Activity[] = activityDtos.map((activity) => ({ + ...activityDummyData, + ...activity, + date: parseDate(activity.date), + feeInAssetProfileCurrency: 4.46, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'USD', + dataSource: activity.dataSource, + name: 'Bitcoin', + symbol: activity.symbol + }, + unitPriceInAssetProfileCurrency: 44558.42 + })); + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'USD', + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + + const investments = portfolioCalculator.getInvestments(); + + const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({ + data: portfolioSnapshot.historicalData, + groupBy: 'month' + }); + + expect(portfolioSnapshot.historicalData[0]).toEqual({ + date: '2021-12-11', + investmentValueWithCurrencyEffect: 0, + netPerformance: 0, + netPerformanceInPercentage: 0, + netPerformanceInPercentageWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, + netWorth: 0, + totalAccountBalance: 0, + totalInvestment: 0, + totalInvestmentValueWithCurrencyEffect: 0, + value: 0, + valueWithCurrencyEffect: 0 + }); + + /** + * Closing price on 2021-12-12: 50098.3 + */ + expect(portfolioSnapshot.historicalData[1]).toEqual({ + date: '2021-12-12', + investmentValueWithCurrencyEffect: 44558.42, + netPerformance: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 + netPerformanceInPercentage: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 + netPerformanceInPercentageWithCurrencyEffect: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 + netPerformanceWithCurrencyEffect: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 + netWorth: 50098.3, // 1 * 50098.3 = 50098.3 + totalAccountBalance: 0, + totalInvestment: 44558.42, + totalInvestmentValueWithCurrencyEffect: 44558.42, + value: 50098.3, // 1 * 50098.3 = 50098.3 + valueWithCurrencyEffect: 50098.3 + }); + + expect( + portfolioSnapshot.historicalData[ + portfolioSnapshot.historicalData.length - 1 + ] + ).toEqual({ + date: '2022-01-14', + investmentValueWithCurrencyEffect: 0, + netPerformance: -1463.18, + netPerformanceInPercentage: -0.032837340282712, + netPerformanceInPercentageWithCurrencyEffect: -0.032837340282712, + netPerformanceWithCurrencyEffect: -1463.18, + netWorth: 43099.7, + totalAccountBalance: 0, + totalInvestment: 44558.42, + totalInvestmentValueWithCurrencyEffect: 44558.42, + value: 43099.7, + valueWithCurrencyEffect: 43099.7 + }); + + expect(portfolioSnapshot).toMatchObject({ + currentValueInBaseCurrency: new Big('43099.7'), + errors: [], + hasErrors: false, + positions: [ + { + averagePrice: new Big('44558.42'), + currency: 'USD', + dataSource: 'YAHOO', + dividend: new Big('0'), + dividendInBaseCurrency: new Big('0'), + fee: new Big('4.46'), + feeInBaseCurrency: new Big('4.46'), + firstBuyDate: '2021-12-12', + grossPerformance: new Big('-1458.72'), + grossPerformancePercentage: new Big('-0.03273724696701543726'), + grossPerformancePercentageWithCurrencyEffect: new Big( + '-0.03273724696701543726' + ), + grossPerformanceWithCurrencyEffect: new Big('-1458.72'), + investment: new Big('44558.42'), + investmentWithCurrencyEffect: new Big('44558.42'), + netPerformance: new Big('-1463.18'), + netPerformancePercentage: new Big('-0.03283734028271199921'), + netPerformancePercentageWithCurrencyEffectMap: { + max: new Big('-0.03283734028271199921') + }, + netPerformanceWithCurrencyEffectMap: { + max: new Big('-1463.18') + }, + marketPrice: 43099.7, + marketPriceInBaseCurrency: 43099.7, + quantity: new Big('1'), + symbol: 'BTCUSD', + tags: [], + timeWeightedInvestment: new Big('44558.42'), + timeWeightedInvestmentWithCurrencyEffect: new Big('44558.42'), + transactionCount: 1, + valueInBaseCurrency: new Big('43099.7') + } + ], + totalFeesWithCurrencyEffect: new Big('4.46'), + totalInterestWithCurrencyEffect: new Big('0'), + totalInvestment: new Big('44558.42'), + totalInvestmentWithCurrencyEffect: new Big('44558.42'), + totalLiabilitiesWithCurrencyEffect: new Big('0') + }); + + expect(investments).toEqual([ + { date: '2021-12-12', investment: new Big('44558.42') } + ]); + + expect(investmentsByMonth).toEqual([ + { date: '2021-12-01', investment: 44558.42 }, + { date: '2022-01-01', investment: 0 } + ]); + }); + }); +}); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts similarity index 72% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts index fe379a92a..aaf2c4302 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,9 +14,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -92,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-09-01'), - fee: 49, + feeInAssetProfileCurrency: 49, quantity: 0, SymbolProfile: { ...symbolProfileDummyData, @@ -102,13 +99,13 @@ describe('PortfolioCalculator', () => { symbol: '2c463fb3-af07-486e-adb0-8301b3d72141' }, type: 'FEE', - unitPrice: 0 + unitPriceInAssetProfileCurrency: 0 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'USD', userId: userDummyData.id }); @@ -119,46 +116,15 @@ describe('PortfolioCalculator', () => { currentValueInBaseCurrency: new Big('0'), errors: [], hasErrors: true, - positions: [ - { - averagePrice: new Big('0'), - currency: 'USD', - dataSource: 'MANUAL', - dividend: new Big('0'), - dividendInBaseCurrency: new Big('0'), - fee: new Big('49'), - feeInBaseCurrency: new Big('49'), - firstBuyDate: '2021-09-01', - grossPerformance: null, - grossPerformancePercentage: null, - grossPerformancePercentageWithCurrencyEffect: null, - grossPerformanceWithCurrencyEffect: null, - investment: new Big('0'), - investmentWithCurrencyEffect: new Big('0'), - marketPrice: null, - marketPriceInBaseCurrency: 0, - netPerformance: null, - netPerformancePercentage: null, - netPerformancePercentageWithCurrencyEffectMap: null, - netPerformanceWithCurrencyEffectMap: null, - quantity: new Big('0'), - symbol: '2c463fb3-af07-486e-adb0-8301b3d72141', - tags: [], - timeWeightedInvestment: new Big('0'), - timeWeightedInvestmentWithCurrencyEffect: new Big('0'), - transactionCount: 1, - valueInBaseCurrency: new Big('0') - } - ], + positions: [], totalFeesWithCurrencyEffect: new Big('49'), totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 0, netPerformanceInPercentage: 0, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts similarity index 93% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts index 60fe6dc6b..f7d0e9e6d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -18,9 +15,9 @@ import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-r import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -105,7 +102,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2023-01-03'), - fee: 1, + feeInAssetProfileCurrency: 1, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -115,13 +112,13 @@ describe('PortfolioCalculator', () => { symbol: 'GOOGL' }, type: 'BUY', - unitPrice: 89.12 + unitPriceInAssetProfileCurrency: 89.12 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -180,11 +177,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('89.12').mul(0.8854), totalInvestmentWithCurrencyEffect: new Big('82.329056'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: new Big('26.33').mul(0.8854).toNumber(), netPerformanceInPercentage: 0.29544434470377019749, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts similarity index 91% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts index 5fa90e94c..2cb3899e9 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; @@ -91,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2023-01-01'), // Date in future - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -101,13 +99,13 @@ describe('PortfolioCalculator', () => { symbol: '55196015-1365-4560-aa60-8751ae6d18f8' }, type: 'LIABILITY', - unitPrice: 3000 + unitPriceInAssetProfileCurrency: 3000 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'USD', userId: userDummyData.id }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts similarity index 86% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index ba1cbeb3c..36b6e8be9 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -4,23 +4,19 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock'; import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -52,18 +48,6 @@ jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { }; }); -jest.mock( - '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service', - () => { - return { - // eslint-disable-next-line @typescript-eslint/naming-convention - ExchangeRateDataService: jest.fn().mockImplementation(() => { - return ExchangeRateDataServiceMock; - }) - }; - } -); - describe('PortfolioCalculator', () => { let configurationService: ConfigurationService; let currentRateService: CurrentRateService; @@ -105,7 +89,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-09-16'), - fee: 19, + feeInAssetProfileCurrency: 19, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -115,12 +99,12 @@ describe('PortfolioCalculator', () => { symbol: 'MSFT' }, type: 'BUY', - unitPrice: 298.58 + unitPriceInAssetProfileCurrency: 298.58 }, { ...activityDummyData, date: new Date('2021-11-16'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -130,13 +114,13 @@ describe('PortfolioCalculator', () => { symbol: 'MSFT' }, type: 'DIVIDEND', - unitPrice: 0.62 + unitPriceInAssetProfileCurrency: 0.62 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'USD', userId: userDummyData.id }); @@ -186,11 +170,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('298.58'), totalInvestmentWithCurrencyEffect: new Big('298.58'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ totalInvestmentValueWithCurrencyEffect: 298.58 }) diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts similarity index 92% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts index 84898490f..f64328d39 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts @@ -1,8 +1,5 @@ import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -12,6 +9,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; @@ -84,7 +82,7 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities: [], - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -107,8 +105,7 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); expect(investments).toEqual([]); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts similarity index 92% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index f9f99ee45..96bbbc757 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -6,10 +6,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -19,9 +16,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; import { join } from 'path'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { @@ -68,7 +65,7 @@ describe('PortfolioCalculator', () => { activityDtos = loadActivityExportFile( join( __dirname, - '../../../../../../../test/import/ok-novn-buy-and-sell-partially.json' + '../../../../../../../test/import/ok/novn-buy-and-sell-partially.json' ) ); }); @@ -106,18 +103,20 @@ describe('PortfolioCalculator', () => { ...activityDummyData, ...activity, date: parseDate(activity.date), + feeInAssetProfileCurrency: activity.fee, SymbolProfile: { ...symbolProfileDummyData, currency: activity.currency, dataSource: activity.dataSource, name: 'Novartis AG', symbol: activity.symbol - } + }, + unitPriceInAssetProfileCurrency: activity.unitPrice })); const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -178,11 +177,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('75.80'), totalInvestmentWithCurrencyEffect: new Big('75.80'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 17.68, netPerformanceInPercentage: 0.12184460284330327256, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts similarity index 85% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts index 66cdb9e8e..c19f6917e 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -6,10 +6,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -19,9 +16,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; import { join } from 'path'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { @@ -68,7 +65,7 @@ describe('PortfolioCalculator', () => { activityDtos = loadActivityExportFile( join( __dirname, - '../../../../../../../test/import/ok-novn-buy-and-sell.json' + '../../../../../../../test/import/ok/novn-buy-and-sell.json' ) ); }); @@ -106,18 +103,20 @@ describe('PortfolioCalculator', () => { ...activityDummyData, ...activity, date: parseDate(activity.date), + feeInAssetProfileCurrency: activity.fee, SymbolProfile: { ...symbolProfileDummyData, currency: activity.currency, dataSource: activity.dataSource, name: 'Novartis AG', symbol: activity.symbol - } + }, + unitPriceInAssetProfileCurrency: activity.unitPrice })); const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'CHF', userId: userDummyData.id }); @@ -146,19 +145,23 @@ describe('PortfolioCalculator', () => { valueWithCurrencyEffect: 0 }); + /** + * Closing price on 2022-03-07 is unknown, + * hence it uses the last unit price (2022-04-11): 87.8 + */ expect(portfolioSnapshot.historicalData[1]).toEqual({ date: '2022-03-07', investmentValueWithCurrencyEffect: 151.6, - netPerformance: 0, - netPerformanceInPercentage: 0, - netPerformanceInPercentageWithCurrencyEffect: 0, - netPerformanceWithCurrencyEffect: 0, - netWorth: 151.6, + netPerformance: 24, // 2 * (87.8 - 75.8) = 24 + netPerformanceInPercentage: 0.158311345646438, // 24 ÷ 151.6 = 0.158311345646438 + netPerformanceInPercentageWithCurrencyEffect: 0.158311345646438, // 24 ÷ 151.6 = 0.158311345646438 + netPerformanceWithCurrencyEffect: 24, + netWorth: 175.6, // 2 * 87.8 = 175.6 totalAccountBalance: 0, totalInvestment: 151.6, totalInvestmentValueWithCurrencyEffect: 151.6, - value: 151.6, - valueWithCurrencyEffect: 151.6 + value: 175.6, // 2 * 87.8 = 175.6 + valueWithCurrencyEffect: 175.6 }); expect( @@ -225,11 +228,10 @@ describe('PortfolioCalculator', () => { totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 19.86, netPerformanceInPercentage: 0.13100263852242744063, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts similarity index 74% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts index 228568374..5e9949dd2 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts @@ -4,10 +4,7 @@ import { symbolProfileDummyData, userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; -import { - PortfolioCalculatorFactory, - PerformanceCalculationType -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -17,9 +14,9 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -85,14 +82,14 @@ describe('PortfolioCalculator', () => { }); describe('compute portfolio snapshot', () => { - it.only('with item activity', async () => { + it.only('with valuable activity', async () => { jest.useFakeTimers().setSystemTime(parseDate('2022-01-31').getTime()); const activities: Activity[] = [ { ...activityDummyData, date: new Date('2022-01-01'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -101,14 +98,14 @@ describe('PortfolioCalculator', () => { name: 'Penthouse Apartment', symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde' }, - type: 'ITEM', - unitPrice: 500000 + type: 'BUY', + unitPriceInAssetProfileCurrency: 500000 } ]; const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: PerformanceCalculationType.ROAI, currency: 'USD', userId: userDummyData.id }); @@ -116,9 +113,9 @@ describe('PortfolioCalculator', () => { const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); expect(portfolioSnapshot).toMatchObject({ - currentValueInBaseCurrency: new Big('0'), + currentValueInBaseCurrency: new Big('500000'), errors: [], - hasErrors: true, + hasErrors: false, positions: [ { averagePrice: new Big('500000'), @@ -129,42 +126,45 @@ describe('PortfolioCalculator', () => { fee: new Big('0'), feeInBaseCurrency: new Big('0'), firstBuyDate: '2022-01-01', - grossPerformance: null, - grossPerformancePercentage: null, - grossPerformancePercentageWithCurrencyEffect: null, - grossPerformanceWithCurrencyEffect: null, - investment: new Big('0'), - investmentWithCurrencyEffect: new Big('0'), + grossPerformance: new Big('0'), + grossPerformancePercentage: new Big('0'), + grossPerformancePercentageWithCurrencyEffect: new Big('0'), + grossPerformanceWithCurrencyEffect: new Big('0'), + investment: new Big('500000'), + investmentWithCurrencyEffect: new Big('500000'), marketPrice: null, marketPriceInBaseCurrency: 500000, - netPerformance: null, - netPerformancePercentage: null, - netPerformancePercentageWithCurrencyEffectMap: null, - netPerformanceWithCurrencyEffectMap: null, - quantity: new Big('0'), + netPerformance: new Big('0'), + netPerformancePercentage: new Big('0'), + netPerformancePercentageWithCurrencyEffectMap: { + max: new Big('0') + }, + netPerformanceWithCurrencyEffectMap: { + max: new Big('0') + }, + quantity: new Big('1'), symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde', tags: [], - timeWeightedInvestment: new Big('0'), - timeWeightedInvestmentWithCurrencyEffect: new Big('0'), + timeWeightedInvestment: new Big('500000'), + timeWeightedInvestmentWithCurrencyEffect: new Big('500000'), transactionCount: 1, - valueInBaseCurrency: new Big('0') + valueInBaseCurrency: new Big('500000') } ], totalFeesWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'), - totalInvestment: new Big('0'), - totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') + totalInvestment: new Big('500000'), + totalInvestmentWithCurrencyEffect: new Big('500000'), + totalLiabilitiesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 0, netPerformanceInPercentage: 0, netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0, - totalInvestmentValueWithCurrencyEffect: 0 + totalInvestmentValueWithCurrencyEffect: 500000 }) ); }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.spec.ts similarity index 100% rename from apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts rename to apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.spec.ts diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts new file mode 100644 index 000000000..d4fad7d93 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -0,0 +1,985 @@ +import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; +import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order-item.interface'; +import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; +import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; +import { DATE_FORMAT } from '@ghostfolio/common/helper'; +import { + AssetProfileIdentifier, + SymbolMetrics +} from '@ghostfolio/common/interfaces'; +import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; +import { DateRange } from '@ghostfolio/common/types'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +import { Logger } from '@nestjs/common'; +import { Big } from 'big.js'; +import { addMilliseconds, differenceInDays, format, isBefore } from 'date-fns'; +import { cloneDeep, sortBy } from 'lodash'; + +export class RoaiPortfolioCalculator extends PortfolioCalculator { + private chartDates: string[]; + + protected calculateOverallPerformance( + positions: TimelinePosition[] + ): PortfolioSnapshot { + let currentValueInBaseCurrency = new Big(0); + let grossPerformance = new Big(0); + let grossPerformanceWithCurrencyEffect = new Big(0); + let hasErrors = false; + let netPerformance = new Big(0); + let totalFeesWithCurrencyEffect = new Big(0); + const totalInterestWithCurrencyEffect = new Big(0); + let totalInvestment = new Big(0); + let totalInvestmentWithCurrencyEffect = new Big(0); + let totalTimeWeightedInvestment = new Big(0); + let totalTimeWeightedInvestmentWithCurrencyEffect = new Big(0); + + for (const currentPosition of positions) { + if (currentPosition.feeInBaseCurrency) { + totalFeesWithCurrencyEffect = totalFeesWithCurrencyEffect.plus( + currentPosition.feeInBaseCurrency + ); + } + + if (currentPosition.valueInBaseCurrency) { + currentValueInBaseCurrency = currentValueInBaseCurrency.plus( + currentPosition.valueInBaseCurrency + ); + } else { + hasErrors = true; + } + + if (currentPosition.investment) { + totalInvestment = totalInvestment.plus(currentPosition.investment); + + totalInvestmentWithCurrencyEffect = + totalInvestmentWithCurrencyEffect.plus( + currentPosition.investmentWithCurrencyEffect + ); + } else { + hasErrors = true; + } + + if (currentPosition.grossPerformance) { + grossPerformance = grossPerformance.plus( + currentPosition.grossPerformance + ); + + grossPerformanceWithCurrencyEffect = + grossPerformanceWithCurrencyEffect.plus( + currentPosition.grossPerformanceWithCurrencyEffect + ); + + netPerformance = netPerformance.plus(currentPosition.netPerformance); + } else if (!currentPosition.quantity.eq(0)) { + hasErrors = true; + } + + if (currentPosition.timeWeightedInvestment) { + totalTimeWeightedInvestment = totalTimeWeightedInvestment.plus( + currentPosition.timeWeightedInvestment + ); + + totalTimeWeightedInvestmentWithCurrencyEffect = + totalTimeWeightedInvestmentWithCurrencyEffect.plus( + currentPosition.timeWeightedInvestmentWithCurrencyEffect + ); + } else if (!currentPosition.quantity.eq(0)) { + Logger.warn( + `Missing historical market data for ${currentPosition.symbol} (${currentPosition.dataSource})`, + 'PortfolioCalculator' + ); + + hasErrors = true; + } + } + + return { + currentValueInBaseCurrency, + hasErrors, + positions, + totalFeesWithCurrencyEffect, + totalInterestWithCurrencyEffect, + totalInvestment, + totalInvestmentWithCurrencyEffect, + activitiesCount: this.activities.filter(({ type }) => { + return ['BUY', 'SELL'].includes(type); + }).length, + createdAt: new Date(), + errors: [], + historicalData: [], + totalLiabilitiesWithCurrencyEffect: new Big(0) + }; + } + + protected getPerformanceCalculationType() { + return PerformanceCalculationType.ROAI; + } + + protected getSymbolMetrics({ + chartDateMap, + dataSource, + end, + exchangeRates, + marketSymbolMap, + start, + symbol + }: { + chartDateMap?: { [date: string]: boolean }; + end: Date; + exchangeRates: { [dateString: string]: number }; + marketSymbolMap: { + [date: string]: { [symbol: string]: Big }; + }; + start: Date; + } & AssetProfileIdentifier): SymbolMetrics { + const currentExchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)]; + const currentValues: { [date: string]: Big } = {}; + const currentValuesWithCurrencyEffect: { [date: string]: Big } = {}; + let fees = new Big(0); + let feesAtStartDate = new Big(0); + let feesAtStartDateWithCurrencyEffect = new Big(0); + let feesWithCurrencyEffect = new Big(0); + let grossPerformance = new Big(0); + let grossPerformanceWithCurrencyEffect = new Big(0); + let grossPerformanceAtStartDate = new Big(0); + let grossPerformanceAtStartDateWithCurrencyEffect = new Big(0); + let grossPerformanceFromSells = new Big(0); + let grossPerformanceFromSellsWithCurrencyEffect = new Big(0); + let initialValue: Big; + let initialValueWithCurrencyEffect: Big; + let investmentAtStartDate: Big; + let investmentAtStartDateWithCurrencyEffect: Big; + const investmentValuesAccumulated: { [date: string]: Big } = {}; + const investmentValuesAccumulatedWithCurrencyEffect: { + [date: string]: Big; + } = {}; + const investmentValuesWithCurrencyEffect: { [date: string]: Big } = {}; + let lastAveragePrice = new Big(0); + let lastAveragePriceWithCurrencyEffect = new Big(0); + const netPerformanceValues: { [date: string]: Big } = {}; + const netPerformanceValuesWithCurrencyEffect: { [date: string]: Big } = {}; + const timeWeightedInvestmentValues: { [date: string]: Big } = {}; + + const timeWeightedInvestmentValuesWithCurrencyEffect: { + [date: string]: Big; + } = {}; + + const totalAccountBalanceInBaseCurrency = new Big(0); + let totalDividend = new Big(0); + let totalDividendInBaseCurrency = new Big(0); + let totalInterest = new Big(0); + let totalInterestInBaseCurrency = new Big(0); + let totalInvestment = new Big(0); + let totalInvestmentFromBuyTransactions = new Big(0); + let totalInvestmentFromBuyTransactionsWithCurrencyEffect = new Big(0); + let totalInvestmentWithCurrencyEffect = new Big(0); + let totalLiabilities = new Big(0); + let totalLiabilitiesInBaseCurrency = new Big(0); + let totalQuantityFromBuyTransactions = new Big(0); + let totalUnits = new Big(0); + let valueAtStartDate: Big; + let valueAtStartDateWithCurrencyEffect: Big; + + // Clone orders to keep the original values in this.orders + let orders: PortfolioOrderItem[] = cloneDeep( + this.activities.filter(({ SymbolProfile }) => { + return SymbolProfile.symbol === symbol; + }) + ); + + if (orders.length <= 0) { + return { + currentValues: {}, + currentValuesWithCurrencyEffect: {}, + feesWithCurrencyEffect: new Big(0), + grossPerformance: new Big(0), + grossPerformancePercentage: new Big(0), + grossPerformancePercentageWithCurrencyEffect: new Big(0), + grossPerformanceWithCurrencyEffect: new Big(0), + hasErrors: false, + initialValue: new Big(0), + initialValueWithCurrencyEffect: new Big(0), + investmentValuesAccumulated: {}, + investmentValuesAccumulatedWithCurrencyEffect: {}, + investmentValuesWithCurrencyEffect: {}, + netPerformance: new Big(0), + netPerformancePercentage: new Big(0), + netPerformancePercentageWithCurrencyEffectMap: {}, + netPerformanceValues: {}, + netPerformanceValuesWithCurrencyEffect: {}, + netPerformanceWithCurrencyEffectMap: {}, + timeWeightedInvestment: new Big(0), + timeWeightedInvestmentValues: {}, + timeWeightedInvestmentValuesWithCurrencyEffect: {}, + timeWeightedInvestmentWithCurrencyEffect: new Big(0), + totalAccountBalanceInBaseCurrency: new Big(0), + totalDividend: new Big(0), + totalDividendInBaseCurrency: new Big(0), + totalInterest: new Big(0), + totalInterestInBaseCurrency: new Big(0), + totalInvestment: new Big(0), + totalInvestmentWithCurrencyEffect: new Big(0), + totalLiabilities: new Big(0), + totalLiabilitiesInBaseCurrency: new Big(0) + }; + } + + const dateOfFirstTransaction = new Date(orders[0].date); + + const endDateString = format(end, DATE_FORMAT); + const startDateString = format(start, DATE_FORMAT); + + const unitPriceAtStartDate = marketSymbolMap[startDateString]?.[symbol]; + let unitPriceAtEndDate = marketSymbolMap[endDateString]?.[symbol]; + + let latestActivity = orders.at(-1); + + if ( + dataSource === 'MANUAL' && + ['BUY', 'SELL'].includes(latestActivity?.type) && + latestActivity?.unitPrice && + !unitPriceAtEndDate + ) { + // For BUY / SELL activities with a MANUAL data source where no historical market price is available, + // the calculation should fall back to using the activity’s unit price. + unitPriceAtEndDate = latestActivity.unitPrice; + } + + if ( + !unitPriceAtEndDate || + (!unitPriceAtStartDate && isBefore(dateOfFirstTransaction, start)) + ) { + return { + currentValues: {}, + currentValuesWithCurrencyEffect: {}, + feesWithCurrencyEffect: new Big(0), + grossPerformance: new Big(0), + grossPerformancePercentage: new Big(0), + grossPerformancePercentageWithCurrencyEffect: new Big(0), + grossPerformanceWithCurrencyEffect: new Big(0), + hasErrors: true, + initialValue: new Big(0), + initialValueWithCurrencyEffect: new Big(0), + investmentValuesAccumulated: {}, + investmentValuesAccumulatedWithCurrencyEffect: {}, + investmentValuesWithCurrencyEffect: {}, + netPerformance: new Big(0), + netPerformancePercentage: new Big(0), + netPerformancePercentageWithCurrencyEffectMap: {}, + netPerformanceWithCurrencyEffectMap: {}, + netPerformanceValues: {}, + netPerformanceValuesWithCurrencyEffect: {}, + timeWeightedInvestment: new Big(0), + timeWeightedInvestmentValues: {}, + timeWeightedInvestmentValuesWithCurrencyEffect: {}, + timeWeightedInvestmentWithCurrencyEffect: new Big(0), + totalAccountBalanceInBaseCurrency: new Big(0), + totalDividend: new Big(0), + totalDividendInBaseCurrency: new Big(0), + totalInterest: new Big(0), + totalInterestInBaseCurrency: new Big(0), + totalInvestment: new Big(0), + totalInvestmentWithCurrencyEffect: new Big(0), + totalLiabilities: new Big(0), + totalLiabilitiesInBaseCurrency: new Big(0) + }; + } + + // Add a synthetic order at the start and the end date + orders.push({ + date: startDateString, + fee: new Big(0), + feeInBaseCurrency: new Big(0), + itemType: 'start', + quantity: new Big(0), + SymbolProfile: { + dataSource, + symbol + }, + type: 'BUY', + unitPrice: unitPriceAtStartDate + }); + + orders.push({ + date: endDateString, + fee: new Big(0), + feeInBaseCurrency: new Big(0), + itemType: 'end', + SymbolProfile: { + dataSource, + symbol + }, + quantity: new Big(0), + type: 'BUY', + unitPrice: unitPriceAtEndDate + }); + + let lastUnitPrice: Big; + + const ordersByDate: { [date: string]: PortfolioOrderItem[] } = {}; + + for (const order of orders) { + ordersByDate[order.date] = ordersByDate[order.date] ?? []; + ordersByDate[order.date].push(order); + } + + if (!this.chartDates) { + this.chartDates = Object.keys(chartDateMap).sort(); + } + + for (const dateString of this.chartDates) { + if (dateString < startDateString) { + continue; + } else if (dateString > endDateString) { + break; + } + + if (ordersByDate[dateString]?.length > 0) { + for (const order of ordersByDate[dateString]) { + order.unitPriceFromMarketData = + marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice; + } + } else { + orders.push({ + date: dateString, + fee: new Big(0), + feeInBaseCurrency: new Big(0), + quantity: new Big(0), + SymbolProfile: { + dataSource, + symbol + }, + type: 'BUY', + unitPrice: marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice, + unitPriceFromMarketData: + marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice + }); + } + + latestActivity = orders.at(-1); + + lastUnitPrice = + latestActivity.unitPriceFromMarketData ?? latestActivity.unitPrice; + } + + // Sort orders so that the start and end placeholder order are at the correct + // position + orders = sortBy(orders, ({ date, itemType }) => { + let sortIndex = new Date(date); + + if (itemType === 'end') { + sortIndex = addMilliseconds(sortIndex, 1); + } else if (itemType === 'start') { + sortIndex = addMilliseconds(sortIndex, -1); + } + + return sortIndex.getTime(); + }); + + const indexOfStartOrder = orders.findIndex(({ itemType }) => { + return itemType === 'start'; + }); + + const indexOfEndOrder = orders.findIndex(({ itemType }) => { + return itemType === 'end'; + }); + + let totalInvestmentDays = 0; + let sumOfTimeWeightedInvestments = new Big(0); + let sumOfTimeWeightedInvestmentsWithCurrencyEffect = new Big(0); + + for (let i = 0; i < orders.length; i += 1) { + const order = orders[i]; + + if (PortfolioCalculator.ENABLE_LOGGING) { + console.log(); + console.log(); + console.log( + i + 1, + order.date, + order.type, + order.itemType ? `(${order.itemType})` : '' + ); + } + + const exchangeRateAtOrderDate = exchangeRates[order.date]; + + if (order.type === 'DIVIDEND') { + const dividend = order.quantity.mul(order.unitPrice); + + totalDividend = totalDividend.plus(dividend); + totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus( + dividend.mul(exchangeRateAtOrderDate ?? 1) + ); + } else if (order.type === 'INTEREST') { + const interest = order.quantity.mul(order.unitPrice); + + totalInterest = totalInterest.plus(interest); + totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus( + interest.mul(exchangeRateAtOrderDate ?? 1) + ); + } else if (order.type === 'LIABILITY') { + const liabilities = order.quantity.mul(order.unitPrice); + + totalLiabilities = totalLiabilities.plus(liabilities); + totalLiabilitiesInBaseCurrency = totalLiabilitiesInBaseCurrency.plus( + liabilities.mul(exchangeRateAtOrderDate ?? 1) + ); + } + + if (order.itemType === 'start') { + // Take the unit price of the order as the market price if there are no + // orders of this symbol before the start date + order.unitPrice = + indexOfStartOrder === 0 + ? orders[i + 1]?.unitPrice + : unitPriceAtStartDate; + } + + if (order.fee) { + order.feeInBaseCurrency = order.fee.mul(currentExchangeRate ?? 1); + order.feeInBaseCurrencyWithCurrencyEffect = order.fee.mul( + exchangeRateAtOrderDate ?? 1 + ); + } + + const unitPrice = ['BUY', 'SELL'].includes(order.type) + ? order.unitPrice + : order.unitPriceFromMarketData; + + if (unitPrice) { + order.unitPriceInBaseCurrency = unitPrice.mul(currentExchangeRate ?? 1); + + order.unitPriceInBaseCurrencyWithCurrencyEffect = unitPrice.mul( + exchangeRateAtOrderDate ?? 1 + ); + } + + const marketPriceInBaseCurrency = + order.unitPriceFromMarketData?.mul(currentExchangeRate ?? 1) ?? + new Big(0); + const marketPriceInBaseCurrencyWithCurrencyEffect = + order.unitPriceFromMarketData?.mul(exchangeRateAtOrderDate ?? 1) ?? + new Big(0); + + const valueOfInvestmentBeforeTransaction = totalUnits.mul( + marketPriceInBaseCurrency + ); + + const valueOfInvestmentBeforeTransactionWithCurrencyEffect = + totalUnits.mul(marketPriceInBaseCurrencyWithCurrencyEffect); + + if (!investmentAtStartDate && i >= indexOfStartOrder) { + investmentAtStartDate = totalInvestment ?? new Big(0); + + investmentAtStartDateWithCurrencyEffect = + totalInvestmentWithCurrencyEffect ?? new Big(0); + + valueAtStartDate = valueOfInvestmentBeforeTransaction; + + valueAtStartDateWithCurrencyEffect = + valueOfInvestmentBeforeTransactionWithCurrencyEffect; + } + + let transactionInvestment = new Big(0); + let transactionInvestmentWithCurrencyEffect = new Big(0); + + if (order.type === 'BUY') { + transactionInvestment = order.quantity + .mul(order.unitPriceInBaseCurrency) + .mul(getFactor(order.type)); + + transactionInvestmentWithCurrencyEffect = order.quantity + .mul(order.unitPriceInBaseCurrencyWithCurrencyEffect) + .mul(getFactor(order.type)); + + totalQuantityFromBuyTransactions = + totalQuantityFromBuyTransactions.plus(order.quantity); + + totalInvestmentFromBuyTransactions = + totalInvestmentFromBuyTransactions.plus(transactionInvestment); + + totalInvestmentFromBuyTransactionsWithCurrencyEffect = + totalInvestmentFromBuyTransactionsWithCurrencyEffect.plus( + transactionInvestmentWithCurrencyEffect + ); + } else if (order.type === 'SELL') { + if (totalUnits.gt(0)) { + transactionInvestment = totalInvestment + .div(totalUnits) + .mul(order.quantity) + .mul(getFactor(order.type)); + transactionInvestmentWithCurrencyEffect = + totalInvestmentWithCurrencyEffect + .div(totalUnits) + .mul(order.quantity) + .mul(getFactor(order.type)); + } + } + + if (PortfolioCalculator.ENABLE_LOGGING) { + console.log('order.quantity', order.quantity.toNumber()); + console.log('transactionInvestment', transactionInvestment.toNumber()); + + console.log( + 'transactionInvestmentWithCurrencyEffect', + transactionInvestmentWithCurrencyEffect.toNumber() + ); + } + + const totalInvestmentBeforeTransaction = totalInvestment; + + const totalInvestmentBeforeTransactionWithCurrencyEffect = + totalInvestmentWithCurrencyEffect; + + totalInvestment = totalInvestment.plus(transactionInvestment); + + totalInvestmentWithCurrencyEffect = + totalInvestmentWithCurrencyEffect.plus( + transactionInvestmentWithCurrencyEffect + ); + + if (i >= indexOfStartOrder && !initialValue) { + if ( + i === indexOfStartOrder && + !valueOfInvestmentBeforeTransaction.eq(0) + ) { + initialValue = valueOfInvestmentBeforeTransaction; + + initialValueWithCurrencyEffect = + valueOfInvestmentBeforeTransactionWithCurrencyEffect; + } else if (transactionInvestment.gt(0)) { + initialValue = transactionInvestment; + + initialValueWithCurrencyEffect = + transactionInvestmentWithCurrencyEffect; + } + } + + fees = fees.plus(order.feeInBaseCurrency ?? 0); + + feesWithCurrencyEffect = feesWithCurrencyEffect.plus( + order.feeInBaseCurrencyWithCurrencyEffect ?? 0 + ); + + totalUnits = totalUnits.plus(order.quantity.mul(getFactor(order.type))); + + const valueOfInvestment = totalUnits.mul(marketPriceInBaseCurrency); + + const valueOfInvestmentWithCurrencyEffect = totalUnits.mul( + marketPriceInBaseCurrencyWithCurrencyEffect + ); + + const grossPerformanceFromSell = + order.type === 'SELL' + ? order.unitPriceInBaseCurrency + .minus(lastAveragePrice) + .mul(order.quantity) + : new Big(0); + + const grossPerformanceFromSellWithCurrencyEffect = + order.type === 'SELL' + ? order.unitPriceInBaseCurrencyWithCurrencyEffect + .minus(lastAveragePriceWithCurrencyEffect) + .mul(order.quantity) + : new Big(0); + + grossPerformanceFromSells = grossPerformanceFromSells.plus( + grossPerformanceFromSell + ); + + grossPerformanceFromSellsWithCurrencyEffect = + grossPerformanceFromSellsWithCurrencyEffect.plus( + grossPerformanceFromSellWithCurrencyEffect + ); + + lastAveragePrice = totalQuantityFromBuyTransactions.eq(0) + ? new Big(0) + : totalInvestmentFromBuyTransactions.div( + totalQuantityFromBuyTransactions + ); + + lastAveragePriceWithCurrencyEffect = totalQuantityFromBuyTransactions.eq( + 0 + ) + ? new Big(0) + : totalInvestmentFromBuyTransactionsWithCurrencyEffect.div( + totalQuantityFromBuyTransactions + ); + + if (PortfolioCalculator.ENABLE_LOGGING) { + console.log( + 'grossPerformanceFromSells', + grossPerformanceFromSells.toNumber() + ); + console.log( + 'grossPerformanceFromSellWithCurrencyEffect', + grossPerformanceFromSellWithCurrencyEffect.toNumber() + ); + } + + const newGrossPerformance = valueOfInvestment + .minus(totalInvestment) + .plus(grossPerformanceFromSells); + + const newGrossPerformanceWithCurrencyEffect = + valueOfInvestmentWithCurrencyEffect + .minus(totalInvestmentWithCurrencyEffect) + .plus(grossPerformanceFromSellsWithCurrencyEffect); + + grossPerformance = newGrossPerformance; + + grossPerformanceWithCurrencyEffect = + newGrossPerformanceWithCurrencyEffect; + + if (order.itemType === 'start') { + feesAtStartDate = fees; + feesAtStartDateWithCurrencyEffect = feesWithCurrencyEffect; + grossPerformanceAtStartDate = grossPerformance; + + grossPerformanceAtStartDateWithCurrencyEffect = + grossPerformanceWithCurrencyEffect; + } + + if (i > indexOfStartOrder) { + // Only consider periods with an investment for the calculation of + // the time weighted investment + if ( + valueOfInvestmentBeforeTransaction.gt(0) && + ['BUY', 'SELL'].includes(order.type) + ) { + // Calculate the number of days since the previous order + const orderDate = new Date(order.date); + const previousOrderDate = new Date(orders[i - 1].date); + + let daysSinceLastOrder = differenceInDays( + orderDate, + previousOrderDate + ); + if (daysSinceLastOrder <= 0) { + // The time between two activities on the same day is unknown + // -> Set it to the smallest floating point number greater than 0 + daysSinceLastOrder = Number.EPSILON; + } + + // Sum up the total investment days since the start date to calculate + // the time weighted investment + totalInvestmentDays += daysSinceLastOrder; + + sumOfTimeWeightedInvestments = sumOfTimeWeightedInvestments.add( + valueAtStartDate + .minus(investmentAtStartDate) + .plus(totalInvestmentBeforeTransaction) + .mul(daysSinceLastOrder) + ); + + sumOfTimeWeightedInvestmentsWithCurrencyEffect = + sumOfTimeWeightedInvestmentsWithCurrencyEffect.add( + valueAtStartDateWithCurrencyEffect + .minus(investmentAtStartDateWithCurrencyEffect) + .plus(totalInvestmentBeforeTransactionWithCurrencyEffect) + .mul(daysSinceLastOrder) + ); + } + + currentValues[order.date] = valueOfInvestment; + + currentValuesWithCurrencyEffect[order.date] = + valueOfInvestmentWithCurrencyEffect; + + netPerformanceValues[order.date] = grossPerformance + .minus(grossPerformanceAtStartDate) + .minus(fees.minus(feesAtStartDate)); + + netPerformanceValuesWithCurrencyEffect[order.date] = + grossPerformanceWithCurrencyEffect + .minus(grossPerformanceAtStartDateWithCurrencyEffect) + .minus( + feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect) + ); + + investmentValuesAccumulated[order.date] = totalInvestment; + + investmentValuesAccumulatedWithCurrencyEffect[order.date] = + totalInvestmentWithCurrencyEffect; + + investmentValuesWithCurrencyEffect[order.date] = ( + investmentValuesWithCurrencyEffect[order.date] ?? new Big(0) + ).add(transactionInvestmentWithCurrencyEffect); + + // If duration is effectively zero (first day), use the actual investment as the base. + // Otherwise, use the calculated time-weighted average. + timeWeightedInvestmentValues[order.date] = + totalInvestmentDays > Number.EPSILON + ? sumOfTimeWeightedInvestments.div(totalInvestmentDays) + : totalInvestment.gt(0) + ? totalInvestment + : new Big(0); + + timeWeightedInvestmentValuesWithCurrencyEffect[order.date] = + totalInvestmentDays > Number.EPSILON + ? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div( + totalInvestmentDays + ) + : totalInvestmentWithCurrencyEffect.gt(0) + ? totalInvestmentWithCurrencyEffect + : new Big(0); + } + + if (PortfolioCalculator.ENABLE_LOGGING) { + console.log('totalInvestment', totalInvestment.toNumber()); + + console.log( + 'totalInvestmentWithCurrencyEffect', + totalInvestmentWithCurrencyEffect.toNumber() + ); + + console.log( + 'totalGrossPerformance', + grossPerformance.minus(grossPerformanceAtStartDate).toNumber() + ); + + console.log( + 'totalGrossPerformanceWithCurrencyEffect', + grossPerformanceWithCurrencyEffect + .minus(grossPerformanceAtStartDateWithCurrencyEffect) + .toNumber() + ); + } + + if (i === indexOfEndOrder) { + break; + } + } + + const totalGrossPerformance = grossPerformance.minus( + grossPerformanceAtStartDate + ); + + const totalGrossPerformanceWithCurrencyEffect = + grossPerformanceWithCurrencyEffect.minus( + grossPerformanceAtStartDateWithCurrencyEffect + ); + + const totalNetPerformance = grossPerformance + .minus(grossPerformanceAtStartDate) + .minus(fees.minus(feesAtStartDate)); + + const timeWeightedAverageInvestmentBetweenStartAndEndDate = + totalInvestmentDays > 0 + ? sumOfTimeWeightedInvestments.div(totalInvestmentDays) + : new Big(0); + + const timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect = + totalInvestmentDays > 0 + ? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div( + totalInvestmentDays + ) + : new Big(0); + + const grossPerformancePercentage = + timeWeightedAverageInvestmentBetweenStartAndEndDate.gt(0) + ? totalGrossPerformance.div( + timeWeightedAverageInvestmentBetweenStartAndEndDate + ) + : new Big(0); + + const grossPerformancePercentageWithCurrencyEffect = + timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.gt( + 0 + ) + ? totalGrossPerformanceWithCurrencyEffect.div( + timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect + ) + : new Big(0); + + const feesPerUnit = totalUnits.gt(0) + ? fees.minus(feesAtStartDate).div(totalUnits) + : new Big(0); + + const feesPerUnitWithCurrencyEffect = totalUnits.gt(0) + ? feesWithCurrencyEffect + .minus(feesAtStartDateWithCurrencyEffect) + .div(totalUnits) + : new Big(0); + + const netPerformancePercentage = + timeWeightedAverageInvestmentBetweenStartAndEndDate.gt(0) + ? totalNetPerformance.div( + timeWeightedAverageInvestmentBetweenStartAndEndDate + ) + : new Big(0); + + const netPerformancePercentageWithCurrencyEffectMap: { + [key: DateRange]: Big; + } = {}; + + const netPerformanceWithCurrencyEffectMap: { + [key: DateRange]: Big; + } = {}; + + for (const dateRange of [ + '1d', + '1y', + '5y', + 'max', + 'mtd', + 'wtd', + 'ytd' + // TODO: + // ...eachYearOfInterval({ end, start }) + // .filter((date) => { + // return !isThisYear(date); + // }) + // .map((date) => { + // return format(date, 'yyyy'); + // }) + ] as DateRange[]) { + const dateInterval = getIntervalFromDateRange(dateRange); + const endDate = dateInterval.endDate; + let startDate = dateInterval.startDate; + + if (isBefore(startDate, start)) { + startDate = start; + } + + const rangeEndDateString = format(endDate, DATE_FORMAT); + const rangeStartDateString = format(startDate, DATE_FORMAT); + + const currentValuesAtDateRangeStartWithCurrencyEffect = + currentValuesWithCurrencyEffect[rangeStartDateString] ?? new Big(0); + + const investmentValuesAccumulatedAtStartDateWithCurrencyEffect = + investmentValuesAccumulatedWithCurrencyEffect[rangeStartDateString] ?? + new Big(0); + + const grossPerformanceAtDateRangeStartWithCurrencyEffect = + currentValuesAtDateRangeStartWithCurrencyEffect.minus( + investmentValuesAccumulatedAtStartDateWithCurrencyEffect + ); + + let average = new Big(0); + let dayCount = 0; + + for (let i = this.chartDates.length - 1; i >= 0; i -= 1) { + const date = this.chartDates[i]; + + if (date > rangeEndDateString) { + continue; + } else if (date < rangeStartDateString) { + break; + } + + if ( + investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big && + investmentValuesAccumulatedWithCurrencyEffect[date].gt(0) + ) { + average = average.add( + investmentValuesAccumulatedWithCurrencyEffect[date].add( + grossPerformanceAtDateRangeStartWithCurrencyEffect + ) + ); + + dayCount++; + } + } + + if (dayCount > 0) { + average = average.div(dayCount); + } + + netPerformanceWithCurrencyEffectMap[dateRange] = + netPerformanceValuesWithCurrencyEffect[rangeEndDateString]?.minus( + // If the date range is 'max', take 0 as a start value. Otherwise, + // the value of the end of the day of the start date is taken which + // differs from the buying price. + dateRange === 'max' + ? new Big(0) + : (netPerformanceValuesWithCurrencyEffect[rangeStartDateString] ?? + new Big(0)) + ) ?? new Big(0); + + netPerformancePercentageWithCurrencyEffectMap[dateRange] = average.gt(0) + ? netPerformanceWithCurrencyEffectMap[dateRange].div(average) + : new Big(0); + } + + if (PortfolioCalculator.ENABLE_LOGGING) { + console.log( + ` + ${symbol} + Unit price: ${orders[indexOfStartOrder].unitPrice.toFixed( + 2 + )} -> ${unitPriceAtEndDate.toFixed(2)} + Total investment: ${totalInvestment.toFixed(2)} + Total investment with currency effect: ${totalInvestmentWithCurrencyEffect.toFixed( + 2 + )} + Time weighted investment: ${timeWeightedAverageInvestmentBetweenStartAndEndDate.toFixed( + 2 + )} + Time weighted investment with currency effect: ${timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.toFixed( + 2 + )} + Total dividend: ${totalDividend.toFixed(2)} + Gross performance: ${totalGrossPerformance.toFixed( + 2 + )} / ${grossPerformancePercentage.mul(100).toFixed(2)}% + Gross performance with currency effect: ${totalGrossPerformanceWithCurrencyEffect.toFixed( + 2 + )} / ${grossPerformancePercentageWithCurrencyEffect + .mul(100) + .toFixed(2)}% + Fees per unit: ${feesPerUnit.toFixed(2)} + Fees per unit with currency effect: ${feesPerUnitWithCurrencyEffect.toFixed( + 2 + )} + Net performance: ${totalNetPerformance.toFixed( + 2 + )} / ${netPerformancePercentage.mul(100).toFixed(2)}% + Net performance with currency effect: ${netPerformancePercentageWithCurrencyEffectMap[ + 'max' + ].toFixed(2)}%` + ); + } + + return { + currentValues, + currentValuesWithCurrencyEffect, + feesWithCurrencyEffect, + grossPerformancePercentage, + grossPerformancePercentageWithCurrencyEffect, + initialValue, + initialValueWithCurrencyEffect, + investmentValuesAccumulated, + investmentValuesAccumulatedWithCurrencyEffect, + investmentValuesWithCurrencyEffect, + netPerformancePercentage, + netPerformancePercentageWithCurrencyEffectMap, + netPerformanceValues, + netPerformanceValuesWithCurrencyEffect, + netPerformanceWithCurrencyEffectMap, + timeWeightedInvestmentValues, + timeWeightedInvestmentValuesWithCurrencyEffect, + totalAccountBalanceInBaseCurrency, + totalDividend, + totalDividendInBaseCurrency, + totalInterest, + totalInterestInBaseCurrency, + totalInvestment, + totalInvestmentWithCurrencyEffect, + totalLiabilities, + totalLiabilitiesInBaseCurrency, + grossPerformance: totalGrossPerformance, + grossPerformanceWithCurrencyEffect: + totalGrossPerformanceWithCurrencyEffect, + hasErrors: totalUnits.gt(0) && (!initialValue || !unitPriceAtEndDate), + netPerformance: totalNetPerformance, + timeWeightedInvestment: + timeWeightedAverageInvestmentBetweenStartAndEndDate, + timeWeightedInvestmentWithCurrencyEffect: + timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect + }; + } +} diff --git a/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts new file mode 100644 index 000000000..b4929c570 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roi/portfolio-calculator.ts @@ -0,0 +1,29 @@ +import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; +import { + AssetProfileIdentifier, + SymbolMetrics +} from '@ghostfolio/common/interfaces'; +import { PortfolioSnapshot } from '@ghostfolio/common/models'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +export class RoiPortfolioCalculator extends PortfolioCalculator { + protected calculateOverallPerformance(): PortfolioSnapshot { + throw new Error('Method not implemented.'); + } + + protected getPerformanceCalculationType() { + return PerformanceCalculationType.ROI; + } + + protected getSymbolMetrics({}: { + end: Date; + exchangeRates: { [dateString: string]: number }; + marketSymbolMap: { + [date: string]: { [symbol: string]: Big }; + }; + start: Date; + step?: number; + } & AssetProfileIdentifier): SymbolMetrics { + throw new Error('Method not implemented.'); + } +} diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts index 3f53ee04b..8a58f816a 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -1,965 +1,29 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; -import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order-item.interface'; -import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; -import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; -import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, SymbolMetrics } from '@ghostfolio/common/interfaces'; -import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; -import { DateRange } from '@ghostfolio/common/types'; +import { PortfolioSnapshot } from '@ghostfolio/common/models'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; -import { Logger } from '@nestjs/common'; -import { Big } from 'big.js'; -import { addMilliseconds, differenceInDays, format, isBefore } from 'date-fns'; -import { cloneDeep, first, last, sortBy } from 'lodash'; - -export class TWRPortfolioCalculator extends PortfolioCalculator { - private chartDates: string[]; - - protected calculateOverallPerformance( - positions: TimelinePosition[] - ): PortfolioSnapshot { - let currentValueInBaseCurrency = new Big(0); - let grossPerformance = new Big(0); - let grossPerformanceWithCurrencyEffect = new Big(0); - let hasErrors = false; - let netPerformance = new Big(0); - let totalFeesWithCurrencyEffect = new Big(0); - const totalInterestWithCurrencyEffect = new Big(0); - let totalInvestment = new Big(0); - let totalInvestmentWithCurrencyEffect = new Big(0); - let totalTimeWeightedInvestment = new Big(0); - let totalTimeWeightedInvestmentWithCurrencyEffect = new Big(0); - - for (const currentPosition of positions) { - if (currentPosition.feeInBaseCurrency) { - totalFeesWithCurrencyEffect = totalFeesWithCurrencyEffect.plus( - currentPosition.feeInBaseCurrency - ); - } - - if (currentPosition.valueInBaseCurrency) { - currentValueInBaseCurrency = currentValueInBaseCurrency.plus( - currentPosition.valueInBaseCurrency - ); - } else { - hasErrors = true; - } - - if (currentPosition.investment) { - totalInvestment = totalInvestment.plus(currentPosition.investment); - - totalInvestmentWithCurrencyEffect = - totalInvestmentWithCurrencyEffect.plus( - currentPosition.investmentWithCurrencyEffect - ); - } else { - hasErrors = true; - } - - if (currentPosition.grossPerformance) { - grossPerformance = grossPerformance.plus( - currentPosition.grossPerformance - ); - - grossPerformanceWithCurrencyEffect = - grossPerformanceWithCurrencyEffect.plus( - currentPosition.grossPerformanceWithCurrencyEffect - ); - - netPerformance = netPerformance.plus(currentPosition.netPerformance); - } else if (!currentPosition.quantity.eq(0)) { - hasErrors = true; - } - - if (currentPosition.timeWeightedInvestment) { - totalTimeWeightedInvestment = totalTimeWeightedInvestment.plus( - currentPosition.timeWeightedInvestment - ); - - totalTimeWeightedInvestmentWithCurrencyEffect = - totalTimeWeightedInvestmentWithCurrencyEffect.plus( - currentPosition.timeWeightedInvestmentWithCurrencyEffect - ); - } else if (!currentPosition.quantity.eq(0)) { - Logger.warn( - `Missing historical market data for ${currentPosition.symbol} (${currentPosition.dataSource})`, - 'PortfolioCalculator' - ); - - hasErrors = true; - } - } +export class TwrPortfolioCalculator extends PortfolioCalculator { + protected calculateOverallPerformance(): PortfolioSnapshot { + throw new Error('Method not implemented.'); + } - return { - currentValueInBaseCurrency, - hasErrors, - positions, - totalFeesWithCurrencyEffect, - totalInterestWithCurrencyEffect, - totalInvestment, - totalInvestmentWithCurrencyEffect, - errors: [], - historicalData: [], - totalLiabilitiesWithCurrencyEffect: new Big(0), - totalValuablesWithCurrencyEffect: new Big(0) - }; + protected getPerformanceCalculationType() { + return PerformanceCalculationType.TWR; } - protected getSymbolMetrics({ - chartDateMap, - dataSource, - end, - exchangeRates, - marketSymbolMap, - start, - symbol - }: { - chartDateMap?: { [date: string]: boolean }; + protected getSymbolMetrics({}: { end: Date; exchangeRates: { [dateString: string]: number }; marketSymbolMap: { [date: string]: { [symbol: string]: Big }; }; start: Date; + step?: number; } & AssetProfileIdentifier): SymbolMetrics { - const currentExchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)]; - const currentValues: { [date: string]: Big } = {}; - const currentValuesWithCurrencyEffect: { [date: string]: Big } = {}; - let fees = new Big(0); - let feesAtStartDate = new Big(0); - let feesAtStartDateWithCurrencyEffect = new Big(0); - let feesWithCurrencyEffect = new Big(0); - let grossPerformance = new Big(0); - let grossPerformanceWithCurrencyEffect = new Big(0); - let grossPerformanceAtStartDate = new Big(0); - let grossPerformanceAtStartDateWithCurrencyEffect = new Big(0); - let grossPerformanceFromSells = new Big(0); - let grossPerformanceFromSellsWithCurrencyEffect = new Big(0); - let initialValue: Big; - let initialValueWithCurrencyEffect: Big; - let investmentAtStartDate: Big; - let investmentAtStartDateWithCurrencyEffect: Big; - const investmentValuesAccumulated: { [date: string]: Big } = {}; - const investmentValuesAccumulatedWithCurrencyEffect: { - [date: string]: Big; - } = {}; - const investmentValuesWithCurrencyEffect: { [date: string]: Big } = {}; - let lastAveragePrice = new Big(0); - let lastAveragePriceWithCurrencyEffect = new Big(0); - const netPerformanceValues: { [date: string]: Big } = {}; - const netPerformanceValuesWithCurrencyEffect: { [date: string]: Big } = {}; - const timeWeightedInvestmentValues: { [date: string]: Big } = {}; - - const timeWeightedInvestmentValuesWithCurrencyEffect: { - [date: string]: Big; - } = {}; - - const totalAccountBalanceInBaseCurrency = new Big(0); - let totalDividend = new Big(0); - let totalDividendInBaseCurrency = new Big(0); - let totalInterest = new Big(0); - let totalInterestInBaseCurrency = new Big(0); - let totalInvestment = new Big(0); - let totalInvestmentFromBuyTransactions = new Big(0); - let totalInvestmentFromBuyTransactionsWithCurrencyEffect = new Big(0); - let totalInvestmentWithCurrencyEffect = new Big(0); - let totalLiabilities = new Big(0); - let totalLiabilitiesInBaseCurrency = new Big(0); - let totalQuantityFromBuyTransactions = new Big(0); - let totalUnits = new Big(0); - let totalValuables = new Big(0); - let totalValuablesInBaseCurrency = new Big(0); - let valueAtStartDate: Big; - let valueAtStartDateWithCurrencyEffect: Big; - - // Clone orders to keep the original values in this.orders - let orders: PortfolioOrderItem[] = cloneDeep( - this.activities.filter(({ SymbolProfile }) => { - return SymbolProfile.symbol === symbol; - }) - ); - - if (orders.length <= 0) { - return { - currentValues: {}, - currentValuesWithCurrencyEffect: {}, - feesWithCurrencyEffect: new Big(0), - grossPerformance: new Big(0), - grossPerformancePercentage: new Big(0), - grossPerformancePercentageWithCurrencyEffect: new Big(0), - grossPerformanceWithCurrencyEffect: new Big(0), - hasErrors: false, - initialValue: new Big(0), - initialValueWithCurrencyEffect: new Big(0), - investmentValuesAccumulated: {}, - investmentValuesAccumulatedWithCurrencyEffect: {}, - investmentValuesWithCurrencyEffect: {}, - netPerformance: new Big(0), - netPerformancePercentage: new Big(0), - netPerformancePercentageWithCurrencyEffectMap: {}, - netPerformanceValues: {}, - netPerformanceValuesWithCurrencyEffect: {}, - netPerformanceWithCurrencyEffectMap: {}, - timeWeightedInvestment: new Big(0), - timeWeightedInvestmentValues: {}, - timeWeightedInvestmentValuesWithCurrencyEffect: {}, - timeWeightedInvestmentWithCurrencyEffect: new Big(0), - totalAccountBalanceInBaseCurrency: new Big(0), - totalDividend: new Big(0), - totalDividendInBaseCurrency: new Big(0), - totalInterest: new Big(0), - totalInterestInBaseCurrency: new Big(0), - totalInvestment: new Big(0), - totalInvestmentWithCurrencyEffect: new Big(0), - totalLiabilities: new Big(0), - totalLiabilitiesInBaseCurrency: new Big(0), - totalValuables: new Big(0), - totalValuablesInBaseCurrency: new Big(0) - }; - } - - const dateOfFirstTransaction = new Date(first(orders).date); - - const endDateString = format(end, DATE_FORMAT); - const startDateString = format(start, DATE_FORMAT); - - const unitPriceAtStartDate = marketSymbolMap[startDateString]?.[symbol]; - const unitPriceAtEndDate = marketSymbolMap[endDateString]?.[symbol]; - - if ( - !unitPriceAtEndDate || - (!unitPriceAtStartDate && isBefore(dateOfFirstTransaction, start)) - ) { - return { - currentValues: {}, - currentValuesWithCurrencyEffect: {}, - feesWithCurrencyEffect: new Big(0), - grossPerformance: new Big(0), - grossPerformancePercentage: new Big(0), - grossPerformancePercentageWithCurrencyEffect: new Big(0), - grossPerformanceWithCurrencyEffect: new Big(0), - hasErrors: true, - initialValue: new Big(0), - initialValueWithCurrencyEffect: new Big(0), - investmentValuesAccumulated: {}, - investmentValuesAccumulatedWithCurrencyEffect: {}, - investmentValuesWithCurrencyEffect: {}, - netPerformance: new Big(0), - netPerformancePercentage: new Big(0), - netPerformancePercentageWithCurrencyEffectMap: {}, - netPerformanceWithCurrencyEffectMap: {}, - netPerformanceValues: {}, - netPerformanceValuesWithCurrencyEffect: {}, - timeWeightedInvestment: new Big(0), - timeWeightedInvestmentValues: {}, - timeWeightedInvestmentValuesWithCurrencyEffect: {}, - timeWeightedInvestmentWithCurrencyEffect: new Big(0), - totalAccountBalanceInBaseCurrency: new Big(0), - totalDividend: new Big(0), - totalDividendInBaseCurrency: new Big(0), - totalInterest: new Big(0), - totalInterestInBaseCurrency: new Big(0), - totalInvestment: new Big(0), - totalInvestmentWithCurrencyEffect: new Big(0), - totalLiabilities: new Big(0), - totalLiabilitiesInBaseCurrency: new Big(0), - totalValuables: new Big(0), - totalValuablesInBaseCurrency: new Big(0) - }; - } - - // Add a synthetic order at the start and the end date - orders.push({ - date: startDateString, - fee: new Big(0), - feeInBaseCurrency: new Big(0), - itemType: 'start', - quantity: new Big(0), - SymbolProfile: { - dataSource, - symbol - }, - type: 'BUY', - unitPrice: unitPriceAtStartDate - }); - - orders.push({ - date: endDateString, - fee: new Big(0), - feeInBaseCurrency: new Big(0), - itemType: 'end', - SymbolProfile: { - dataSource, - symbol - }, - quantity: new Big(0), - type: 'BUY', - unitPrice: unitPriceAtEndDate - }); - - let lastUnitPrice: Big; - - const ordersByDate: { [date: string]: PortfolioOrderItem[] } = {}; - - for (const order of orders) { - ordersByDate[order.date] = ordersByDate[order.date] ?? []; - ordersByDate[order.date].push(order); - } - - if (!this.chartDates) { - this.chartDates = Object.keys(chartDateMap).sort(); - } - - for (const dateString of this.chartDates) { - if (dateString < startDateString) { - continue; - } else if (dateString > endDateString) { - break; - } - - if (ordersByDate[dateString]?.length > 0) { - for (const order of ordersByDate[dateString]) { - order.unitPriceFromMarketData = - marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice; - } - } else { - orders.push({ - date: dateString, - fee: new Big(0), - feeInBaseCurrency: new Big(0), - quantity: new Big(0), - SymbolProfile: { - dataSource, - symbol - }, - type: 'BUY', - unitPrice: marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice, - unitPriceFromMarketData: - marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice - }); - } - - const lastOrder = last(orders); - - lastUnitPrice = lastOrder.unitPriceFromMarketData ?? lastOrder.unitPrice; - } - - // Sort orders so that the start and end placeholder order are at the correct - // position - orders = sortBy(orders, ({ date, itemType }) => { - let sortIndex = new Date(date); - - if (itemType === 'end') { - sortIndex = addMilliseconds(sortIndex, 1); - } else if (itemType === 'start') { - sortIndex = addMilliseconds(sortIndex, -1); - } - - return sortIndex.getTime(); - }); - - const indexOfStartOrder = orders.findIndex(({ itemType }) => { - return itemType === 'start'; - }); - - const indexOfEndOrder = orders.findIndex(({ itemType }) => { - return itemType === 'end'; - }); - - let totalInvestmentDays = 0; - let sumOfTimeWeightedInvestments = new Big(0); - let sumOfTimeWeightedInvestmentsWithCurrencyEffect = new Big(0); - - for (let i = 0; i < orders.length; i += 1) { - const order = orders[i]; - - if (PortfolioCalculator.ENABLE_LOGGING) { - console.log(); - console.log(); - console.log( - i + 1, - order.date, - order.type, - order.itemType ? `(${order.itemType})` : '' - ); - } - - const exchangeRateAtOrderDate = exchangeRates[order.date]; - - if (order.type === 'DIVIDEND') { - const dividend = order.quantity.mul(order.unitPrice); - - totalDividend = totalDividend.plus(dividend); - totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus( - dividend.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'INTEREST') { - const interest = order.quantity.mul(order.unitPrice); - - totalInterest = totalInterest.plus(interest); - totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus( - interest.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'ITEM') { - const valuables = order.quantity.mul(order.unitPrice); - - totalValuables = totalValuables.plus(valuables); - totalValuablesInBaseCurrency = totalValuablesInBaseCurrency.plus( - valuables.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'LIABILITY') { - const liabilities = order.quantity.mul(order.unitPrice); - - totalLiabilities = totalLiabilities.plus(liabilities); - totalLiabilitiesInBaseCurrency = totalLiabilitiesInBaseCurrency.plus( - liabilities.mul(exchangeRateAtOrderDate ?? 1) - ); - } - - if (order.itemType === 'start') { - // Take the unit price of the order as the market price if there are no - // orders of this symbol before the start date - order.unitPrice = - indexOfStartOrder === 0 - ? orders[i + 1]?.unitPrice - : unitPriceAtStartDate; - } - - if (order.fee) { - order.feeInBaseCurrency = order.fee.mul(currentExchangeRate ?? 1); - order.feeInBaseCurrencyWithCurrencyEffect = order.fee.mul( - exchangeRateAtOrderDate ?? 1 - ); - } - - const unitPrice = ['BUY', 'SELL'].includes(order.type) - ? order.unitPrice - : order.unitPriceFromMarketData; - - if (unitPrice) { - order.unitPriceInBaseCurrency = unitPrice.mul(currentExchangeRate ?? 1); - - order.unitPriceInBaseCurrencyWithCurrencyEffect = unitPrice.mul( - exchangeRateAtOrderDate ?? 1 - ); - } - - const valueOfInvestmentBeforeTransaction = totalUnits.mul( - order.unitPriceInBaseCurrency - ); - - const valueOfInvestmentBeforeTransactionWithCurrencyEffect = - totalUnits.mul(order.unitPriceInBaseCurrencyWithCurrencyEffect); - - if (!investmentAtStartDate && i >= indexOfStartOrder) { - investmentAtStartDate = totalInvestment ?? new Big(0); - - investmentAtStartDateWithCurrencyEffect = - totalInvestmentWithCurrencyEffect ?? new Big(0); - - valueAtStartDate = valueOfInvestmentBeforeTransaction; - - valueAtStartDateWithCurrencyEffect = - valueOfInvestmentBeforeTransactionWithCurrencyEffect; - } - - let transactionInvestment = new Big(0); - let transactionInvestmentWithCurrencyEffect = new Big(0); - - if (order.type === 'BUY') { - transactionInvestment = order.quantity - .mul(order.unitPriceInBaseCurrency) - .mul(getFactor(order.type)); - - transactionInvestmentWithCurrencyEffect = order.quantity - .mul(order.unitPriceInBaseCurrencyWithCurrencyEffect) - .mul(getFactor(order.type)); - - totalQuantityFromBuyTransactions = - totalQuantityFromBuyTransactions.plus(order.quantity); - - totalInvestmentFromBuyTransactions = - totalInvestmentFromBuyTransactions.plus(transactionInvestment); - - totalInvestmentFromBuyTransactionsWithCurrencyEffect = - totalInvestmentFromBuyTransactionsWithCurrencyEffect.plus( - transactionInvestmentWithCurrencyEffect - ); - } else if (order.type === 'SELL') { - if (totalUnits.gt(0)) { - transactionInvestment = totalInvestment - .div(totalUnits) - .mul(order.quantity) - .mul(getFactor(order.type)); - transactionInvestmentWithCurrencyEffect = - totalInvestmentWithCurrencyEffect - .div(totalUnits) - .mul(order.quantity) - .mul(getFactor(order.type)); - } - } - - if (PortfolioCalculator.ENABLE_LOGGING) { - console.log('order.quantity', order.quantity.toNumber()); - console.log('transactionInvestment', transactionInvestment.toNumber()); - - console.log( - 'transactionInvestmentWithCurrencyEffect', - transactionInvestmentWithCurrencyEffect.toNumber() - ); - } - - const totalInvestmentBeforeTransaction = totalInvestment; - - const totalInvestmentBeforeTransactionWithCurrencyEffect = - totalInvestmentWithCurrencyEffect; - - totalInvestment = totalInvestment.plus(transactionInvestment); - - totalInvestmentWithCurrencyEffect = - totalInvestmentWithCurrencyEffect.plus( - transactionInvestmentWithCurrencyEffect - ); - - if (i >= indexOfStartOrder && !initialValue) { - if ( - i === indexOfStartOrder && - !valueOfInvestmentBeforeTransaction.eq(0) - ) { - initialValue = valueOfInvestmentBeforeTransaction; - - initialValueWithCurrencyEffect = - valueOfInvestmentBeforeTransactionWithCurrencyEffect; - } else if (transactionInvestment.gt(0)) { - initialValue = transactionInvestment; - - initialValueWithCurrencyEffect = - transactionInvestmentWithCurrencyEffect; - } - } - - fees = fees.plus(order.feeInBaseCurrency ?? 0); - - feesWithCurrencyEffect = feesWithCurrencyEffect.plus( - order.feeInBaseCurrencyWithCurrencyEffect ?? 0 - ); - - totalUnits = totalUnits.plus(order.quantity.mul(getFactor(order.type))); - - const valueOfInvestment = totalUnits.mul(order.unitPriceInBaseCurrency); - - const valueOfInvestmentWithCurrencyEffect = totalUnits.mul( - order.unitPriceInBaseCurrencyWithCurrencyEffect - ); - - const grossPerformanceFromSell = - order.type === 'SELL' - ? order.unitPriceInBaseCurrency - .minus(lastAveragePrice) - .mul(order.quantity) - : new Big(0); - - const grossPerformanceFromSellWithCurrencyEffect = - order.type === 'SELL' - ? order.unitPriceInBaseCurrencyWithCurrencyEffect - .minus(lastAveragePriceWithCurrencyEffect) - .mul(order.quantity) - : new Big(0); - - grossPerformanceFromSells = grossPerformanceFromSells.plus( - grossPerformanceFromSell - ); - - grossPerformanceFromSellsWithCurrencyEffect = - grossPerformanceFromSellsWithCurrencyEffect.plus( - grossPerformanceFromSellWithCurrencyEffect - ); - - lastAveragePrice = totalQuantityFromBuyTransactions.eq(0) - ? new Big(0) - : totalInvestmentFromBuyTransactions.div( - totalQuantityFromBuyTransactions - ); - - lastAveragePriceWithCurrencyEffect = totalQuantityFromBuyTransactions.eq( - 0 - ) - ? new Big(0) - : totalInvestmentFromBuyTransactionsWithCurrencyEffect.div( - totalQuantityFromBuyTransactions - ); - - if (PortfolioCalculator.ENABLE_LOGGING) { - console.log( - 'grossPerformanceFromSells', - grossPerformanceFromSells.toNumber() - ); - console.log( - 'grossPerformanceFromSellWithCurrencyEffect', - grossPerformanceFromSellWithCurrencyEffect.toNumber() - ); - } - - const newGrossPerformance = valueOfInvestment - .minus(totalInvestment) - .plus(grossPerformanceFromSells); - - const newGrossPerformanceWithCurrencyEffect = - valueOfInvestmentWithCurrencyEffect - .minus(totalInvestmentWithCurrencyEffect) - .plus(grossPerformanceFromSellsWithCurrencyEffect); - - grossPerformance = newGrossPerformance; - - grossPerformanceWithCurrencyEffect = - newGrossPerformanceWithCurrencyEffect; - - if (order.itemType === 'start') { - feesAtStartDate = fees; - feesAtStartDateWithCurrencyEffect = feesWithCurrencyEffect; - grossPerformanceAtStartDate = grossPerformance; - - grossPerformanceAtStartDateWithCurrencyEffect = - grossPerformanceWithCurrencyEffect; - } - - if (i > indexOfStartOrder) { - // Only consider periods with an investment for the calculation of - // the time weighted investment - if ( - valueOfInvestmentBeforeTransaction.gt(0) && - ['BUY', 'SELL'].includes(order.type) - ) { - // Calculate the number of days since the previous order - const orderDate = new Date(order.date); - const previousOrderDate = new Date(orders[i - 1].date); - - let daysSinceLastOrder = differenceInDays( - orderDate, - previousOrderDate - ); - if (daysSinceLastOrder <= 0) { - // The time between two activities on the same day is unknown - // -> Set it to the smallest floating point number greater than 0 - daysSinceLastOrder = Number.EPSILON; - } - - // Sum up the total investment days since the start date to calculate - // the time weighted investment - totalInvestmentDays += daysSinceLastOrder; - - sumOfTimeWeightedInvestments = sumOfTimeWeightedInvestments.add( - valueAtStartDate - .minus(investmentAtStartDate) - .plus(totalInvestmentBeforeTransaction) - .mul(daysSinceLastOrder) - ); - - sumOfTimeWeightedInvestmentsWithCurrencyEffect = - sumOfTimeWeightedInvestmentsWithCurrencyEffect.add( - valueAtStartDateWithCurrencyEffect - .minus(investmentAtStartDateWithCurrencyEffect) - .plus(totalInvestmentBeforeTransactionWithCurrencyEffect) - .mul(daysSinceLastOrder) - ); - } - - currentValues[order.date] = valueOfInvestment; - - currentValuesWithCurrencyEffect[order.date] = - valueOfInvestmentWithCurrencyEffect; - - netPerformanceValues[order.date] = grossPerformance - .minus(grossPerformanceAtStartDate) - .minus(fees.minus(feesAtStartDate)); - - netPerformanceValuesWithCurrencyEffect[order.date] = - grossPerformanceWithCurrencyEffect - .minus(grossPerformanceAtStartDateWithCurrencyEffect) - .minus( - feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect) - ); - - investmentValuesAccumulated[order.date] = totalInvestment; - - investmentValuesAccumulatedWithCurrencyEffect[order.date] = - totalInvestmentWithCurrencyEffect; - - investmentValuesWithCurrencyEffect[order.date] = ( - investmentValuesWithCurrencyEffect[order.date] ?? new Big(0) - ).add(transactionInvestmentWithCurrencyEffect); - - timeWeightedInvestmentValues[order.date] = - totalInvestmentDays > 0 - ? sumOfTimeWeightedInvestments.div(totalInvestmentDays) - : new Big(0); - - timeWeightedInvestmentValuesWithCurrencyEffect[order.date] = - totalInvestmentDays > 0 - ? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div( - totalInvestmentDays - ) - : new Big(0); - } - - if (PortfolioCalculator.ENABLE_LOGGING) { - console.log('totalInvestment', totalInvestment.toNumber()); - - console.log( - 'totalInvestmentWithCurrencyEffect', - totalInvestmentWithCurrencyEffect.toNumber() - ); - - console.log( - 'totalGrossPerformance', - grossPerformance.minus(grossPerformanceAtStartDate).toNumber() - ); - - console.log( - 'totalGrossPerformanceWithCurrencyEffect', - grossPerformanceWithCurrencyEffect - .minus(grossPerformanceAtStartDateWithCurrencyEffect) - .toNumber() - ); - } - - if (i === indexOfEndOrder) { - break; - } - } - - const totalGrossPerformance = grossPerformance.minus( - grossPerformanceAtStartDate - ); - - const totalGrossPerformanceWithCurrencyEffect = - grossPerformanceWithCurrencyEffect.minus( - grossPerformanceAtStartDateWithCurrencyEffect - ); - - const totalNetPerformance = grossPerformance - .minus(grossPerformanceAtStartDate) - .minus(fees.minus(feesAtStartDate)); - - const timeWeightedAverageInvestmentBetweenStartAndEndDate = - totalInvestmentDays > 0 - ? sumOfTimeWeightedInvestments.div(totalInvestmentDays) - : new Big(0); - - const timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect = - totalInvestmentDays > 0 - ? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div( - totalInvestmentDays - ) - : new Big(0); - - const grossPerformancePercentage = - timeWeightedAverageInvestmentBetweenStartAndEndDate.gt(0) - ? totalGrossPerformance.div( - timeWeightedAverageInvestmentBetweenStartAndEndDate - ) - : new Big(0); - - const grossPerformancePercentageWithCurrencyEffect = - timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.gt( - 0 - ) - ? totalGrossPerformanceWithCurrencyEffect.div( - timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect - ) - : new Big(0); - - const feesPerUnit = totalUnits.gt(0) - ? fees.minus(feesAtStartDate).div(totalUnits) - : new Big(0); - - const feesPerUnitWithCurrencyEffect = totalUnits.gt(0) - ? feesWithCurrencyEffect - .minus(feesAtStartDateWithCurrencyEffect) - .div(totalUnits) - : new Big(0); - - const netPerformancePercentage = - timeWeightedAverageInvestmentBetweenStartAndEndDate.gt(0) - ? totalNetPerformance.div( - timeWeightedAverageInvestmentBetweenStartAndEndDate - ) - : new Big(0); - - const netPerformancePercentageWithCurrencyEffectMap: { - [key: DateRange]: Big; - } = {}; - - const netPerformanceWithCurrencyEffectMap: { - [key: DateRange]: Big; - } = {}; - - for (const dateRange of [ - '1d', - '1y', - '5y', - 'max', - 'mtd', - 'wtd', - 'ytd' - // TODO: - // ...eachYearOfInterval({ end, start }) - // .filter((date) => { - // return !isThisYear(date); - // }) - // .map((date) => { - // return format(date, 'yyyy'); - // }) - ] as DateRange[]) { - const dateInterval = getIntervalFromDateRange(dateRange); - const endDate = dateInterval.endDate; - let startDate = dateInterval.startDate; - - if (isBefore(startDate, start)) { - startDate = start; - } - - const rangeEndDateString = format(endDate, DATE_FORMAT); - const rangeStartDateString = format(startDate, DATE_FORMAT); - - const currentValuesAtDateRangeStartWithCurrencyEffect = - currentValuesWithCurrencyEffect[rangeStartDateString] ?? new Big(0); - - const investmentValuesAccumulatedAtStartDateWithCurrencyEffect = - investmentValuesAccumulatedWithCurrencyEffect[rangeStartDateString] ?? - new Big(0); - - const grossPerformanceAtDateRangeStartWithCurrencyEffect = - currentValuesAtDateRangeStartWithCurrencyEffect.minus( - investmentValuesAccumulatedAtStartDateWithCurrencyEffect - ); - - let average = new Big(0); - let dayCount = 0; - - for (let i = this.chartDates.length - 1; i >= 0; i -= 1) { - const date = this.chartDates[i]; - - if (date > rangeEndDateString) { - continue; - } else if (date < rangeStartDateString) { - break; - } - - if ( - investmentValuesAccumulatedWithCurrencyEffect[date] instanceof Big && - investmentValuesAccumulatedWithCurrencyEffect[date].gt(0) - ) { - average = average.add( - investmentValuesAccumulatedWithCurrencyEffect[date].add( - grossPerformanceAtDateRangeStartWithCurrencyEffect - ) - ); - - dayCount++; - } - } - - if (dayCount > 0) { - average = average.div(dayCount); - } - - netPerformanceWithCurrencyEffectMap[dateRange] = - netPerformanceValuesWithCurrencyEffect[rangeEndDateString]?.minus( - // If the date range is 'max', take 0 as a start value. Otherwise, - // the value of the end of the day of the start date is taken which - // differs from the buying price. - dateRange === 'max' - ? new Big(0) - : (netPerformanceValuesWithCurrencyEffect[rangeStartDateString] ?? - new Big(0)) - ) ?? new Big(0); - - netPerformancePercentageWithCurrencyEffectMap[dateRange] = average.gt(0) - ? netPerformanceWithCurrencyEffectMap[dateRange].div(average) - : new Big(0); - } - - if (PortfolioCalculator.ENABLE_LOGGING) { - console.log( - ` - ${symbol} - Unit price: ${orders[indexOfStartOrder].unitPrice.toFixed( - 2 - )} -> ${unitPriceAtEndDate.toFixed(2)} - Total investment: ${totalInvestment.toFixed(2)} - Total investment with currency effect: ${totalInvestmentWithCurrencyEffect.toFixed( - 2 - )} - Time weighted investment: ${timeWeightedAverageInvestmentBetweenStartAndEndDate.toFixed( - 2 - )} - Time weighted investment with currency effect: ${timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.toFixed( - 2 - )} - Total dividend: ${totalDividend.toFixed(2)} - Gross performance: ${totalGrossPerformance.toFixed( - 2 - )} / ${grossPerformancePercentage.mul(100).toFixed(2)}% - Gross performance with currency effect: ${totalGrossPerformanceWithCurrencyEffect.toFixed( - 2 - )} / ${grossPerformancePercentageWithCurrencyEffect - .mul(100) - .toFixed(2)}% - Fees per unit: ${feesPerUnit.toFixed(2)} - Fees per unit with currency effect: ${feesPerUnitWithCurrencyEffect.toFixed( - 2 - )} - Net performance: ${totalNetPerformance.toFixed( - 2 - )} / ${netPerformancePercentage.mul(100).toFixed(2)}% - Net performance with currency effect: ${netPerformancePercentageWithCurrencyEffectMap[ - 'max' - ].toFixed(2)}%` - ); - } - - return { - currentValues, - currentValuesWithCurrencyEffect, - feesWithCurrencyEffect, - grossPerformancePercentage, - grossPerformancePercentageWithCurrencyEffect, - initialValue, - initialValueWithCurrencyEffect, - investmentValuesAccumulated, - investmentValuesAccumulatedWithCurrencyEffect, - investmentValuesWithCurrencyEffect, - netPerformancePercentage, - netPerformancePercentageWithCurrencyEffectMap, - netPerformanceValues, - netPerformanceValuesWithCurrencyEffect, - netPerformanceWithCurrencyEffectMap, - timeWeightedInvestmentValues, - timeWeightedInvestmentValuesWithCurrencyEffect, - totalAccountBalanceInBaseCurrency, - totalDividend, - totalDividendInBaseCurrency, - totalInterest, - totalInterestInBaseCurrency, - totalInvestment, - totalInvestmentWithCurrencyEffect, - totalLiabilities, - totalLiabilitiesInBaseCurrency, - totalValuables, - totalValuablesInBaseCurrency, - grossPerformance: totalGrossPerformance, - grossPerformanceWithCurrencyEffect: - totalGrossPerformanceWithCurrencyEffect, - hasErrors: totalUnits.gt(0) && (!initialValue || !unitPriceAtEndDate), - netPerformance: totalNetPerformance, - timeWeightedInvestment: - timeWeightedAverageInvestmentBetweenStartAndEndDate, - timeWeightedInvestmentWithCurrencyEffect: - timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect - }; + throw new Error('Method not implemented.'); } } diff --git a/apps/api/src/app/portfolio/current-rate.service.mock.ts b/apps/api/src/app/portfolio/current-rate.service.mock.ts index fab25ae2d..4b4b8f00e 100644 --- a/apps/api/src/app/portfolio/current-rate.service.mock.ts +++ b/apps/api/src/app/portfolio/current-rate.service.mock.ts @@ -47,6 +47,10 @@ function mockGetValue(symbol: string, date: Date) { return { marketPrice: 14156.4 }; } else if (isSameDay(parseDate('2018-01-01'), date)) { return { marketPrice: 13657.2 }; + } else if (isSameDay(parseDate('2021-12-12'), date)) { + return { marketPrice: 50098.3 }; + } else if (isSameDay(parseDate('2022-01-14'), date)) { + return { marketPrice: 43099.7 }; } return { marketPrice: 0 }; diff --git a/apps/api/src/app/portfolio/current-rate.service.spec.ts b/apps/api/src/app/portfolio/current-rate.service.spec.ts index d0e61c8ce..d8b7482e7 100644 --- a/apps/api/src/app/portfolio/current-rate.service.spec.ts +++ b/apps/api/src/app/portfolio/current-rate.service.spec.ts @@ -6,6 +6,7 @@ import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { DataSource, MarketData } from '@prisma/client'; import { CurrentRateService } from './current-rate.service'; +import { DateQuery } from './interfaces/date-query.interface'; import { GetValuesObject } from './interfaces/get-values-object.interface'; jest.mock('@ghostfolio/api/services/market-data/market-data.service', () => { @@ -25,33 +26,40 @@ jest.mock('@ghostfolio/api/services/market-data/market-data.service', () => { }, getRange: ({ assetProfileIdentifiers, - dateRangeEnd, - dateRangeStart + dateQuery }: { assetProfileIdentifiers: AssetProfileIdentifier[]; - dateRangeEnd: Date; - dateRangeStart: Date; + dateQuery: DateQuery; + skip?: number; + take?: number; }) => { return Promise.resolve([ { - createdAt: dateRangeStart, + createdAt: dateQuery.gte, dataSource: assetProfileIdentifiers[0].dataSource, - date: dateRangeStart, + date: dateQuery.gte, id: '8fa48fde-f397-4b0d-adbc-fb940e830e6d', marketPrice: 1841.823902, state: 'CLOSE', symbol: assetProfileIdentifiers[0].symbol }, { - createdAt: dateRangeEnd, + createdAt: dateQuery.lt, dataSource: assetProfileIdentifiers[0].dataSource, - date: dateRangeEnd, + date: dateQuery.lt, id: '082d6893-df27-4c91-8a5d-092e84315b56', marketPrice: 1847.839966, state: 'CLOSE', symbol: assetProfileIdentifiers[0].symbol } ]); + }, + getRangeCount: ({}: { + assetProfileIdentifiers: AssetProfileIdentifier[]; + dateRangeEnd: Date; + dateRangeStart: Date; + }) => { + return Promise.resolve(2); } }; }) @@ -128,9 +136,15 @@ describe('CurrentRateService', () => { values: [ { dataSource: 'YAHOO', - date: undefined, + date: new Date('2020-01-01T00:00:00.000Z'), marketPrice: 1841.823902, symbol: 'AMZN' + }, + { + dataSource: 'YAHOO', + date: new Date('2020-01-02T00:00:00.000Z'), + marketPrice: 1847.839966, + symbol: 'AMZN' } ] }); diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index ab7bf2ebf..5d39a54bb 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -13,7 +13,7 @@ import type { RequestWithUser } from '@ghostfolio/common/types'; import { Inject, Injectable } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { isBefore, isToday } from 'date-fns'; -import { flatten, isEmpty, uniqBy } from 'lodash'; +import { isEmpty, uniqBy } from 'lodash'; import { GetValueObject } from './interfaces/get-value-object.interface'; import { GetValuesObject } from './interfaces/get-values-object.interface'; @@ -21,6 +21,8 @@ import { GetValuesParams } from './interfaces/get-values-params.interface'; @Injectable() export class CurrentRateService { + private static readonly MARKET_DATA_PAGE_SIZE = 50000; + public constructor( private readonly dataProviderService: DataProviderService, private readonly marketDataService: MarketDataService, @@ -41,42 +43,37 @@ export class CurrentRateService { (!dateQuery.gte || isBefore(dateQuery.gte, new Date())) && (!dateQuery.in || this.containsToday(dateQuery.in)); - const promises: Promise[] = []; const quoteErrors: ResponseError['errors'] = []; const today = resetHours(new Date()); + const values: GetValueObject[] = []; if (includesToday) { - promises.push( - this.dataProviderService - .getQuotes({ items: dataGatheringItems, user: this.request?.user }) - .then((dataResultProvider) => { - const result: GetValueObject[] = []; - - for (const { dataSource, symbol } of dataGatheringItems) { - if (dataResultProvider?.[symbol]?.dataProviderInfo) { - dataProviderInfos.push( - dataResultProvider[symbol].dataProviderInfo - ); - } + const quotesBySymbol = await this.dataProviderService.getQuotes({ + items: dataGatheringItems, + user: this.request?.user + }); - if (dataResultProvider?.[symbol]?.marketPrice) { - result.push({ - dataSource, - symbol, - date: today, - marketPrice: dataResultProvider?.[symbol]?.marketPrice - }); - } else { - quoteErrors.push({ - dataSource, - symbol - }); - } - } + for (const { dataSource, symbol } of dataGatheringItems) { + const quote = quotesBySymbol[symbol]; - return result; - }) - ); + if (quote?.dataProviderInfo) { + dataProviderInfos.push(quote.dataProviderInfo); + } + + if (quote?.marketPrice) { + values.push({ + dataSource, + symbol, + date: today, + marketPrice: quote.marketPrice + }); + } else { + quoteErrors.push({ + dataSource, + symbol + }); + } + } } const assetProfileIdentifiers: AssetProfileIdentifier[] = @@ -84,32 +81,42 @@ export class CurrentRateService { return { dataSource, symbol }; }); - promises.push( - this.marketDataService - .getRange({ - assetProfileIdentifiers, - dateQuery - }) - .then((data) => { - return data.map(({ dataSource, date, marketPrice, symbol }) => { - return { - dataSource, - date, - marketPrice, - symbol - }; - }); - }) - ); + const marketDataCount = await this.marketDataService.getRangeCount({ + assetProfileIdentifiers, + dateQuery + }); + + for ( + let i = 0; + i < marketDataCount; + i += CurrentRateService.MARKET_DATA_PAGE_SIZE + ) { + // Use page size to limit the number of records fetched at once + const data = await this.marketDataService.getRange({ + assetProfileIdentifiers, + dateQuery, + skip: i, + take: CurrentRateService.MARKET_DATA_PAGE_SIZE + }); - const values = flatten(await Promise.all(promises)); + values.push( + ...data.map(({ dataSource, date, marketPrice, symbol }) => ({ + dataSource, + date, + marketPrice, + symbol + })) + ); + } const response: GetValuesObject = { dataProviderInfos, errors: quoteErrors.map(({ dataSource, symbol }) => { return { dataSource, symbol }; }), - values: uniqBy(values, ({ date, symbol }) => `${date}-${symbol}`) + values: uniqBy(values, ({ date, symbol }) => { + return `${date}-${symbol}`; + }) }; if (!isEmpty(quoteErrors)) { diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-order.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-order.interface.ts index 63a936c32..1c53430f6 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-order.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-order.interface.ts @@ -6,7 +6,7 @@ export interface PortfolioOrder extends Pick { quantity: Big; SymbolProfile: Pick< Activity['SymbolProfile'], - 'currency' | 'dataSource' | 'name' | 'symbol' + 'currency' | 'dataSource' | 'name' | 'symbol' | 'userId' >; unitPrice: Big; } diff --git a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts index d15d02d3a..f4ceadf3b 100644 --- a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts @@ -8,8 +8,10 @@ export interface TransactionPointSymbol { dividend: Big; fee: Big; firstBuyDate: string; + includeInHoldings: boolean; investment: Big; quantity: Big; + skipErrors: boolean; symbol: string; tags?: Tag[]; transactionCount: number; diff --git a/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts b/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts index fcbea81ca..698b202e4 100644 --- a/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts @@ -8,5 +8,4 @@ export interface TransactionPoint { interest: Big; items: TransactionPointSymbol[]; liabilities: Big; - valuables: Big; } diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 797d0449a..f6cbbf105 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -20,6 +20,7 @@ import { import { PortfolioDetails, PortfolioDividends, + PortfolioHoldingResponse, PortfolioHoldingsResponse, PortfolioInvestments, PortfolioPerformanceResponse, @@ -56,7 +57,6 @@ import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; import { Big } from 'big.js'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface'; import { PortfolioService } from './portfolio.service'; import { UpdateHoldingTagsDto } from './update-holding-tags.dto'; @@ -105,6 +105,7 @@ export class PortfolioController { const { accounts, + createdAt, hasErrors, holdings, markets, @@ -233,6 +234,7 @@ export class PortfolioController { return { accounts, + createdAt, hasError, holdings, platforms, @@ -315,7 +317,7 @@ export class PortfolioController { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { endDate, startDate } = getIntervalFromDateRange(dateRange); @@ -363,6 +365,33 @@ export class PortfolioController { return { dividends }; } + @Get('holding/:dataSource/:symbol') + @UseInterceptors(RedactValuesInResponseInterceptor) + @UseInterceptors(TransformDataSourceInRequestInterceptor) + @UseInterceptors(TransformDataSourceInResponseInterceptor) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async getHolding( + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, + @Param('dataSource') dataSource: DataSource, + @Param('symbol') symbol: string + ): Promise { + const holding = await this.portfolioService.getHolding({ + dataSource, + impersonationId, + symbol, + userId: this.request.user.id + }); + + if (!holding) { + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + + return holding; + } + @Get('holdings') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(RedactValuesInResponseInterceptor) @@ -384,19 +413,19 @@ export class PortfolioController { filterByAssetClasses, filterByDataSource, filterByHoldingType, - filterBySearchQuery, filterBySymbol, filterByTags }); - const { holdings } = await this.portfolioService.getDetails({ + const holdings = await this.portfolioService.getHoldings({ dateRange, filters, impersonationId, + query: filterBySearchQuery, userId: this.request.user.id }); - return { holdings: Object.values(holdings) }; + return { holdings }; } @Get('investments') @@ -425,7 +454,8 @@ export class PortfolioController { filters, groupBy, impersonationId, - savingsRate: this.request.user?.Settings?.settings.savingsRate + savingsRate: this.request.user?.settings?.settings.savingsRate, + userId: this.request.user.id }); if ( @@ -508,7 +538,7 @@ export class PortfolioController { user: this.request.user }) || isRestrictedView(this.request.user) || - this.request.user.Settings.settings.viewMode === 'ZEN' + this.request.user.settings.settings.viewMode === 'ZEN' ) { performanceInformation.chart = performanceInformation.chart.map( ({ @@ -581,6 +611,9 @@ export class PortfolioController { return performanceInformation; } + /** + * @deprecated + */ @Get('position/:dataSource/:symbol') @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInRequestInterceptor) @@ -590,12 +623,13 @@ export class PortfolioController { @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string - ): Promise { - const holding = await this.portfolioService.getPosition( + ): Promise { + const holding = await this.portfolioService.getHolding({ dataSource, impersonationId, - symbol - ); + symbol, + userId: this.request.user.id + }); if (!holding) { throw new HttpException( @@ -612,17 +646,20 @@ export class PortfolioController { public async getReport( @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string ): Promise { - const report = await this.portfolioService.getReport(impersonationId); + const report = await this.portfolioService.getReport({ + impersonationId, + userId: this.request.user.id + }); if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.request.user.subscription.type === 'Basic' ) { - for (const rule in report.rules) { - report.rules[rule] = null; + for (const rule in report.xRay.rules) { + report.xRay.rules[rule] = null; } - report.statistics = { + report.xRay.statistics = { rulesActiveCount: 0, rulesFulfilledCount: 0 }; @@ -632,7 +669,7 @@ export class PortfolioController { } @HasPermission(permissions.updateOrder) - @Put('position/:dataSource/:symbol/tags') + @Put('holding/:dataSource/:symbol/tags') @UseInterceptors(TransformDataSourceInRequestInterceptor) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async updateHoldingTags( @@ -641,11 +678,48 @@ export class PortfolioController { @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise { - const holding = await this.portfolioService.getPosition( + const holding = await this.portfolioService.getHolding({ dataSource, impersonationId, - symbol - ); + symbol, + userId: this.request.user.id + }); + + if (!holding) { + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + + await this.portfolioService.updateTags({ + dataSource, + impersonationId, + symbol, + tags: data.tags, + userId: this.request.user.id + }); + } + + /** + * @deprecated + */ + @HasPermission(permissions.updateOrder) + @Put('position/:dataSource/:symbol/tags') + @UseInterceptors(TransformDataSourceInRequestInterceptor) + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async updatePositionTags( + @Body() data: UpdateHoldingTagsDto, + @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, + @Param('dataSource') dataSource: DataSource, + @Param('symbol') symbol: string + ): Promise { + const holding = await this.portfolioService.getHolding({ + dataSource, + impersonationId, + symbol, + userId: this.request.user.id + }); if (!holding) { throw new HttpException( diff --git a/apps/api/src/app/portfolio/portfolio.module.ts b/apps/api/src/app/portfolio/portfolio.module.ts index 7ae74ee5f..6dd5811a3 100644 --- a/apps/api/src/app/portfolio/portfolio.module.ts +++ b/apps/api/src/app/portfolio/portfolio.module.ts @@ -9,9 +9,11 @@ import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redac import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -33,10 +35,12 @@ import { RulesService } from './rules.service'; imports: [ AccessModule, ApiModule, + BenchmarkModule, ConfigurationModule, DataGatheringModule, DataProviderModule, ExchangeRateDataModule, + I18nModule, ImpersonationModule, MarketDataModule, OrderModule, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 400b0c3a9..02804a847 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -15,8 +15,15 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets'; import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup'; import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment'; +import { RegionalMarketClusterRiskAsiaPacific } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/asia-pacific'; +import { RegionalMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/emerging-markets'; +import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe'; +import { RegionalMarketClusterRiskJapan } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/japan'; +import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { @@ -25,33 +32,34 @@ import { } from '@ghostfolio/common/calculation-helper'; import { DEFAULT_CURRENCY, - EMERGENCY_FUND_TAG_ID, + TAG_ID_EMERGENCY_FUND, UNKNOWN_KEY } from '@ghostfolio/common/config'; import { DATE_FORMAT, getSum, parseDate } from '@ghostfolio/common/helper'; import { - Accounts, + AccountsResponse, EnhancedSymbolProfile, Filter, HistoricalDataItem, InvestmentItem, PortfolioDetails, + PortfolioHoldingResponse, PortfolioInvestments, PortfolioPerformanceResponse, PortfolioPosition, PortfolioReportResponse, PortfolioSummary, - Position, UserSettings } from '@ghostfolio/common/interfaces'; import { TimelinePosition } from '@ghostfolio/common/models'; -import type { +import { AccountWithValue, DateRange, GroupBy, RequestWithUser, UserWithSettings } from '@ghostfolio/common/types'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Inject, Injectable } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; @@ -77,16 +85,14 @@ import { parseISO, set } from 'date-fns'; -import { isEmpty, last, uniq } from 'lodash'; +import { isEmpty } from 'lodash'; import { PortfolioCalculator } from './calculator/portfolio-calculator'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from './calculator/portfolio-calculator.factory'; -import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface'; +import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory'; import { RulesService } from './rules.service'; +const Fuse = require('fuse.js'); + const asiaPacificMarkets = require('../../assets/countries/asia-pacific-markets.json'); const developedMarkets = require('../../assets/countries/developed-markets.json'); const emergingMarkets = require('../../assets/countries/emerging-markets.json'); @@ -97,9 +103,11 @@ export class PortfolioService { public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, + private readonly benchmarkService: BenchmarkService, private readonly calculatorFactory: PortfolioCalculatorFactory, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, + private readonly i18nService: I18nService, private readonly impersonationService: ImpersonationService, private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser, @@ -136,7 +144,7 @@ export class PortfolioService { } if (filterByDataSource && filterBySymbol) { - where.Order = { + where.activities = { some: { SymbolProfile: { AND: [ @@ -151,7 +159,10 @@ export class PortfolioService { const [accounts, details] = await Promise.all([ this.accountService.accounts({ where, - include: { Order: true, Platform: true }, + include: { + activities: true, + platform: true + }, orderBy: { name: 'asc' } }), this.getDetails({ @@ -162,13 +173,13 @@ export class PortfolioService { }) ]); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; return accounts.map((account) => { let transactionCount = 0; - for (const order of account.Order) { - if (!order.isDraft) { + for (const { isDraft } of account.activities) { + if (!isDraft) { transactionCount += 1; } } @@ -180,6 +191,7 @@ export class PortfolioService { ...account, transactionCount, valueInBaseCurrency, + allocationInPercentage: null, // TODO balanceInBaseCurrency: this.exchangeRateDataService.toCurrency( account.balance, account.currency, @@ -192,7 +204,7 @@ export class PortfolioService { ) }; - delete result.Order; + delete result.activities; return result; }); @@ -206,7 +218,7 @@ export class PortfolioService { filters?: Filter[]; userId: string; withExcludedAccounts?: boolean; - }): Promise { + }): Promise { const accounts = await this.getAccounts({ filters, userId, @@ -241,10 +253,14 @@ export class PortfolioService { activities: Activity[]; groupBy?: GroupBy; }): Promise { - let dividends = activities.map(({ date, valueInBaseCurrency }) => { + let dividends = activities.map(({ currency, date, value }) => { return { date: format(date, DATE_FORMAT), - investment: valueInBaseCurrency + investment: this.exchangeRateDataService.toCurrency( + value, + currency, + this.getUserCurrency() + ) }; }); @@ -255,28 +271,69 @@ export class PortfolioService { return dividends; } + public async getHoldings({ + dateRange, + filters, + impersonationId, + query, + userId + }: { + dateRange: DateRange; + filters?: Filter[]; + impersonationId: string; + query?: string; + userId: string; + }) { + userId = await this.getUserId(impersonationId, userId); + const { holdings: holdingsMap } = await this.getDetails({ + dateRange, + filters, + impersonationId, + userId + }); + + let holdings = Object.values(holdingsMap); + + if (query) { + const fuse = new Fuse(holdings, { + keys: ['isin', 'name', 'symbol'], + threshold: 0.3 + }); + + holdings = fuse.search(query).map(({ item }) => { + return item; + }); + } + + return holdings; + } + public async getInvestments({ dateRange, filters, groupBy, impersonationId, - savingsRate + savingsRate, + userId }: { dateRange: DateRange; filters?: Filter[]; groupBy?: GroupBy; impersonationId: string; savingsRate: number; + userId: string; }): Promise { - const userId = await this.getUserId(impersonationId, this.request.user.id); + userId = await this.getUserId(impersonationId, userId); + const user = await this.userService.user({ id: userId }); + const userCurrency = this.getUserCurrency(user); const { endDate, startDate } = getIntervalFromDateRange(dateRange); const { activities } = await this.orderService.getOrdersForPortfolioCalculator({ filters, - userId, - userCurrency: this.getUserCurrency() + userCurrency, + userId }); if (activities.length === 0) { @@ -290,8 +347,8 @@ export class PortfolioService { activities, filters, userId, - calculationType: PerformanceCalculationType.TWR, - currency: this.request.user.Settings.settings.baseCurrency + calculationType: this.getUserPerformanceCalculationType(user), + currency: userCurrency }); const { historicalData } = await portfolioCalculator.getSnapshot(); @@ -353,7 +410,7 @@ export class PortfolioService { const userCurrency = this.getUserCurrency(user); const emergencyFund = new Big( - (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 + (user.settings?.settings as UserSettings)?.emergencyFund ?? 0 ); const { activities } = @@ -367,11 +424,11 @@ export class PortfolioService { activities, filters, userId, - calculationType: PerformanceCalculationType.TWR, + calculationType: this.getUserPerformanceCalculationType(user), currency: userCurrency }); - const { currentValueInBaseCurrency, hasErrors, positions } = + const { createdAt, currentValueInBaseCurrency, hasErrors, positions } = await portfolioCalculator.getSnapshot(); const cashDetails = await this.accountService.getCashDetails({ @@ -531,7 +588,7 @@ export class PortfolioService { } if (filters?.length === 0 || isFilteredByAccount || isFilteredByCash) { - const cashPositions = await this.getCashPositions({ + const cashPositions = this.getCashPositions({ cashDetails, userCurrency, value: filteredValueInBaseCurrency @@ -553,10 +610,10 @@ export class PortfolioService { if ( filters?.length === 1 && - filters[0].id === EMERGENCY_FUND_TAG_ID && + filters[0].id === TAG_ID_EMERGENCY_FUND && filters[0].type === 'TAG' ) { - const emergencyFundCashPositions = await this.getCashPositions({ + const emergencyFundCashPositions = this.getCashPositions({ cashDetails, userCurrency, value: filteredValueInBaseCurrency @@ -564,7 +621,7 @@ export class PortfolioService { const emergencyFundInCash = emergencyFund .minus( - this.getEmergencyFundPositionsValueInBaseCurrency({ + this.getEmergencyFundHoldingsValueInBaseCurrency({ holdings }) ) @@ -603,8 +660,8 @@ export class PortfolioService { userCurrency, userId, balanceInBaseCurrency: cashDetails.balanceInBaseCurrency, - emergencyFundPositionsValueInBaseCurrency: - this.getEmergencyFundPositionsValueInBaseCurrency({ + emergencyFundHoldingsValueInBaseCurrency: + this.getEmergencyFundHoldingsValueInBaseCurrency({ holdings }) }); @@ -612,6 +669,7 @@ export class PortfolioService { return { accounts, + createdAt, hasErrors, holdings, markets, @@ -621,12 +679,18 @@ export class PortfolioService { }; } - public async getPosition( - aDataSource: DataSource, - aImpersonationId: string, - aSymbol: string - ): Promise { - const userId = await this.getUserId(aImpersonationId, this.request.user.id); + public async getHolding({ + dataSource, + impersonationId, + symbol, + userId + }: { + dataSource: DataSource; + impersonationId: string; + symbol: string; + userId: string; + }): Promise { + userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); const userCurrency = this.getUserCurrency(user); @@ -638,6 +702,7 @@ export class PortfolioService { if (activities.length === 0) { return { + activities: [], averagePrice: undefined, dataProviderInfo: undefined, dividendInBaseCurrency: undefined, @@ -650,15 +715,15 @@ export class PortfolioService { grossPerformancePercentWithCurrencyEffect: undefined, grossPerformanceWithCurrencyEffect: undefined, historicalData: [], - investment: undefined, + investmentInBaseCurrencyWithCurrencyEffect: undefined, marketPrice: undefined, - maxPrice: undefined, - minPrice: undefined, + marketPriceMax: undefined, + marketPriceMin: undefined, netPerformance: undefined, netPerformancePercent: undefined, netPerformancePercentWithCurrencyEffect: undefined, netPerformanceWithCurrencyEffect: undefined, - orders: [], + performances: undefined, quantity: undefined, SymbolProfile: undefined, tags: [], @@ -668,13 +733,13 @@ export class PortfolioService { } const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([ - { dataSource: aDataSource, symbol: aSymbol } + { dataSource, symbol } ]); const portfolioCalculator = this.calculatorFactory.createCalculator({ activities, userId, - calculationType: PerformanceCalculationType.TWR, + calculationType: this.getUserPerformanceCalculationType(user), currency: userCurrency }); @@ -683,28 +748,35 @@ export class PortfolioService { const { positions } = await portfolioCalculator.getSnapshot(); - const position = positions.find(({ dataSource, symbol }) => { - return dataSource === aDataSource && symbol === aSymbol; + const holding = positions.find((position) => { + return position.dataSource === dataSource && position.symbol === symbol; }); - if (position) { + if (holding) { const { averagePrice, currency, - dataSource, dividendInBaseCurrency, fee, firstBuyDate, + grossPerformance, + grossPerformancePercentage, + grossPerformancePercentageWithCurrencyEffect, + grossPerformanceWithCurrencyEffect, + investmentWithCurrencyEffect, marketPrice, + netPerformance, + netPerformancePercentage, + netPerformancePercentageWithCurrencyEffectMap, + netPerformanceWithCurrencyEffectMap, quantity, - symbol, tags, timeWeightedInvestment, timeWeightedInvestmentWithCurrencyEffect, transactionCount - } = position; + } = holding; - const activitiesOfPosition = activities.filter(({ SymbolProfile }) => { + const activitiesOfHolding = activities.filter(({ SymbolProfile }) => { return ( SymbolProfile.dataSource === dataSource && SymbolProfile.symbol === symbol @@ -731,20 +803,30 @@ export class PortfolioService { }); const historicalData = await this.dataProviderService.getHistorical( - [{ dataSource, symbol: aSymbol }], + [{ dataSource, symbol }], 'day', parseISO(firstBuyDate), new Date() ); const historicalDataArray: HistoricalDataItem[] = []; - let maxPrice = Math.max(activitiesOfPosition[0].unitPrice, marketPrice); - let minPrice = Math.min(activitiesOfPosition[0].unitPrice, marketPrice); + let marketPriceMax = Math.max( + activitiesOfHolding[0].unitPriceInAssetProfileCurrency, + marketPrice + ); + let marketPriceMaxDate = + marketPrice > activitiesOfHolding[0].unitPriceInAssetProfileCurrency + ? new Date() + : activitiesOfHolding[0].date; + let marketPriceMin = Math.min( + activitiesOfHolding[0].unitPriceInAssetProfileCurrency, + marketPrice + ); - if (historicalData[aSymbol]) { + if (historicalData[symbol]) { let j = -1; for (const [date, { marketPrice }] of Object.entries( - historicalData[aSymbol] + historicalData[symbol] )) { while ( j + 1 < transactionPoints.length && @@ -757,8 +839,8 @@ export class PortfolioService { let currentQuantity = 0; const currentSymbol = transactionPoints[j]?.items.find( - ({ symbol }) => { - return symbol === aSymbol; + (transactionPointSymbol) => { + return transactionPointSymbol.symbol === symbol; } ); @@ -777,27 +859,40 @@ export class PortfolioService { quantity: currentQuantity }); - maxPrice = Math.max(marketPrice ?? 0, maxPrice); - minPrice = Math.min(marketPrice ?? Number.MAX_SAFE_INTEGER, minPrice); + if (marketPrice > marketPriceMax) { + marketPriceMax = marketPrice; + marketPriceMaxDate = parseISO(date); + } + marketPriceMin = Math.min( + marketPrice ?? Number.MAX_SAFE_INTEGER, + marketPriceMin + ); } } else { // Add historical entry for buy date, if no historical data available historicalDataArray.push({ - averagePrice: activitiesOfPosition[0].unitPrice, + averagePrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, date: firstBuyDate, - marketPrice: activitiesOfPosition[0].unitPrice, - quantity: activitiesOfPosition[0].quantity + marketPrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency, + quantity: activitiesOfHolding[0].quantity }); } + const performancePercent = + this.benchmarkService.calculateChangeInPercentage( + marketPriceMax, + marketPrice + ); + return { firstBuyDate, marketPrice, - maxPrice, - minPrice, + marketPriceMax, + marketPriceMin, SymbolProfile, tags, transactionCount, + activities: activitiesOfHolding, averagePrice: averagePrice.toNumber(), dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0], dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), @@ -809,24 +904,27 @@ export class PortfolioService { SymbolProfile.currency, userCurrency ), - grossPerformance: position.grossPerformance?.toNumber(), - grossPerformancePercent: - position.grossPerformancePercentage?.toNumber(), + grossPerformance: grossPerformance?.toNumber(), + grossPerformancePercent: grossPerformancePercentage?.toNumber(), grossPerformancePercentWithCurrencyEffect: - position.grossPerformancePercentageWithCurrencyEffect?.toNumber(), + grossPerformancePercentageWithCurrencyEffect?.toNumber(), grossPerformanceWithCurrencyEffect: - position.grossPerformanceWithCurrencyEffect?.toNumber(), + grossPerformanceWithCurrencyEffect?.toNumber(), historicalData: historicalDataArray, - investment: position.investment?.toNumber(), - netPerformance: position.netPerformance?.toNumber(), - netPerformancePercent: position.netPerformancePercentage?.toNumber(), + investmentInBaseCurrencyWithCurrencyEffect: + investmentWithCurrencyEffect?.toNumber(), + netPerformance: netPerformance?.toNumber(), + netPerformancePercent: netPerformancePercentage?.toNumber(), netPerformancePercentWithCurrencyEffect: - position.netPerformancePercentageWithCurrencyEffectMap?.[ - 'max' - ]?.toNumber(), + netPerformancePercentageWithCurrencyEffectMap?.['max']?.toNumber(), netPerformanceWithCurrencyEffect: - position.netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(), - orders: activitiesOfPosition, + netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(), + performances: { + allTimeHigh: { + performancePercent, + date: marketPriceMaxDate + } + }, quantity: quantity.toNumber(), value: this.exchangeRateDataService.toCurrency( quantity.mul(marketPrice ?? 0).toNumber(), @@ -837,12 +935,12 @@ export class PortfolioService { } else { const currentData = await this.dataProviderService.getQuotes({ user, - items: [{ dataSource: DataSource.YAHOO, symbol: aSymbol }] + items: [{ symbol, dataSource: DataSource.YAHOO }] }); - const marketPrice = currentData[aSymbol]?.marketPrice; + const marketPrice = currentData[symbol]?.marketPrice; let historicalData = await this.dataProviderService.getHistorical( - [{ dataSource: DataSource.YAHOO, symbol: aSymbol }], + [{ symbol, dataSource: DataSource.YAHOO }], 'day', portfolioStart, new Date() @@ -851,40 +949,52 @@ export class PortfolioService { if (isEmpty(historicalData)) { try { historicalData = await this.dataProviderService.getHistoricalRaw({ - assetProfileIdentifiers: [ - { dataSource: DataSource.YAHOO, symbol: aSymbol } - ], + assetProfileIdentifiers: [{ symbol, dataSource: DataSource.YAHOO }], from: portfolioStart, to: new Date() }); } catch { historicalData = { - [aSymbol]: {} + [symbol]: {} }; } } const historicalDataArray: HistoricalDataItem[] = []; - let maxPrice = marketPrice; - let minPrice = marketPrice; + let marketPriceMax = marketPrice; + let marketPriceMaxDate = new Date(); + let marketPriceMin = marketPrice; for (const [date, { marketPrice }] of Object.entries( - historicalData[aSymbol] + historicalData[symbol] )) { historicalDataArray.push({ date, value: marketPrice }); - maxPrice = Math.max(marketPrice ?? 0, maxPrice); - minPrice = Math.min(marketPrice ?? Number.MAX_SAFE_INTEGER, minPrice); + if (marketPrice > marketPriceMax) { + marketPriceMax = marketPrice; + marketPriceMaxDate = parseISO(date); + } + marketPriceMin = Math.min( + marketPrice ?? Number.MAX_SAFE_INTEGER, + marketPriceMin + ); } + const performancePercent = + this.benchmarkService.calculateChangeInPercentage( + marketPriceMax, + marketPrice + ); + return { marketPrice, - maxPrice, - minPrice, + marketPriceMax, + marketPriceMin, SymbolProfile, + activities: [], averagePrice: 0, dataProviderInfo: undefined, dividendInBaseCurrency: 0, @@ -897,12 +1007,17 @@ export class PortfolioService { grossPerformancePercentWithCurrencyEffect: undefined, grossPerformanceWithCurrencyEffect: undefined, historicalData: historicalDataArray, - investment: 0, + investmentInBaseCurrencyWithCurrencyEffect: 0, netPerformance: undefined, netPerformancePercent: undefined, netPerformancePercentWithCurrencyEffect: undefined, netPerformanceWithCurrencyEffect: undefined, - orders: [], + performances: { + allTimeHigh: { + performancePercent, + date: marketPriceMaxDate + } + }, quantity: 0, tags: [], transactionCount: undefined, @@ -911,154 +1026,6 @@ export class PortfolioService { } } - public async getPositions({ - dateRange = 'max', - filters, - impersonationId - }: { - dateRange?: DateRange; - filters?: Filter[]; - impersonationId: string; - }): Promise<{ hasErrors: boolean; positions: Position[] }> { - const searchQuery = filters.find(({ type }) => { - return type === 'SEARCH_QUERY'; - })?.id; - const userId = await this.getUserId(impersonationId, this.request.user.id); - const user = await this.userService.user({ id: userId }); - - const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ - filters, - userId, - userCurrency: this.getUserCurrency() - }); - - if (activities.length === 0) { - return { - hasErrors: false, - positions: [] - }; - } - - const portfolioCalculator = this.calculatorFactory.createCalculator({ - activities, - filters, - userId, - calculationType: PerformanceCalculationType.TWR, - currency: this.request.user.Settings.settings.baseCurrency - }); - - const portfolioSnapshot = await portfolioCalculator.getSnapshot(); - const hasErrors = portfolioSnapshot.hasErrors; - let positions = portfolioSnapshot.positions; - - positions = positions.filter(({ quantity }) => { - return !quantity.eq(0); - }); - - const assetProfileIdentifiers = positions.map(({ dataSource, symbol }) => { - return { - dataSource, - symbol - }; - }); - - const [dataProviderResponses, symbolProfiles] = await Promise.all([ - this.dataProviderService.getQuotes({ - user, - items: assetProfileIdentifiers - }), - this.symbolProfileService.getSymbolProfiles( - positions.map(({ dataSource, symbol }) => { - return { dataSource, symbol }; - }) - ) - ]); - - const symbolProfileMap: { [symbol: string]: EnhancedSymbolProfile } = {}; - - for (const symbolProfile of symbolProfiles) { - symbolProfileMap[symbolProfile.symbol] = symbolProfile; - } - - if (searchQuery) { - positions = positions.filter(({ symbol }) => { - const enhancedSymbolProfile = symbolProfileMap[symbol]; - - return ( - enhancedSymbolProfile.isin?.toLowerCase().startsWith(searchQuery) || - enhancedSymbolProfile.name?.toLowerCase().startsWith(searchQuery) || - enhancedSymbolProfile.symbol?.toLowerCase().startsWith(searchQuery) - ); - }); - } - - return { - hasErrors, - positions: positions.map( - ({ - averagePrice, - currency, - dataSource, - firstBuyDate, - grossPerformance, - grossPerformancePercentage, - grossPerformancePercentageWithCurrencyEffect, - grossPerformanceWithCurrencyEffect, - investment, - investmentWithCurrencyEffect, - netPerformance, - netPerformancePercentage, - netPerformancePercentageWithCurrencyEffectMap, - netPerformanceWithCurrencyEffectMap, - quantity, - symbol, - timeWeightedInvestment, - timeWeightedInvestmentWithCurrencyEffect, - transactionCount - }) => { - return { - currency, - dataSource, - firstBuyDate, - symbol, - transactionCount, - assetClass: symbolProfileMap[symbol].assetClass, - assetSubClass: symbolProfileMap[symbol].assetSubClass, - averagePrice: averagePrice.toNumber(), - grossPerformance: grossPerformance?.toNumber() ?? null, - grossPerformancePercentage: - grossPerformancePercentage?.toNumber() ?? null, - grossPerformancePercentageWithCurrencyEffect: - grossPerformancePercentageWithCurrencyEffect?.toNumber() ?? null, - grossPerformanceWithCurrencyEffect: - grossPerformanceWithCurrencyEffect?.toNumber() ?? null, - investment: investment.toNumber(), - investmentWithCurrencyEffect: - investmentWithCurrencyEffect?.toNumber(), - marketState: - dataProviderResponses[symbol]?.marketState ?? 'delayed', - name: symbolProfileMap[symbol].name, - netPerformance: netPerformance?.toNumber() ?? null, - netPerformancePercentage: - netPerformancePercentage?.toNumber() ?? null, - netPerformancePercentageWithCurrencyEffect: - netPerformancePercentageWithCurrencyEffectMap?.[ - dateRange - ]?.toNumber() ?? null, - netPerformanceWithCurrencyEffect: - netPerformanceWithCurrencyEffectMap?.[dateRange]?.toNumber() ?? - null, - quantity: quantity.toNumber(), - timeWeightedInvestment: timeWeightedInvestment?.toNumber(), - timeWeightedInvestmentWithCurrencyEffect: - timeWeightedInvestmentWithCurrencyEffect?.toNumber() - }; - } - ) - }; - } - public async getPerformance({ dateRange = 'max', filters, @@ -1075,19 +1042,18 @@ export class PortfolioService { const user = await this.userService.user({ id: userId }); const userCurrency = this.getUserCurrency(user); - const accountBalanceItems = - await this.accountBalanceService.getAccountBalanceItems({ + const [accountBalanceItems, { activities }] = await Promise.all([ + this.accountBalanceService.getAccountBalanceItems({ filters, userId, userCurrency - }); - - const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ + }), + this.orderService.getOrdersForPortfolioCalculator({ filters, userCurrency, userId - }); + }) + ]); if (accountBalanceItems.length === 0 && activities.length === 0) { return { @@ -1111,7 +1077,7 @@ export class PortfolioService { activities, filters, userId, - calculationType: PerformanceCalculationType.TWR, + calculationType: this.getUserPerformanceCalculationType(user), currency: userCurrency }); @@ -1133,18 +1099,15 @@ export class PortfolioService { netWorth, totalInvestment, valueWithCurrencyEffect - } = - chart?.length > 0 - ? last(chart) - : { - netPerformance: 0, - netPerformanceInPercentage: 0, - netPerformanceInPercentageWithCurrencyEffect: 0, - netPerformanceWithCurrencyEffect: 0, - netWorth: 0, - totalInvestment: 0, - valueWithCurrencyEffect: 0 - }; + } = chart?.at(-1) ?? { + netPerformance: 0, + netPerformanceInPercentage: 0, + netPerformanceInPercentageWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, + netWorth: 0, + totalInvestment: 0, + valueWithCurrencyEffect: 0 + }; return { chart, @@ -1164,18 +1127,29 @@ export class PortfolioService { }; } - public async getReport( - impersonationId: string - ): Promise { - const userId = await this.getUserId(impersonationId, this.request.user.id); - const userSettings = this.request.user.Settings.settings as UserSettings; + public async getReport({ + impersonationId, + userId + }: { + impersonationId: string; + userId: string; + }): Promise { + userId = await this.getUserId(impersonationId, userId); + const userSettings = this.request.user.settings.settings as UserSettings; - const { accounts, holdings, markets, summary } = await this.getDetails({ - impersonationId, - userId, - withMarkets: true, - withSummary: true - }); + const { accounts, holdings, markets, marketsAdvanced, summary } = + await this.getDetails({ + impersonationId, + userId, + withMarkets: true, + withSummary: true + }); + + const marketsAdvancedTotalInBaseCurrency = getSum( + Object.values(marketsAdvanced).map(({ valueInBaseCurrency }) => { + return new Big(valueInBaseCurrency); + }) + ).toNumber(); const marketsTotalInBaseCurrency = getSum( Object.values(markets).map(({ valueInBaseCurrency }) => { @@ -1183,17 +1157,21 @@ export class PortfolioService { }) ).toNumber(); - const rules: PortfolioReportResponse['rules'] = { + const rules: PortfolioReportResponse['xRay']['rules'] = { accountClusterRisk: - summary.ordersCount > 0 + summary.activityCount > 0 ? await this.rulesService.evaluate( [ new AccountClusterRiskCurrentInvestment( this.exchangeRateDataService, + this.i18nService, + userSettings.language, accounts ), new AccountClusterRiskSingleAccount( this.exchangeRateDataService, + this.i18nService, + userSettings.language, accounts ) ], @@ -1201,15 +1179,19 @@ export class PortfolioService { ) : undefined, assetClassClusterRisk: - summary.ordersCount > 0 + summary.activityCount > 0 ? await this.rulesService.evaluate( [ new AssetClassClusterRiskEquity( this.exchangeRateDataService, + this.i18nService, + userSettings.language, Object.values(holdings) ), new AssetClassClusterRiskFixedIncome( this.exchangeRateDataService, + this.i18nService, + userSettings.language, Object.values(holdings) ) ], @@ -1217,34 +1199,42 @@ export class PortfolioService { ) : undefined, currencyClusterRisk: - summary.ordersCount > 0 + summary.activityCount > 0 ? await this.rulesService.evaluate( [ new CurrencyClusterRiskBaseCurrencyCurrentInvestment( this.exchangeRateDataService, - Object.values(holdings) + this.i18nService, + Object.values(holdings), + userSettings.language ), new CurrencyClusterRiskCurrentInvestment( this.exchangeRateDataService, - Object.values(holdings) + this.i18nService, + Object.values(holdings), + userSettings.language ) ], userSettings ) : undefined, economicMarketClusterRisk: - summary.ordersCount > 0 + summary.activityCount > 0 ? await this.rulesService.evaluate( [ new EconomicMarketClusterRiskDevelopedMarkets( this.exchangeRateDataService, + this.i18nService, marketsTotalInBaseCurrency, - markets.developedMarkets.valueInBaseCurrency + markets.developedMarkets.valueInBaseCurrency, + userSettings.language ), new EconomicMarketClusterRiskEmergingMarkets( this.exchangeRateDataService, + this.i18nService, marketsTotalInBaseCurrency, - markets.emergingMarkets.valueInBaseCurrency + markets.emergingMarkets.valueInBaseCurrency, + userSettings.language ) ], userSettings @@ -1254,7 +1244,13 @@ export class PortfolioService { [ new EmergencyFundSetup( this.exchangeRateDataService, - userSettings.emergencyFund + this.i18nService, + userSettings.language, + this.getTotalEmergencyFund({ + userSettings, + emergencyFundHoldingsValueInBaseCurrency: + this.getEmergencyFundHoldingsValueInBaseCurrency({ holdings }) + }).toNumber() ) ], userSettings @@ -1263,15 +1259,65 @@ export class PortfolioService { [ new FeeRatioInitialInvestment( this.exchangeRateDataService, + this.i18nService, + userSettings.language, summary.committedFunds, summary.fees ) ], userSettings - ) + ), + regionalMarketClusterRisk: + summary.activityCount > 0 + ? await this.rulesService.evaluate( + [ + new RegionalMarketClusterRiskAsiaPacific( + this.exchangeRateDataService, + this.i18nService, + userSettings.language, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.asiaPacific.valueInBaseCurrency + ), + new RegionalMarketClusterRiskEmergingMarkets( + this.exchangeRateDataService, + this.i18nService, + userSettings.language, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.emergingMarkets.valueInBaseCurrency + ), + new RegionalMarketClusterRiskEurope( + this.exchangeRateDataService, + this.i18nService, + userSettings.language, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.europe.valueInBaseCurrency + ), + new RegionalMarketClusterRiskJapan( + this.exchangeRateDataService, + this.i18nService, + userSettings.language, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.japan.valueInBaseCurrency + ), + new RegionalMarketClusterRiskNorthAmerica( + this.exchangeRateDataService, + this.i18nService, + userSettings.language, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.northAmerica.valueInBaseCurrency + ) + ], + userSettings + ) + : undefined }; - return { rules, statistics: this.getReportStatistics(rules) }; + return { + xRay: { + rules, + statistics: this.getReportStatistics(rules) + } + }; } public async updateTags({ @@ -1431,7 +1477,7 @@ export class PortfolioService { return { markets, marketsAdvanced }; } - private async getCashPositions({ + private getCashPositions({ cashDetails, userCurrency, value @@ -1543,7 +1589,7 @@ export class PortfolioService { return dividendsByGroup; } - private getEmergencyFundPositionsValueInBaseCurrency({ + private getEmergencyFundHoldingsValueInBaseCurrency({ holdings }: { holdings: PortfolioDetails['holdings']; @@ -1553,19 +1599,19 @@ export class PortfolioService { const emergencyFundHoldings = Object.values(holdings).filter(({ tags }) => { return ( tags?.some(({ id }) => { - return id === EMERGENCY_FUND_TAG_ID; + return id === TAG_ID_EMERGENCY_FUND; }) ?? false ); }); - let valueInBaseCurrencyOfEmergencyFundPositions = new Big(0); + let valueInBaseCurrencyOfEmergencyFundHoldings = new Big(0); for (const { valueInBaseCurrency } of emergencyFundHoldings) { - valueInBaseCurrencyOfEmergencyFundPositions = - valueInBaseCurrencyOfEmergencyFundPositions.plus(valueInBaseCurrency); + valueInBaseCurrencyOfEmergencyFundHoldings = + valueInBaseCurrencyOfEmergencyFundHoldings.plus(valueInBaseCurrency); } - return valueInBaseCurrencyOfEmergencyFundPositions.toNumber(); + return valueInBaseCurrencyOfEmergencyFundHoldings.toNumber(); } private getInitialCashPosition({ @@ -1691,8 +1737,8 @@ export class PortfolioService { } private getReportStatistics( - evaluatedRules: PortfolioReportResponse['rules'] - ): PortfolioReportResponse['statistics'] { + evaluatedRules: PortfolioReportResponse['xRay']['rules'] + ): PortfolioReportResponse['xRay']['statistics'] { const rulesActiveCount = Object.values(evaluatedRules) .flat() .filter((rule) => { @@ -1732,7 +1778,7 @@ export class PortfolioService { private async getSummary({ balanceInBaseCurrency, - emergencyFundPositionsValueInBaseCurrency, + emergencyFundHoldingsValueInBaseCurrency, filteredValueInBaseCurrency, impersonationId, portfolioCalculator, @@ -1740,7 +1786,7 @@ export class PortfolioService { userId }: { balanceInBaseCurrency: number; - emergencyFundPositionsValueInBaseCurrency: number; + emergencyFundHoldingsValueInBaseCurrency: number; filteredValueInBaseCurrency: Big; impersonationId: string; portfolioCalculator: PortfolioCalculator; @@ -1760,7 +1806,7 @@ export class PortfolioService { const nonExcludedActivities: Activity[] = []; for (const activity of activities) { - if (activity.Account?.isExcluded) { + if (activity.account?.isExcluded) { excludedActivities.push(activity); } else { nonExcludedActivities.push(activity); @@ -1785,12 +1831,10 @@ export class PortfolioService { const dividendInBaseCurrency = await portfolioCalculator.getDividendInBaseCurrency(); - const emergencyFund = new Big( - Math.max( - emergencyFundPositionsValueInBaseCurrency, - (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 - ) - ); + const totalEmergencyFund = this.getTotalEmergencyFund({ + emergencyFundHoldingsValueInBaseCurrency, + userSettings: user.settings?.settings as UserSettings + }); const fees = await portfolioCalculator.getFeesInBaseCurrency(); @@ -1801,8 +1845,6 @@ export class PortfolioService { const liabilities = await portfolioCalculator.getLiabilitiesInBaseCurrency(); - const valuables = await portfolioCalculator.getValuablesInBaseCurrency(); - const totalBuy = this.getSumOfActivityType({ userCurrency, activities: nonExcludedActivities, @@ -1816,8 +1858,8 @@ export class PortfolioService { }).toNumber(); const cash = new Big(balanceInBaseCurrency) - .minus(emergencyFund) - .plus(emergencyFundPositionsValueInBaseCurrency) + .minus(totalEmergencyFund) + .plus(emergencyFundHoldingsValueInBaseCurrency) .toNumber(); const committedFunds = new Big(totalBuy).minus(totalSell); @@ -1851,7 +1893,6 @@ export class PortfolioService { const netWorth = new Big(balanceInBaseCurrency) .plus(currentValueInBaseCurrency) - .plus(valuables) .plus(excludedAccountsAndActivities) .minus(liabilities) .toNumber(); @@ -1876,22 +1917,24 @@ export class PortfolioService { annualizedPerformancePercentWithCurrencyEffect, cash, excludedAccountsAndActivities, - firstOrderDate, netPerformance, netPerformancePercentage, netPerformancePercentageWithCurrencyEffect, netPerformanceWithCurrencyEffect, totalBuy, totalSell, + activityCount: activities.filter(({ type }) => { + return ['BUY', 'SELL'].includes(type); + }).length, committedFunds: committedFunds.toNumber(), currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), emergencyFund: { - assets: emergencyFundPositionsValueInBaseCurrency, - cash: emergencyFund - .minus(emergencyFundPositionsValueInBaseCurrency) + assets: emergencyFundHoldingsValueInBaseCurrency, + cash: totalEmergencyFund + .minus(emergencyFundHoldingsValueInBaseCurrency) .toNumber(), - total: emergencyFund.toNumber() + total: totalEmergencyFund.toNumber() }, fees: fees.toNumber(), filteredValueInBaseCurrency: filteredValueInBaseCurrency.toNumber(), @@ -1899,7 +1942,7 @@ export class PortfolioService { ? filteredValueInBaseCurrency.div(netWorth).toNumber() : undefined, fireWealth: new Big(currentValueInBaseCurrency) - .minus(emergencyFundPositionsValueInBaseCurrency) + .minus(emergencyFundHoldingsValueInBaseCurrency) .toNumber(), grossPerformance: new Big(netPerformance).plus(fees).toNumber(), grossPerformanceWithCurrencyEffect: new Big( @@ -1908,11 +1951,7 @@ export class PortfolioService { .plus(fees) .toNumber(), interest: interest.toNumber(), - items: valuables.toNumber(), liabilities: liabilities.toNumber(), - ordersCount: activities.filter(({ type }) => { - return ['BUY', 'SELL'].includes(type); - }).length, totalInvestment: totalInvestment.toNumber(), totalValueInBaseCurrency: netWorth }; @@ -1944,10 +1983,25 @@ export class PortfolioService { ); } + private getTotalEmergencyFund({ + emergencyFundHoldingsValueInBaseCurrency, + userSettings + }: { + emergencyFundHoldingsValueInBaseCurrency: number; + userSettings: UserSettings; + }) { + return new Big( + Math.max( + emergencyFundHoldingsValueInBaseCurrency, + userSettings?.emergencyFund ?? 0 + ) + ); + } + private getUserCurrency(aUser?: UserWithSettings) { return ( - aUser?.Settings?.settings.baseCurrency ?? - this.request.user?.Settings?.settings.baseCurrency ?? + aUser?.settings?.settings.baseCurrency ?? + this.request.user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY ); } @@ -1959,6 +2013,12 @@ export class PortfolioService { return impersonationUserId || aUserId; } + private getUserPerformanceCalculationType( + aUser: UserWithSettings + ): PerformanceCalculationType { + return aUser?.settings?.settings.performanceCalculationType; + } + private async getValueOfAccountsAndPlatforms({ activities, filters = [], @@ -1979,29 +2039,31 @@ export class PortfolioService { let currentAccounts: (Account & { Order?: Order[]; - Platform?: Platform; + platform?: Platform; })[] = []; if (filters.length === 0) { currentAccounts = await this.accountService.getAccounts(userId); } else if (filters.length === 1 && filters[0].type === 'ACCOUNT') { currentAccounts = await this.accountService.accounts({ - include: { Platform: true }, + include: { platform: true }, where: { id: filters[0].id } }); } else { - const accountIds = uniq( - activities - .filter(({ accountId }) => { - return accountId; - }) - .map(({ accountId }) => { - return accountId; - }) + const accountIds = Array.from( + new Set( + activities + .filter(({ accountId }) => { + return accountId; + }) + .map(({ accountId }) => { + return accountId; + }) + ) ); currentAccounts = await this.accountService.accounts({ - include: { Platform: true }, + include: { platform: true }, where: { id: { in: accountIds } } }); } @@ -2026,18 +2088,18 @@ export class PortfolioService { ) }; - if (platforms[account.Platform?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { - platforms[account.Platform?.id || UNKNOWN_KEY].valueInBaseCurrency += + if (platforms[account.platformId || UNKNOWN_KEY]?.valueInBaseCurrency) { + platforms[account.platformId || UNKNOWN_KEY].valueInBaseCurrency += this.exchangeRateDataService.toCurrency( account.balance, account.currency, userCurrency ); } else { - platforms[account.Platform?.id || UNKNOWN_KEY] = { + platforms[account.platformId || UNKNOWN_KEY] = { balance: account.balance, currency: account.currency, - name: account.Platform?.name, + name: account.platform?.name, valueInBaseCurrency: this.exchangeRateDataService.toCurrency( account.balance, account.currency, @@ -2047,7 +2109,7 @@ export class PortfolioService { } for (const { - Account, + account, quantity, SymbolProfile, type @@ -2058,28 +2120,28 @@ export class PortfolioService { (portfolioItemsNow[SymbolProfile.symbol]?.marketPriceInBaseCurrency ?? 0); - if (accounts[Account?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { - accounts[Account?.id || UNKNOWN_KEY].valueInBaseCurrency += + if (accounts[account?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { + accounts[account?.id || UNKNOWN_KEY].valueInBaseCurrency += currentValueOfSymbolInBaseCurrency; } else { - accounts[Account?.id || UNKNOWN_KEY] = { + accounts[account?.id || UNKNOWN_KEY] = { balance: 0, - currency: Account?.currency, + currency: account?.currency, name: account.name, valueInBaseCurrency: currentValueOfSymbolInBaseCurrency }; } if ( - platforms[Account?.Platform?.id || UNKNOWN_KEY]?.valueInBaseCurrency + platforms[account?.platformId || UNKNOWN_KEY]?.valueInBaseCurrency ) { - platforms[Account?.Platform?.id || UNKNOWN_KEY].valueInBaseCurrency += + platforms[account?.platformId || UNKNOWN_KEY].valueInBaseCurrency += currentValueOfSymbolInBaseCurrency; } else { - platforms[Account?.Platform?.id || UNKNOWN_KEY] = { + platforms[account?.platformId || UNKNOWN_KEY] = { balance: 0, - currency: Account?.currency, - name: account.Platform?.name, + currency: account?.currency, + name: account.platform?.name, valueInBaseCurrency: currentValueOfSymbolInBaseCurrency }; } diff --git a/apps/api/src/app/portfolio/rules.service.ts b/apps/api/src/app/portfolio/rules.service.ts index 48d1658aa..7f6d964f5 100644 --- a/apps/api/src/app/portfolio/rules.service.ts +++ b/apps/api/src/app/portfolio/rules.service.ts @@ -22,6 +22,7 @@ export class RulesService { return { evaluation, value, + categoryName: rule.getCategoryName(), configuration: rule.getConfiguration(), isActive: true, key: rule.getKey(), @@ -29,6 +30,7 @@ export class RulesService { }; } else { return { + categoryName: rule.getCategoryName(), isActive: false, key: rule.getKey(), name: rule.getName() diff --git a/apps/api/src/app/redis-cache/redis-cache.module.ts b/apps/api/src/app/redis-cache/redis-cache.module.ts index 5411309bd..d0e3228b7 100644 --- a/apps/api/src/app/redis-cache/redis-cache.module.ts +++ b/apps/api/src/app/redis-cache/redis-cache.module.ts @@ -1,17 +1,16 @@ import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { createKeyv } from '@keyv/redis'; import { CacheModule } from '@nestjs/cache-manager'; import { Module } from '@nestjs/common'; -import { redisStore } from 'cache-manager-redis-yet'; -import type { RedisClientOptions } from 'redis'; import { RedisCacheService } from './redis-cache.service'; @Module({ exports: [RedisCacheService], imports: [ - CacheModule.registerAsync({ + CacheModule.registerAsync({ imports: [ConfigurationModule], inject: [ConfigurationService], useFactory: async (configurationService: ConfigurationService) => { @@ -20,10 +19,13 @@ import { RedisCacheService } from './redis-cache.service'; ); return { - store: redisStore, - ttl: configurationService.get('CACHE_TTL'), - url: `redis://${redisPassword ? `:${redisPassword}` : ''}@${configurationService.get('REDIS_HOST')}:${configurationService.get('REDIS_PORT')}/${configurationService.get('REDIS_DB')}` - } as RedisClientOptions; + stores: [ + createKeyv( + `redis://${redisPassword ? `:${redisPassword}` : ''}@${configurationService.get('REDIS_HOST')}:${configurationService.get('REDIS_PORT')}/${configurationService.get('REDIS_DB')}` + ) + ], + ttl: configurationService.get('CACHE_TTL') + }; } }), ConfigurationModule diff --git a/apps/api/src/app/redis-cache/redis-cache.service.ts b/apps/api/src/app/redis-cache/redis-cache.service.ts index c972c30a1..621199cc9 100644 --- a/apps/api/src/app/redis-cache/redis-cache.service.ts +++ b/apps/api/src/app/redis-cache/redis-cache.service.ts @@ -2,21 +2,31 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/con import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, Filter } from '@ghostfolio/common/interfaces'; -import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; import { Inject, Injectable, Logger } from '@nestjs/common'; -import { Milliseconds } from 'cache-manager'; -import { RedisCache } from 'cache-manager-redis-yet'; import { createHash } from 'crypto'; +import Keyv from 'keyv'; +import ms from 'ms'; @Injectable() export class RedisCacheService { + private client: Keyv; + public constructor( - @Inject(CACHE_MANAGER) private readonly cache: RedisCache, + @Inject(CACHE_MANAGER) private readonly cache: Cache, private readonly configurationService: ConfigurationService ) { - const client = cache.store.client; + this.client = cache.stores[0]; + + this.client.deserialize = (value) => { + try { + return JSON.parse(value); + } catch {} + + return value; + }; - client.on('error', (error) => { + this.client.on('error', (error) => { Logger.error(error, 'RedisCacheService'); }); } @@ -26,13 +36,18 @@ export class RedisCacheService { } public async getKeys(aPrefix?: string): Promise { - let prefix = aPrefix; - - if (prefix) { - prefix = `${prefix}*`; - } - - return this.cache.store.keys(prefix); + const keys: string[] = []; + const prefix = aPrefix; + + try { + for await (const [key] of this.client.iterator({})) { + if ((prefix && key.startsWith(prefix)) || !prefix) { + keys.push(key); + } + } + } catch {} + + return keys; } public getPortfolioSnapshotKey({ @@ -59,6 +74,40 @@ export class RedisCacheService { return `quote-${getAssetProfileIdentifier({ dataSource, symbol })}`; } + public async isHealthy() { + const testKey = '__health_check__'; + const testValue = Date.now().toString(); + + try { + await Promise.race([ + (async () => { + await this.set(testKey, testValue, ms('1 second')); + const result = await this.get(testKey); + + if (result !== testValue) { + throw new Error('Redis health check failed: value mismatch'); + } + })(), + new Promise((_, reject) => + setTimeout( + () => reject(new Error('Redis health check failed: timeout')), + ms('2 seconds') + ) + ) + ]); + + return true; + } catch (error) { + Logger.error(error?.message, 'RedisCacheService'); + + return false; + } finally { + try { + await this.remove(testKey); + } catch {} + } + } + public async remove(key: string) { return this.cache.del(key); } @@ -72,16 +121,14 @@ export class RedisCacheService { `${this.getPortfolioSnapshotKey({ userId })}` ); - for (const key of keys) { - await this.remove(key); - } + return this.cache.mdel(keys); } public async reset() { - return this.cache.reset(); + return this.cache.clear(); } - public async set(key: string, value: string, ttl?: Milliseconds) { + public async set(key: string, value: string, ttl?: number) { return this.cache.set( key, value, diff --git a/apps/api/src/app/sitemap/sitemap.controller.ts b/apps/api/src/app/sitemap/sitemap.controller.ts deleted file mode 100644 index ea21906ef..000000000 --- a/apps/api/src/app/sitemap/sitemap.controller.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; -import { - DATE_FORMAT, - getYesterday, - interpolate -} from '@ghostfolio/common/helper'; -import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; - -import { Controller, Get, Res, VERSION_NEUTRAL, Version } from '@nestjs/common'; -import { format } from 'date-fns'; -import { Response } from 'express'; -import * as fs from 'fs'; -import * as path from 'path'; - -@Controller('sitemap.xml') -export class SitemapController { - public sitemapXml = ''; - - public constructor( - private readonly configurationService: ConfigurationService - ) { - try { - this.sitemapXml = fs.readFileSync( - path.join(__dirname, 'assets', 'sitemap.xml'), - 'utf8' - ); - } catch {} - } - - @Get() - @Version(VERSION_NEUTRAL) - public async getSitemapXml(@Res() response: Response): Promise { - const currentDate = format(getYesterday(), DATE_FORMAT); - - response.setHeader('content-type', 'application/xml'); - response.send( - interpolate(this.sitemapXml, { - currentDate, - personalFinanceTools: this.configurationService.get( - 'ENABLE_FEATURE_SUBSCRIPTION' - ) - ? personalFinanceTools - .map(({ alias, key }) => { - return [ - '', - ` https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/es/recursos/personal-finance-tools/alternativa-de-software-libre-a-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/fr/ressources/personal-finance-tools/alternative-open-source-a-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/it/risorse/personal-finance-tools/alternativa-open-source-a-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/nl/bronnen/personal-finance-tools/open-source-alternatief-voor-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '', - '', - ` https://ghostfol.io/pt/recursos/personal-finance-tools/alternativa-de-software-livre-ao-${alias ?? key}`, - ` ${currentDate}T00:00:00+00:00`, - '' - ].join('\n'); - }) - .join('\n') - : '' - }) - ); - } -} diff --git a/apps/api/src/app/subscription/subscription.controller.ts b/apps/api/src/app/subscription/subscription.controller.ts index f37543fdf..244a6b806 100644 --- a/apps/api/src/app/subscription/subscription.controller.ts +++ b/apps/api/src/app/subscription/subscription.controller.ts @@ -49,8 +49,7 @@ export class SubscriptionController { } let coupons = - ((await this.propertyService.getByKey(PROPERTY_COUPONS)) as Coupon[]) ?? - []; + (await this.propertyService.getByKey(PROPERTY_COUPONS)) ?? []; const coupon = coupons.find((currentCoupon) => { return currentCoupon.code === couponCode; diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index ae0260d8c..4aa1897a1 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -32,7 +32,7 @@ export class SubscriptionService { this.stripe = new Stripe( this.configurationService.get('STRIPE_SECRET_KEY'), { - apiVersion: '2024-09-30.acacia' + apiVersion: '2025-06-30.basil' } ); } @@ -50,8 +50,7 @@ export class SubscriptionService { const subscriptionOffers: { [offer in SubscriptionOfferKey]: SubscriptionOffer; } = - ((await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) as any) ?? - {}; + (await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) ?? {}; const subscriptionOffer = Object.values(subscriptionOffers).find( (subscriptionOffer) => { @@ -61,7 +60,7 @@ export class SubscriptionService { const checkoutSessionCreateParams: Stripe.Checkout.SessionCreateParams = { cancel_url: `${this.configurationService.get('ROOT_URL')}/${ - user.Settings?.settings?.language ?? DEFAULT_LANGUAGE_CODE + user.settings.settings.language }/account`, client_reference_id: user.id, line_items: [ @@ -71,7 +70,7 @@ export class SubscriptionService { } ], locale: - (user.Settings?.settings + (user.settings?.settings ?.language as Stripe.Checkout.SessionCreateParams.Locale) ?? DEFAULT_LANGUAGE_CODE, metadata: subscriptionOffer @@ -122,7 +121,7 @@ export class SubscriptionService { data: { expiresAt, price, - User: { + user: { connect: { id: userId } @@ -158,38 +157,66 @@ export class SubscriptionService { } } - public getSubscription({ + public async getSubscription({ createdAt, subscriptions }: { createdAt: UserWithSettings['createdAt']; subscriptions: Subscription[]; - }): UserWithSettings['subscription'] { + }): Promise { if (subscriptions.length > 0) { const { expiresAt, price } = subscriptions.reduce((a, b) => { return new Date(a.expiresAt) > new Date(b.expiresAt) ? a : b; }); - let offer: SubscriptionOfferKey = price ? 'renewal' : 'default'; + let offerKey: SubscriptionOfferKey = price ? 'renewal' : 'default'; if (isBefore(createdAt, parseDate('2023-01-01'))) { - offer = 'renewal-early-bird-2023'; + offerKey = 'renewal-early-bird-2023'; } else if (isBefore(createdAt, parseDate('2024-01-01'))) { - offer = 'renewal-early-bird-2024'; + offerKey = 'renewal-early-bird-2024'; } + const offer = await this.getSubscriptionOffer({ + key: offerKey + }); + return { - expiresAt, offer, + expiresAt: isBefore(new Date(), expiresAt) ? expiresAt : undefined, type: isBefore(new Date(), expiresAt) ? SubscriptionType.Premium : SubscriptionType.Basic }; } else { + const offer = await this.getSubscriptionOffer({ + key: 'default' + }); + return { - offer: 'default', + offer, type: SubscriptionType.Basic }; } } + + public async getSubscriptionOffer({ + key + }: { + key: SubscriptionOfferKey; + }): Promise { + if (!this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { + return undefined; + } + + const offers: { + [offer in SubscriptionOfferKey]: SubscriptionOffer; + } = + (await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) ?? {}; + + return { + ...offers[key], + isRenewal: key.startsWith('renewal') + }; + } } diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index 89cdd416c..5d9a49a29 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -47,7 +47,7 @@ export class SymbolController { try { return this.symbolService.lookup({ includeIndices, - query: query.toLowerCase(), + query, user: this.request.user }); } catch { diff --git a/apps/api/src/app/tag/create-tag.dto.ts b/apps/api/src/app/tag/create-tag.dto.ts deleted file mode 100644 index 650a0ce12..000000000 --- a/apps/api/src/app/tag/create-tag.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IsString } from 'class-validator'; - -export class CreateTagDto { - @IsString() - name: string; -} diff --git a/apps/api/src/app/tag/tag.module.ts b/apps/api/src/app/tag/tag.module.ts deleted file mode 100644 index 48587c54e..000000000 --- a/apps/api/src/app/tag/tag.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; - -import { Module } from '@nestjs/common'; - -import { TagController } from './tag.controller'; -import { TagService } from './tag.service'; - -@Module({ - controllers: [TagController], - exports: [TagService], - imports: [PrismaModule], - providers: [TagService] -}) -export class TagModule {} diff --git a/apps/api/src/app/tag/tag.service.ts b/apps/api/src/app/tag/tag.service.ts deleted file mode 100644 index c4a5447ac..000000000 --- a/apps/api/src/app/tag/tag.service.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; - -import { Injectable } from '@nestjs/common'; -import { Prisma, Tag } from '@prisma/client'; - -@Injectable() -export class TagService { - public constructor(private readonly prismaService: PrismaService) {} - - public async createTag(data: Prisma.TagCreateInput) { - return this.prismaService.tag.create({ - data - }); - } - - public async deleteTag(where: Prisma.TagWhereUniqueInput): Promise { - return this.prismaService.tag.delete({ where }); - } - - public async getTag( - tagWhereUniqueInput: Prisma.TagWhereUniqueInput - ): Promise { - return this.prismaService.tag.findUnique({ - where: tagWhereUniqueInput - }); - } - - public async getTags({ - cursor, - orderBy, - skip, - take, - where - }: { - cursor?: Prisma.TagWhereUniqueInput; - orderBy?: Prisma.TagOrderByWithRelationInput; - skip?: number; - take?: number; - where?: Prisma.TagWhereInput; - } = {}) { - return this.prismaService.tag.findMany({ - cursor, - orderBy, - skip, - take, - where - }); - } - - public async getTagsWithActivityCount() { - const tagsWithOrderCount = await this.prismaService.tag.findMany({ - include: { - _count: { - select: { orders: true } - } - } - }); - - return tagsWithOrderCount.map(({ _count, id, name, userId }) => { - return { - id, - name, - userId, - activityCount: _count.orders - }; - }); - } - - public async updateTag({ - data, - where - }: { - data: Prisma.TagUpdateInput; - where: Prisma.TagWhereUniqueInput; - }): Promise { - return this.prismaService.tag.update({ - data, - where - }); - } -} diff --git a/apps/api/src/app/tag/update-tag.dto.ts b/apps/api/src/app/tag/update-tag.dto.ts deleted file mode 100644 index b26ffde11..000000000 --- a/apps/api/src/app/tag/update-tag.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsString } from 'class-validator'; - -export class UpdateTagDto { - @IsString() - id: string; - - @IsString() - name: string; -} diff --git a/apps/api/src/app/user/update-own-access-token.dto.ts b/apps/api/src/app/user/update-own-access-token.dto.ts new file mode 100644 index 000000000..42f6f7289 --- /dev/null +++ b/apps/api/src/app/user/update-own-access-token.dto.ts @@ -0,0 +1,6 @@ +import { IsString } from 'class-validator'; + +export class UpdateOwnAccessTokenDto { + @IsString() + accessToken: string; +} diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 149e06285..e545fd335 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -1,8 +1,13 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; -import { User, UserSettings } from '@ghostfolio/common/interfaces'; +import { + AccessTokenResponse, + User, + UserSettings +} from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; @@ -28,6 +33,7 @@ import { merge, size } from 'lodash'; import { DeleteOwnUserDto } from './delete-own-user.dto'; import { UserItem } from './interfaces/user-item.interface'; +import { UpdateOwnAccessTokenDto } from './update-own-access-token.dto'; import { UpdateUserSettingDto } from './update-user-setting.dto'; import { UserService } from './user.service'; @@ -36,6 +42,7 @@ export class UserController { public constructor( private readonly configurationService: ConfigurationService, private readonly jwtService: JwtService, + private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, @Inject(REQUEST) private readonly request: RequestWithUser, private readonly userService: UserService @@ -47,24 +54,12 @@ export class UserController { public async deleteOwnUser( @Body() data: DeleteOwnUserDto ): Promise { - const hashedAccessToken = this.userService.createAccessToken( + const user = await this.validateAccessToken( data.accessToken, - this.configurationService.get('ACCESS_TOKEN_SALT') + this.request.user.id ); - const [user] = await this.userService.users({ - where: { accessToken: hashedAccessToken, id: this.request.user.id } - }); - - if (!user) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - return this.userService.deleteUser({ - accessToken: hashedAccessToken, id: user.id }); } @@ -85,6 +80,29 @@ export class UserController { }); } + @HasPermission(permissions.accessAdminControl) + @Post(':id/access-token') + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async updateUserAccessToken( + @Param('id') id: string + ): Promise { + return this.rotateUserAccessToken(id); + } + + @HasPermission(permissions.updateOwnAccessToken) + @Post('access-token') + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async updateOwnAccessToken( + @Body() data: UpdateOwnAccessTokenDto + ): Promise { + const user = await this.validateAccessToken( + data.accessToken, + this.request.user.id + ); + + return this.rotateUserAccessToken(user.id); + } + @Get() @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async getUser( @@ -148,7 +166,7 @@ export class UserController { const userSettings: UserSettings = merge( {}, - this.request.user.Settings.settings as UserSettings, + this.request.user.settings.settings as UserSettings, data ); @@ -164,4 +182,43 @@ export class UserController { userId: this.request.user.id }); } + + private async rotateUserAccessToken( + userId: string + ): Promise { + const { accessToken, hashedAccessToken } = + this.userService.generateAccessToken({ + userId + }); + + await this.prismaService.user.update({ + data: { accessToken: hashedAccessToken }, + where: { id: userId } + }); + + return { accessToken }; + } + + private async validateAccessToken( + accessToken: string, + userId: string + ): Promise { + const hashedAccessToken = this.userService.createAccessToken({ + password: accessToken, + salt: this.configurationService.get('ACCESS_TOKEN_SALT') + }); + + const [user] = await this.userService.users({ + where: { accessToken: hashedAccessToken, id: userId } + }); + + if (!user) { + throw new HttpException( + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN + ); + } + + return user; + } } diff --git a/apps/api/src/app/user/user.module.ts b/apps/api/src/app/user/user.module.ts index 063cfef82..8a21b0a55 100644 --- a/apps/api/src/app/user/user.module.ts +++ b/apps/api/src/app/user/user.module.ts @@ -1,6 +1,7 @@ import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { I18nModule } from '@ghostfolio/api/services/i18n/i18n.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { TagModule } from '@ghostfolio/api/services/tag/tag.module'; @@ -16,6 +17,7 @@ import { UserService } from './user.service'; exports: [UserService], imports: [ ConfigurationModule, + I18nModule, JwtModule.register({ secret: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: '30 days' } diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 33e9a67da..a043761fa 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -13,6 +13,11 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets'; import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup'; import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment'; +import { RegionalMarketClusterRiskAsiaPacific } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/asia-pacific'; +import { RegionalMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/emerging-markets'; +import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe'; +import { RegionalMarketClusterRiskJapan } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/japan'; +import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; @@ -36,6 +41,7 @@ import { permissions } from '@ghostfolio/common/permissions'; import { UserWithSettings } from '@ghostfolio/common/types'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; @@ -46,11 +52,10 @@ import { sortBy, without } from 'lodash'; @Injectable() export class UserService { - private i18nService = new I18nService(); - public constructor( private readonly configurationService: ConfigurationService, private readonly eventEmitter: EventEmitter2, + private readonly i18nService: I18nService, private readonly orderService: OrderService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, @@ -62,24 +67,47 @@ export class UserService { return this.prismaService.user.count(args); } - public createAccessToken(password: string, salt: string): string { + public createAccessToken({ + password, + salt + }: { + password: string; + salt: string; + }): string { const hash = createHmac('sha512', salt); hash.update(password); return hash.digest('hex'); } + public generateAccessToken({ userId }: { userId: string }) { + const accessToken = this.createAccessToken({ + password: userId, + salt: getRandomString(10) + }); + + const hashedAccessToken = this.createAccessToken({ + password: accessToken, + salt: this.configurationService.get('ACCESS_TOKEN_SALT') + }); + + return { accessToken, hashedAccessToken }; + } + public async getUser( - { Account, id, permissions, Settings, subscription }: UserWithSettings, + { accounts, id, permissions, settings, subscription }: UserWithSettings, aLocale = locale ): Promise { const userData = await Promise.all([ this.prismaService.access.findMany({ include: { - User: true + user: true }, orderBy: { alias: 'asc' }, - where: { GranteeUser: { id } } + where: { granteeUserId: id } + }), + this.prismaService.order.count({ + where: { userId: id } }), this.prismaService.order.findFirst({ orderBy: { @@ -91,14 +119,16 @@ export class UserService { ]); const access = userData[0]; - const firstActivity = userData[1]; - let tags = userData[2]; + const activitiesCount = userData[1]; + const firstActivity = userData[2]; + let tags = userData[3]; let systemMessage: SystemMessage; - const systemMessageProperty = (await this.propertyService.getByKey( - PROPERTY_SYSTEM_MESSAGE - )) as SystemMessage; + const systemMessageProperty = + await this.propertyService.getByKey( + PROPERTY_SYSTEM_MESSAGE + ); if (systemMessageProperty?.targetGroups?.includes(subscription?.type)) { systemMessage = systemMessageProperty; @@ -112,6 +142,8 @@ export class UserService { } return { + accounts, + activitiesCount, id, permissions, subscription, @@ -124,11 +156,10 @@ export class UserService { permissions: accessItem.permissions }; }), - accounts: Account, dateOfFirstActivity: firstActivity?.date ?? new Date(), settings: { - ...(Settings.settings as UserSettings), - locale: (Settings.settings as UserSettings)?.locale ?? aLocale + ...(settings.settings as UserSettings), + locale: (settings.settings as UserSettings)?.locale ?? aLocale } }; } @@ -149,56 +180,56 @@ export class UserService { userWhereUniqueInput: Prisma.UserWhereUniqueInput ): Promise { const { - Access, + accessesGet, accessToken, - Account, - Analytics, + accounts, + analytics, authChallenge, createdAt, id, provider, role, - Settings, - Subscription, + settings, + subscriptions, thirdPartyId, updatedAt } = await this.prismaService.user.findUnique({ include: { - Access: true, - Account: { - include: { Platform: true } + accessesGet: true, + accounts: { + include: { platform: true } }, - Analytics: true, - Settings: true, - Subscription: true + analytics: true, + settings: true, + subscriptions: true }, where: userWhereUniqueInput }); const user: UserWithSettings = { - Access, + accessesGet, accessToken, - Account, + accounts, authChallenge, createdAt, id, provider, role, - Settings: Settings as UserWithSettings['Settings'], + settings: settings as UserWithSettings['settings'], thirdPartyId, updatedAt, - activityCount: Analytics?.activityCount, + activityCount: analytics?.activityCount, dataProviderGhostfolioDailyRequests: - Analytics?.dataProviderGhostfolioDailyRequests + analytics?.dataProviderGhostfolioDailyRequests }; - if (user?.Settings) { - if (!user.Settings.settings) { - user.Settings.settings = {}; + if (user?.settings) { + if (!user.settings.settings) { + user.settings.settings = {}; } } else if (user) { // Set default settings if needed - user.Settings = { + user.settings = { settings: {}, updatedAt: new Date(), userId: user?.id @@ -206,74 +237,144 @@ export class UserService { } // Set default value for base currency - if (!(user.Settings.settings as UserSettings)?.baseCurrency) { - (user.Settings.settings as UserSettings).baseCurrency = DEFAULT_CURRENCY; + if (!(user.settings.settings as UserSettings)?.baseCurrency) { + (user.settings.settings as UserSettings).baseCurrency = DEFAULT_CURRENCY; } // Set default value for date range - (user.Settings.settings as UserSettings).dateRange = - (user.Settings.settings as UserSettings).viewMode === 'ZEN' + (user.settings.settings as UserSettings).dateRange = + (user.settings.settings as UserSettings).viewMode === 'ZEN' ? 'max' - : ((user.Settings.settings as UserSettings)?.dateRange ?? 'max'); + : ((user.settings.settings as UserSettings)?.dateRange ?? 'max'); + + // Set default value for performance calculation type + if (!(user.settings.settings as UserSettings)?.performanceCalculationType) { + (user.settings.settings as UserSettings).performanceCalculationType = + PerformanceCalculationType.ROAI; + } // Set default value for view mode - if (!(user.Settings.settings as UserSettings).viewMode) { - (user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; + if (!(user.settings.settings as UserSettings).viewMode) { + (user.settings.settings as UserSettings).viewMode = 'DEFAULT'; } - (user.Settings.settings as UserSettings).xRayRules = { + (user.settings.settings as UserSettings).xRayRules = { AccountClusterRiskCurrentInvestment: - new AccountClusterRiskCurrentInvestment(undefined, {}).getSettings( - user.Settings.settings - ), + new AccountClusterRiskCurrentInvestment( + undefined, + undefined, + undefined, + {} + ).getSettings(user.settings.settings), AccountClusterRiskSingleAccount: new AccountClusterRiskSingleAccount( + undefined, + undefined, undefined, {} - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), AssetClassClusterRiskEquity: new AssetClassClusterRiskEquity( + undefined, + undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), AssetClassClusterRiskFixedIncome: new AssetClassClusterRiskFixedIncome( + undefined, + undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), CurrencyClusterRiskBaseCurrencyCurrentInvestment: new CurrencyClusterRiskBaseCurrencyCurrentInvestment( + undefined, + undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), CurrencyClusterRiskCurrentInvestment: new CurrencyClusterRiskCurrentInvestment( + undefined, + undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EconomicMarketClusterRiskDevelopedMarkets: new EconomicMarketClusterRiskDevelopedMarkets( + undefined, + undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EconomicMarketClusterRiskEmergingMarkets: new EconomicMarketClusterRiskEmergingMarkets( + undefined, + undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EmergencyFundSetup: new EmergencyFundSetup( + undefined, + undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), FeeRatioInitialInvestment: new FeeRatioInitialInvestment( + undefined, + undefined, + undefined, + undefined, + undefined + ).getSettings(user.settings.settings), + RegionalMarketClusterRiskAsiaPacific: + new RegionalMarketClusterRiskAsiaPacific( + undefined, + undefined, + undefined, + undefined, + undefined + ).getSettings(user.settings.settings), + RegionalMarketClusterRiskEmergingMarkets: + new RegionalMarketClusterRiskEmergingMarkets( + undefined, + undefined, + undefined, + undefined, + undefined + ).getSettings(user.settings.settings), + RegionalMarketClusterRiskEurope: new RegionalMarketClusterRiskEurope( + undefined, + undefined, + undefined, + undefined, + undefined + ).getSettings(user.settings.settings), + RegionalMarketClusterRiskJapan: new RegionalMarketClusterRiskJapan( + undefined, + undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings) + ).getSettings(user.settings.settings), + RegionalMarketClusterRiskNorthAmerica: + new RegionalMarketClusterRiskNorthAmerica( + undefined, + undefined, + undefined, + undefined, + undefined + ).getSettings(user.settings.settings) }; let currentPermissions = getPermissions(user.role); - if (!(user.Settings.settings as UserSettings).isExperimentalFeatures) { + if (user.provider === 'ANONYMOUS') { + currentPermissions.push(permissions.deleteOwnUser); + currentPermissions.push(permissions.updateOwnAccessToken); + } + + if (!(user.settings.settings as UserSettings).isExperimentalFeatures) { // currentPermissions = without( // currentPermissions, // permissions.xyz @@ -281,9 +382,9 @@ export class UserService { } if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - user.subscription = this.subscriptionService.getSubscription({ - createdAt: user.createdAt, - subscriptions: Subscription + user.subscription = await this.subscriptionService.getSubscription({ + subscriptions, + createdAt: user.createdAt }); if (user.subscription?.type === 'Basic') { @@ -291,44 +392,65 @@ export class UserService { new Date(), user.createdAt ); - let frequency = 10; + let frequency = 7; - if (daysSinceRegistration > 365) { + if (daysSinceRegistration > 720) { + frequency = 1; + } else if (daysSinceRegistration > 360) { frequency = 2; } else if (daysSinceRegistration > 180) { frequency = 3; } else if (daysSinceRegistration > 60) { frequency = 4; } else if (daysSinceRegistration > 30) { - frequency = 6; + frequency = 5; } else if (daysSinceRegistration > 15) { - frequency = 8; + frequency = 6; } - if (Analytics?.activityCount % frequency === 1) { + if (analytics?.activityCount % frequency === 1) { currentPermissions.push(permissions.enableSubscriptionInterstitial); } currentPermissions = without( currentPermissions, permissions.accessHoldingsChart, - permissions.createAccess + permissions.createAccess, + permissions.createMarketDataOfOwnAssetProfile, + permissions.createOwnTag, + permissions.createWatchlistItem, + permissions.readAiPrompt, + permissions.readMarketDataOfOwnAssetProfile, + permissions.updateMarketDataOfOwnAssetProfile ); // Reset benchmark - user.Settings.settings.benchmark = undefined; + user.settings.settings.benchmark = undefined; // Reset holdings view mode - user.Settings.settings.holdingsViewMode = undefined; + user.settings.settings.holdingsViewMode = undefined; } else if (user.subscription?.type === 'Premium') { - currentPermissions.push(permissions.createApiKey); - currentPermissions.push(permissions.enableDataProviderGhostfolio); - currentPermissions.push(permissions.reportDataGlitch); + if (!hasRole(user, Role.DEMO)) { + currentPermissions.push(permissions.createApiKey); + currentPermissions.push(permissions.enableDataProviderGhostfolio); + currentPermissions.push(permissions.readMarketDataOfMarkets); + currentPermissions.push(permissions.reportDataGlitch); + } currentPermissions = without( currentPermissions, permissions.deleteOwnUser ); + + // Reset offer + user.subscription.offer.coupon = undefined; + user.subscription.offer.couponId = undefined; + user.subscription.offer.durationExtension = undefined; + user.subscription.offer.label = undefined; + } + + if (hasRole(user, Role.ADMIN)) { + currentPermissions.push(permissions.syncDemoUserAccount); } } @@ -337,9 +459,9 @@ export class UserService { currentPermissions.push(permissions.toggleReadOnlyMode); } - const isReadOnlyMode = (await this.propertyService.getByKey( + const isReadOnlyMode = await this.propertyService.getByKey( PROPERTY_IS_READ_ONLY_MODE - )) as boolean; + ); if (isReadOnlyMode) { currentPermissions = currentPermissions.filter((permission) => { @@ -352,11 +474,11 @@ export class UserService { } } - if (!environment.production && role === 'ADMIN') { + if (!environment.production && hasRole(user, Role.ADMIN)) { currentPermissions.push(permissions.impersonateAllUsers); } - user.Account = sortBy(user.Account, ({ name }) => { + user.accounts = sortBy(user.accounts, ({ name }) => { return name.toLowerCase(); }); user.permissions = currentPermissions.sort(); @@ -390,10 +512,10 @@ export class UserService { data.provider = 'ANONYMOUS'; } - let user = await this.prismaService.user.create({ + const user = await this.prismaService.user.create({ data: { ...data, - Account: { + accounts: { create: { currency: DEFAULT_CURRENCY, name: this.i18nService.getTranslation({ @@ -402,7 +524,7 @@ export class UserService { }) } }, - Settings: { + settings: { create: { settings: { currency: DEFAULT_CURRENCY @@ -415,20 +537,17 @@ export class UserService { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { await this.prismaService.analytics.create({ data: { - User: { connect: { id: user.id } } + user: { connect: { id: user.id } } } }); } if (data.provider === 'ANONYMOUS') { - const accessToken = this.createAccessToken(user.id, getRandomString(10)); - - const hashedAccessToken = this.createAccessToken( - accessToken, - this.configurationService.get('ACCESS_TOKEN_SALT') - ); + const { accessToken, hashedAccessToken } = this.generateAccessToken({ + userId: user.id + }); - user = await this.prismaService.user.update({ + await this.prismaService.user.update({ data: { accessToken: hashedAccessToken }, where: { id: user.id } }); @@ -513,7 +632,7 @@ export class UserService { const { settings } = await this.prismaService.settings.upsert({ create: { settings: userSettings as unknown as Prisma.JsonObject, - User: { + user: { connect: { id: userId } diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index ac2157389..7144de8c5 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -1,6 +1,8 @@ { + "1": "just buy $1 worth of this coin", "3": "The Three Musketeers", "7": "Lucky7", + "32": "Project 32", "42": "42 Coin", "47": "President Trump", "300": "300 token", @@ -11,21 +13,25 @@ "611": "SixEleven", "777": "Jackpot", "808": "808", - "888": "Octocoin", + "888": "888", "1337": "EliteCoin", "1717": "1717 Masonic Commemorative Token", "2015": "2015 coin", "2024": "2024", + "2025": "2025 TOKEN", "2049": "TOKEN 2049", "2192": "LERNITAS", + "4444": "4444 Meme", + "50501": "50501movement", "$MAID": "MaidCoin", - "$ROPE": "Rope", "$TREAM": "World Stream Finance", "00": "ZER0ZER0", "007": "007 coin", "0DOG": "Bitcoin Dogs", "0KN": "0 Knowledge Network", + "0LNETWORK": "0L Network", "0NE": "Stone", + "0X0": "0x0.ai", "0X1": "0x1.tools: AI Multi-tool Plaform", "0XBTC": "0xBitcoin", "0XCOCO": "0xCoco", @@ -36,11 +42,12 @@ "0XOS": "0xOS AI", "0XSEARCH": "Search", "0XVOX": "HashVox AI", - "0x0": "0x0.ai", "0xDIARY": "The 0xDiary Token", "0xVPN": "0xVPN.org", "1-UP": "1-UP", "1000SATS": "SATS", + "1000X": "1000x by Virtuals", + "101M": "101M", "10SET": "Tenset", "1ART": "ArtWallet", "1CAT": "Bitcoin Cats", @@ -50,6 +57,8 @@ "1EX": "1ex Trading Board", "1FLR": "Flare Token", "1GOLD": "1irstGold", + "1GUY": "1GUY", + "1HUB": "1HubAI", "1INCH": "1inch", "1IRST": "1irstcoin", "1MCT": "MicroCreditToken", @@ -57,7 +66,10 @@ "1MIL": "1MillionNFTs", "1MT": "1Move", "1NFT": "1NFT", + "1ON8": "Little Dragon", + "1OZT": "Tala", "1PECO": "1peco", + "1R0R": "R0AR TOKEN", "1SG": "1SG", "1SOL": "1Sol", "1ST": "FirstBlood", @@ -65,6 +77,7 @@ "1UP": "Uptrennd", "1WO": "1World", "2022M": "2022MOON", + "20EX": "20ex", "21BTC": "21.co Wrapped BTC", "21X": "21X", "2BACCO": "2BACCO Coin", @@ -91,9 +104,11 @@ "3CRV": "LP 3pool Curve", "3D3D": "3d3d", "3DES": "3DES", + "3DVANCE": "3D Vance", "3FT": "ThreeFold Token", "3KM": "3 Kingdoms Multiverse", "3P": "Web3Camp", + "3RDEYE": "3rd Eye", "3ULL": "3ULL Coin", "3ULLV1": "Playa3ull Games v1", "3XD": "3DChain", @@ -104,10 +119,12 @@ "4CHAN": "4Chan", "4CZ": "FourCZ", "4DOGE": "4DOGE", + "4EVER": "4EVERLAND", "4JNET": "4JNET", "4MW": "For Meta World", "4P": "4P FOUR", "4RZ": "4REALZA COIN", + "4THPILLAR": "4th Pillar Four Token", "4TOKEN": "Ignore Fud", "4WIN": "4TRUMP", "4WMM": "4-Way Mirror Money", @@ -115,6 +132,7 @@ "50TRUMP": "50TRUMP", "50X": "50x.com", "5IRE": "5ire", + "69MINUTES": "69 Minutes", "77G": "GraphenTech", "7E": "7ELEVEN", "88MPH": "88mph", @@ -126,21 +144,27 @@ "9DOGS": "NINE DOGS", "9GAG": "9GAG", "9MM": "Shigure UI", - "A": "Alpha Token", + "A": "Vaulta", "A1INCH": "1inch (Arbitrum Bridge)", "A2A": "A2A", + "A2I": "Arcana AI", "A4": "A4 Finance", + "A47": "AGENDA 47", "A4M": "AlienForm", "A51": "A51 Finance", "A5T": "Alpha5", + "A7A5": "A7A5", "A8": "Ancient8", "AA": "Alva", "AAA": "Moon Rabbit", + "AAAHHM": "Plankton in Pain", + "AAAI": "AAAI_agent by Virtuals", "AAB": "AAX Token", "AABL": "Abble", "AAC": "Double-A Chain", "AAG": "AAG Ventures", "AAI": "AutoAir AI", + "AAPLX": "Apple xStock", "AAPX": "AMPnet", "AARDY": "Baby Aardvark", "AARK": "Aark", @@ -152,9 +176,11 @@ "AAVEGOTCHIFOMO": "Aavegotchi FOMO", "AAX": "Academic Labs", "AAZ": "ATLAZ", + "AB": "Newton", "AB1INCH": "1inch (Avalanche Bride)", "ABA": "EcoBall", "ABBC": "ABBC Coin", + "ABBVX": "AbbVie xStock", "ABC": "ABC Chain", "ABCC": "ABCC Token", "ABCD": "Crypto Inu", @@ -176,12 +202,16 @@ "ABOND": "ApeBond", "ABONDV1": "ApeSwap", "ABR": "Allbridge", + "ABSIMPSON": "abstract simpson", "ABT": "ArcBlock", + "ABTC": "aBTC", + "ABTX": "Abbott xStock", "ABUL": "Abulaba", "ABUNI": "Uniswap Protocol Token (Arbitrum Bridge)", "ABUSDC": "USD Coin (Arbitrum Bridge)", "ABX": "Arbidex", "ABY": "ArtByte", + "ABYS": "Trinity Of The Fabled", "ABYSS": "Abyss Finance", "AC": "Asia Coin", "AC3": "AC3", @@ -208,11 +238,14 @@ "ACL": "Auction Light", "ACM": "AC Milan Fan Token", "ACN": "AvonCoin", + "ACNX": "Accenture xStock", "ACOIN": "ACoin", - "ACP": "Anarchists Prime", + "ACOLYT": "Acolyte by Virtuals", + "ACP": "Arena Of Faith", "ACPT": "Crypto Accept", "ACQ": "Acquire.Fi", "ACRE": "Arable Protocol", + "ACRED": "Apollo Diversified Credit Securitize Fund", "ACRIA": "Acria.AI", "ACS": "Access Protocol", "ACSI": "ACryptoSI", @@ -228,7 +261,8 @@ "ADA": "Cardano", "ADAB": "Adab Solutions", "ADACASH": "ADACash", - "ADAI": "Aave DAI", + "ADAI": "Aave Interest bearing DAI", + "ADAIV1": "Aave DAI", "ADAM": "Adam Back", "ADANA": "Adanaspor Fan Token", "ADAO": "ADADao", @@ -259,6 +293,7 @@ "ADON": "Adonis", "ADP": "Adappter Token", "ADR": "Adroverse", + "ADRI": "AdRise", "ADRX": "Adrenaline Chain", "ADS": "Adshares", "ADT": "AdToken", @@ -272,6 +307,7 @@ "AEG": "Aether Games", "AEGGS": "aEGGS", "AEGIS": "Aegis", + "AEGS": "Aegisum", "AELIN": "Aelin", "AEN": "Aenco", "AENS": "AEN Smart", @@ -283,12 +319,16 @@ "AERO": "Aerodrome Finance", "AEROBUD": "Aerobud", "AEROCOIN": "Aero Coin", + "AEROME": "AeroMe", "AEROT": "AEROTYME", "AES": "Artis Aes Evolution", "AET": "AfterEther", "AETH": "Aave ETH", "AETHC": "Ankr Reward-Bearing Staked ETH", "AETHERV2": "AetherV2", + "AETHRA": "Aethra AI", + "AETHUSDT": "Aave Ethereum USDT", + "AETHWETH": "Aave Ethereum WETH", "AEUR": "Anchored Coins AEUR", "AEVO": "Aevo", "AEVUM": "Aevum", @@ -308,38 +348,49 @@ "AFRO": "Afrostar", "AFROX": "AfroDex", "AFSUI": "Aftermath Staked SUI", + "AFT": "AIFlow Token", "AFTT": "Africa Trading Chain", "AFX": "Afrix", "AFYON": "Afyonspor Fan Token", "AG": "AGAME", "AG8": "ATROMG8", - "AGA": "AGA Token", + "AGA": "Agora DEX Token", "AGATA": "Agatech", + "AGATOKEN": "AGA Token", "AGB": "Apes Go Bananas", "AGC": "Argocoin", + "AGEN": "Agent Krasnov", "AGENT": "AgentLayer", + "AGENTFUN": "AgentFun.AI", "AGET": "Agetron", "AGETH": "Kelp Gain", "AGEUR": "agEUR", "AGF": "Augmented Finance", "AGG": "AGG", "AGI": "Delysium", + "AGIALPHA": "AGI ALPHA AGENT", + "AGIFTTOKEN": "aGifttoken", "AGII": "AGII", "AGIL": "Agility LSD", "AGIV1": "SingularityNET v1", "AGIX": "SingularityNET", + "AGIXBT": "AGIXBT by Virtuals", + "AGIXT": "AGiXT", "AGLA": "Angola", "AGLD": "Adventure Gold", "AGM": "Argoneum", "AGN": "Agnus Ai", + "AGNT": "iAgent Protocol", "AGO": "AgoDefi", "AGON": "Arabian Dragon", + "AGORK": "@gork", "AGOV": "Answer Governance", "AGPC": "AGPC", + "AGRI": "AgriDex Token", "AGRO": "Bit Agro", "AGRS": "Agoras Token", "AGS": "Aegis", - "AGT": "aGifttoken", + "AGT": "AIVille Governance Token", "AGURI": "Aguri-Chan", "AGV": "Astra Guild Ventures", "AGVC": "AgaveCoin", @@ -348,8 +399,14 @@ "AHOO": "Ahoolee", "AHT": "AhaToken", "AI": "Sleepless", - "AI16Z": "ai16z", + "AI16Z": "ElizaOS", + "AI21X": "ai21x", + "AI23T": "23 Turtles", + "AI69SAKURA": "Sakura", "AIA": "AIA Chain", + "AIAF": "AI Agent Factory", + "AIAGENT": "AI Agents", + "AIAGENTAPP": "Aiagent.app", "AIAI": "All In AI", "AIAKITA": "AiAkita", "AIAT": "AI Analysis Token", @@ -359,12 +416,15 @@ "AIBCOIN": "AIBLOCK", "AIBK": "AIB Utility Token", "AIBU": "AIBUZZ TOKEN", - "AIC": "AI Crypto", + "AIC": "AI Companions", + "AICE": "Aicean", "AICELL": "AICell", "AICH": "AIChain", "AICO": "AICON", "AICODE": "AI CODE", "AICORE": "AICORE", + "AICRYPTO": "AI Crypto", + "AICRYPTOKEN": "AI Crypto Token", "AID": "AidCoin", "AIDA": "Ai-Da robot", "AIDI": "Aidi Inu", @@ -377,11 +437,14 @@ "AIDUS": "AIDUS Token", "AIE": "A.I.Earn", "AIEN": "AIENGLISH", + "AIEPK": "EpiK Protocol", "AIF": "AI FREEDOM TOKEN", "AIFLOKI": "AI Floki", "AIFUN": "AI Agent Layer", "AIG": "A.I Genesis", + "AIGA": "Aigang", "AIGPU": "AIGPU Token", + "AIH": "AIHub", "AII": "Artificial Idiot", "AIINU": "AI INU", "AIKEK": "AlphaKEK.AI", @@ -392,57 +455,81 @@ "AIMBOT": "AimBot AI", "AIMEE": "AIMEE", "AIMET": "AI Metaverse", + "AIMONICA": "Aimonica Brands", "AIMR": "MeromAI", "AIMS": "HighCastle Token", - "AIMX": "Aimedis", + "AIMX": "MindMatrix", + "AIMXV1": "Aimedis v1", + "AIMXV2": "Aimedis", "AIN": "AI Network", "AINA": "Ainastasia", "AINN": "AINN", + "AINTI": "AIntivirus", "AINU": "Ainu Token", "AION": "Aion", "AIONE": "AiONE", - "AIOT": "AIOT Token", + "AIOS": "INT OS", + "AIOSHI": "AiOShi Apple Companion", + "AIOT": "OKZOO", "AIOZ": "AIOZ Network", + "AIP": "AI Protocol", "AIPAD": "AIPAD", "AIPE": "AI Prediction Ecosystem", "AIPEPE": "AI PEPE KING", "AIPG": "AI Power Grid", "AIPIN": "AI PIN", "AIPO": "Aipocalypto", + "AIPUMP": "aiPump", "AIR": "Altair", "AIRB": "BillionAir", "AIRBTC": "AIRBTC", "AIRDROP": "AIRDROP2049", "AIRE": "Tokenaire", + "AIRENA": "AI AGENT ARENA", + "AIRENE": "AIRENE by Virtuals", + "AIREVOLUTION": "AI Revolution Coin", + "AIRFRY": "airfryer coin", "AIRI": "aiRight", "AIRIAN": "AIRian", "AIRT": "Aircraft", "AIRTNT": "Tenti", "AIRTOKEN": "AirToken", "AIRX": "Aircoins", - "AIS": "AISwap", + "AIS": "AISociety", "AISCII": "AISCII", "AISHIB": "ARBSHIB", "AIST": "Artificial intelligence staking token", + "AISW": "AISwap", "AIT": "AIT Protocol", "AITECH": "Artificial Intelligence Utility Token", "AITEK": "AI Technology", "AITHEON": "Aitheon", + "AITHER": "Aither Protocol", "AITIGER": "BNB Tiger AI", "AITK": "AITK", "AITN": "Artificial Intelligence Technology Network", "AITRA": "Aitra", + "AITRUMP": "AITRUMP", "AITT": "AITrading", "AIUS": "Arbius", + "AIV": "AIVeronica", + "AIVA": "AI Voice Agents", + "AIVIA": "AI Virtual Agents", "AIWALLET": "AiWallet Token", - "AIX": "Aigang", + "AIWS": "AIWS", + "AIX": "ALIENX", + "AIX9": "AthenaX9", "AIXBT": "aixbt by Virtuals", "AIXERC": "AI-X", + "AIXT": "AIXTerminal", "AJNA": "Ajna Protocol", "AJUN": "Ajuna Network", "AK12": "AK12", "AKA": "Akroma", + "AKAL": "AKA Liberty", + "AKASHA": "Akasha by Bloomverse", "AKI": "Aki Network", + "AKIO": "Akio", "AKIT": "Akita Inu", "AKITA": "Akita Inu", "AKITAI": "AKITA INU", @@ -454,6 +541,8 @@ "AKRO": "Akropolis", "AKT": "Akash Network", "AKTIO": "AKTIO Coin", + "AKUMA": "Akuma Inu", + "AKV": "Akiverse Governance", "AL": "ArchLoot", "ALA": "Alanyaspor Fan Token", "ALAN": "Alan the Alien", @@ -467,8 +556,10 @@ "ALC": "Arab League Coin", "ALCAZAR": "Alcazar", "ALCE": "Alcedo", - "ALCH": "Alchemy", + "ALCH": "Alchemist AI", "ALCHE": "Alchemist", + "ALCHEMYV1": "Alchemy v1", + "ALCHEMYV2": "Alchemy", "ALCX": "Alchemix", "ALD": "AladdinDAO", "ALDIN": "Alaaddin.ai", @@ -477,31 +568,38 @@ "ALEPH": "Aleph.im", "ALEX": "ALEX Lab", "ALEXANDRITE": "Alexandrite", + "ALEXIUS": "Alexius Maximus", "ALF": "AlphaCoin", "ALG": "Algory", "ALGB": "Algebra", + "ALGERIA": "Algeria", "ALGO": "Algorand", "ALGOBLK": "AlgoBlocks", "ALGOW": "Algowave", "ALH": "AlloHash", "ALI": "Alethea Artificial Liquid Intelligence Token", "ALIAS": "Alias", + "ALIBABAAI": "Alibaba AI Agent", "ALIC": "AliCoin", "ALICE": "My Neighbor Alice", "ALICEA": "Alice AI", + "ALICEW": "Alice Weidel", "ALIEN": "AlienCoin", "ALIENPEP": "Alien Pepe", + "ALIENS": "Aliens", "ALIF": " ALIF COIN", "ALINK": "Aave LINK v1", "ALIS": "ALISmedia", "ALIT": "Alitas", "ALITA": "Alita Network", + "ALITATOKEN": "Alita Token", "ALIX": "AlinX", "ALKI": "Alkimi", "ALLBI": "ALL BEST ICO", "ALLC": "All Crypto Mechanics", "ALLEY": "NFT Alley", "ALLIN": "All in", + "ALLMEE": "All.me", "ALM": "Alium Finance", "ALMAN": "Alman", "ALMC": "Awkward Look Monkey Club", @@ -509,6 +607,7 @@ "ALN": "Aluna", "ALNV1": "Aluna v1", "ALOHA": "Aloha", + "ALON": "Alon", "ALOT": "Dexalot", "ALP": "Alphacon", "ALPA": "Alpaca", @@ -522,6 +621,7 @@ "ALPHAF": "Alpha Fi", "ALPHAG": "Alpha Gardeners", "ALPHAPETTO": "Alpha Petto Shells", + "ALPHAPLATFORM": "Alpha Token", "ALPHAS": "Alpha Shards", "ALPHR": "Alphr", "ALPINE": "Alpine F1 Team Fan Token", @@ -544,7 +644,7 @@ "ALWAYS": "Always Evolving", "ALX": "ALAX", "ALY": "Ally", - "AM": "AeroMe", + "AM": "Aston Martin Cognizant", "AMA": "MrWeb", "AMADEUS": "AMADEUS", "AMAL": "AMAL", @@ -555,14 +655,18 @@ "AMBER": "AmberCoin", "AMBO": "Sheertopia", "AMBR": "Ambra", + "AMBRX": "Amber xStock", "AMBT": "AMBT Token", + "AMC": "AI Meta Coin", "AMDC": "Allmedi Coin", "AMDG": "AMDG", "AME": "Amepay", + "AMEP": "America Party", "AMER": "America", "AMERI": "AMERICAN EAGLE", "AMERIC": "American True Hero", "AMERICA": "America", + "AMERICAI": "AMERICA AI Agent", "AMERICANCOIN": "AmericanCoin", "AMF": "AddMeFast", "AMG": "DeHeroGame Amazing Token", @@ -577,10 +681,12 @@ "AMO": "AMO Coin", "AMOGUS": "Sussy Baka Impostor", "AMON": "AmonD", + "AMORE": "Amocucinare", "AMOS": "Amos", "AMP": "Amp", "AMPL": "Ampleforth", "AMPLIFI": "AmpliFi", + "AMR": "Amero", "AMS": "Amsterdam Coin", "AMT": "Acumen", "AMU": "Amulet", @@ -588,14 +694,17 @@ "AMX": "Amero", "AMY": "Amygws", "AMZE": "The Amaze World", + "AMZNX": "Amazon xStocks", "ANA": "Nirvana ANA", "ANAL": "AnalCoin", "ANALOS": "analoS", "ANALY": "Analysoor", + "ANARCHISTS": "Anarchists Prime", "ANAT": "Anatolia Token", "ANB": "Angryb", "ANC": "Anchor Protocol", "ANCHOR": "AnchorSwap", + "ANCIENTKING": "Ancient Kingdom", "ANCP": "Anacrypt", "ANCT": "Anchor", "AND": "AndromedaCoin", @@ -607,9 +716,11 @@ "ANDY": "ANDY", "ANDYB": "AndyBlast", "ANDYBNB": "Andy", - "ANDYBSC": "ANDY", + "ANDYBSC": "Andy BSC", + "ANDYBSCVIP": "ANDY", "ANDYMAN": "ANDYMAN", "ANDYSOL": "Andy on SOL", + "ANEX": "AstroNexus", "ANGEL": "Crypto Angel", "ANGL": "Angel Token", "ANGLE": "ANGLE", @@ -618,8 +729,10 @@ "ANI": "Anime Token", "ANIM": "Animalia", "ANIMA": "Realm Anima", - "ANIME": "Anime", + "ANIME": "Animecoin", "ANIMECOIN": "Animecoin", + "ANIMEONBASE": "Anime", + "ANITA": "Anita AI", "ANJ": "Aragon Court", "ANJI": "Anji", "ANK": "AlphaLink", @@ -630,12 +743,16 @@ "ANKRETH": "Ankr Staked ETH", "ANKRFTM": "Ankr Staked FTM", "ANKRMATIC": "Ankr Staked MATIC", + "ANLOG": "Analog", "ANML": "Animal Concerts", "ANN": "Annex Finance", - "ANON": "ANON", + "ANNE": "ANNE", + "ANON": "HeyAnon", "ANONCOIN": "Anoncoin", + "ANONCRYPTO": "ANON", "ANRX": "AnRKey X", - "ANS": "ANS Crypto Coin", + "ANS": "Apollo Name Service", + "ANSCRYPTO": "ANS Crypto Coin", "ANSOM": "Ansom", "ANSR": "Answerly", "ANT": "Aragon", @@ -644,6 +761,7 @@ "ANTEX": "Antex", "ANTI": "Anti Bitcoin", "ANTIS": "Antis Inu", + "ANTMONS": "Antmons", "ANTS": "ANTS Reloaded", "ANTT": "Antara Token", "ANUS": "URANUS", @@ -653,21 +771,24 @@ "ANY": "Anyswap", "ANYONE": "ANyONe Protocol", "ANZENUSD": "Anzen Finance", + "AO": "AO", "AOC": "Alickshundra Occasional-Cortex", "AOG": "AgeOfGods", "AOK": "AOK", "AOP": "Averopay", "AOS": "AOS", "AOT": "Age of Tanks", - "AP": "AppleSwap AI", + "AP": "America Party", + "AP3X": "Apex token", "APAD": "Anypad", "APC": "AlpaCoin", "APCG": "ALLPAYCOIN", "APD": "Aptopad", "APE": "ApeCoin", - "APED": "Baddest Alpha Ape Bundle", + "APED": "Aped", "APEDEV": "The dev is an Ape", "APEFUN": "Ape", + "APEMAN": "APEMAN", "APEPE": "Ape and Pepe", "APES": "APES", "APETARDIO": "Apetardio", @@ -696,12 +817,15 @@ "APPC": "AppCoins", "APPEALUSD": "Appeal dollar", "APPLE": "AppleSwap", + "APPLESWAPAI": "AppleSwap AI", + "APPX": "AppLovin xStock", "APRICOT": "Apricot Finance", "APRIL": "April", "APRS": "Aperios", "APS": "APRES", "APT": "Aptos", "APTCOIN": "Aptcoin", + "APTM": "Apertum", "APTOGE": "Aptoge", "APTR": "Aperture Finance", "APU": "Apu Apustaja", @@ -715,6 +839,8 @@ "APY": "APY.Finance", "APYS": "APYSwap", "APZ": "Alprockz", + "AQA": " AQA Token", + "AQDC": "AQDC", "AQT": "Alpha Quark Token", "AQTIS": "AQTIS", "AQU": "aQuest", @@ -727,31 +853,37 @@ "AQUARI": "Aquari", "AR": "Arweave", "ARA": "Ara Token", + "ARABCLUB": "The Arab Club Token", + "ARACOIN": "Ara", "ARATA": "Arata", "ARAW": "Araw", "ARB": "Arbitrum", - "ARBI": "Arbi", + "ARBI": "Arbipad", "ARBIT": "Arbit Coin", "ARBP": "ARB Protocol", "ARBS": "Arbswap", "ARBT": "ARBITRAGE", "ARBUZ": "ARBUZ", - "ARC": "Neko Arc", + "ARC": "AI Rig Complex", "ARCA": "Legend of Arcadia", "ARCAD": "Arcadeum", "ARCADE": "ARCADE", "ARCADECITY": "Arcade City", "ARCADEF": "arcadefi", "ARCADEN": "ArcadeNetwork", + "ARCAI": "ARCAI", "ARCANE": "Arcane Token", "ARCAS": "Arcas", "ARCH": "Archway", "ARCHA": "ArchAngel Token", + "ARCHAI": "ArchAI", "ARCHCOIN": "ArchCoin", "ARCHE": "Archean", "ARCHIVE": "Chainback", + "ARCINTEL": "Arc", "ARCO": "AquariusCoin", "ARCONA": "Arcona", + "ARCOS": "ArcadiaOS", "ARCT": "ArbitrageCT", "ARCTICCOIN": "ArcticCoin", "ARCX": "ARC Governance", @@ -797,15 +929,19 @@ "ARO": "Arionum", "ARON": "Astronaut Aron", "AROR": "Arora", + "AROS": "Aros", "ARPA": "ARPA Chain", "ARPAC": "ArpaCoin", "ARQ": "ArQmA", + "ARQX": "ARQx AI", "ARR": "ARROUND", + "ARRI": "Arris", "ARRO": "Arro Social", + "ARROW": "Arrow Token", "ARRR": "Pirate Chain", "ARSL": "Aquarius Loan", "ARSW": "ArthSwap", - "ART": "Maecenas", + "ART": "Genify ART", "ARTC": "Artcoin", "ARTDECO": "ARTDECO", "ARTDRAW": "ArtDraw", @@ -818,6 +954,7 @@ "ARTFI": "ARTFI", "ARTG": "Goya Giant Token", "ARTH": "ARTH", + "ARTHERA": "Arthera", "ARTI": "Arti Project", "ARTIF": "Artificial Intelligence", "ARTII": "ARTII Token", @@ -837,21 +974,27 @@ "ASAFE2": "Allsafe", "ASAN": "ASAN VERSE", "ASAP": "Asap Sniper Bot", + "ASBNB": "Astherus Staked BNB", "ASC": "Ascend", "ASD": "AscendEX Token", "ASDEX": "AstraDEX", "ASEED": "aUSD SEED (Acala)", + "ASETQU": "AsetQu", + "ASF": "Asymmetry Finance Token", "ASG": "Asgard", "ASGC": "ASG", "ASH": "ASH", "ASHS": "AshSwap", - "ASI": "Artificial Superintelligence Alliance", + "ASI": "Sender AI Token", "ASIA": "Asia Coin", "ASIMI": "ASIMI", "ASIX": "ASIX+", + "ASIXDEV": "ASIX", "ASK": "Permission Coin", + "ASKAI": "ASKAI", "ASKO": "Asko", "ASM": "Assemble Protocol", + "ASMAT": "AsMatch", "ASMO": "AS Monaco Fan Token", "ASN": "Ascension Coin", "ASNT": "Assent Protocol", @@ -861,6 +1004,7 @@ "ASPO": "ASPO Shards", "ASQT": "ASQ Protocol", "ASR": "AS Roma Fan Token", + "ASRR": "Assisterr AI", "ASS": "Australian Safe Shepherd", "ASSA": "AssaPlay", "ASSARA": "ASSARA", @@ -870,12 +1014,14 @@ "ASTA": "ASTA", "ASTO": "Altered State Token", "ASTON": "Aston", + "ASTONV": "Aston Villa Fan Token", "ASTR": "Astar", "ASTRA": "Astra Protocol", "ASTRADAO": "Astra DAO", "ASTRAFER": "Astrafer", "ASTRAFERV1": "Astrafer v1", "ASTRAL": "Astral", + "ASTRALAB": "Astra Labs", "ASTRO": "Astroport", "ASTROC": "Astroport Classic", "ASTROLION": "AstroLion", @@ -885,6 +1031,7 @@ "ASTROS": "AstroSwap", "ASTX": "Asterix Labs", "ASUNA": "Asuna Hentai", + "ASUSDF": "Astherus Staked USDF", "ASUSHI": "Sushi (Arbitrum Bridge)", "ASVA": "Asva", "ASW": "AdaSwap", @@ -897,6 +1044,7 @@ "ATD": "A2DAO", "ATEC": "AnonTech", "ATECH": "AvaxTech", + "ATEHUN": "ATEHUN", "ATEM": "Atem Network", "ATF": "Alion Tech Food", "ATFI": "Atlantic Finance Token", @@ -906,6 +1054,7 @@ "ATHE": "Atheios", "ATHEN": "Athenas AI", "ATHENA": "Athena DexFi", + "ATHER": "Ather", "ATHVODKA": "All Time High Vodka", "ATID": "AstridDAO Token", "ATK": "Attack Wagon", @@ -913,15 +1062,18 @@ "ATL": "ATLANT", "ATLA": "Atleta Network", "ATLAS": "Star Atlas", + "ATLASD": "Atlas DEX", "ATLX": "Atlantis Loans Polygon", "ATM": "Atletico de Madrid Fan Token", "ATMA": "ATMA", + "ATMBSC": "ATM", "ATMC": "Autumncoin", "ATMCHAIN": "ATMChain", "ATMCOIN": "ATM", "ATMI": "Atonomi", "ATMOS": "Novusphere", - "ATN": "ATN", + "ATN": "ATHENE NETWORK", + "ATNIO": "ATN", "ATNT": "Artizen", "ATO": "Atocha Protocol", "ATOLO": "RIZON", @@ -932,12 +1084,13 @@ "ATOZ": "Race Kingdom", "ATP": "Atlas Protocol", "ATPAY": "AtPay", - "ATR": "Ather", + "ATR": "Artrade", "ATRI": "Atari Token", "ATRNO": "AETERNUS", "ATROFA": "Atrofarm", "ATRS": "Attarius Network", - "ATS": "Atlas DEX", + "ATRV1": "Artrade v1", + "ATS": "Alltoscan", "ATT": "Attila", "ATTR": "Attrace", "ATX": "ArtexCoin", @@ -957,9 +1110,10 @@ "AUNIT": "Aunit", "AUPC": "Authpaper", "AUR": "AUREO", - "AURA": "Aura Network", + "AURA": "aura", "AURABAL": "Aura BAL", "AURAF": "Aura Finance", + "AURANET": "Aura Network", "AURO": "Aurora", "AURORA": "Aurora", "AURORAC": "Auroracoin", @@ -973,13 +1127,18 @@ "AUSDT": "aUSDT", "AUT": "Autoria", "AUTHORSHIP": "Authorship", - "AUTISM": "AUTISM", + "AUTISM": "autism", + "AUTISMTOKEN": "AUTISM", "AUTO": "Auto", + "AUTOMATIC": "Automatic Treasury Machine", + "AUTONO": "Autonomi", + "AUTOS": "CryptoAutos", "AUTUMN": "Autumn", "AUVERSE": "AuroraVerse", "AUX": "Auxilium", "AV": "Avatar Coin", "AVA": "Travala", + "AVAAI": "Ava AI", "AVACN": "AVACOIN", "AVAI": "Orca AVAI", "AVAIL": "Avail", @@ -991,40 +1150,49 @@ "AVATAR": "Avatar", "AVATLY": "Avatly", "AVAV": "AVAV", + "AVAV1": "AVA v1", "AVAX": "Avalanche", + "AVAXAI": "AIvalanche DeFAI Agents", "AVAXIOU": "Avalanche IOU", "AVB": "Autonomous Virtual Beings", + "AVC": "AVC", "AVDO": "AvocadoCoin", "AVE": "Avesta", "AVEN": "Aventis AI", "AVENT": "Aventa", + "AVERY": "Avery Games", "AVG": "Avocado DAO", + "AVGOX": "Broadcom xStock", "AVH": "Animation Vision Cash", "AVI": "Aviator", "AVINOC": "AVINOC", "AVIVE": "Avive World", - "AVL": "Aston Villa Fan Token", + "AVL": "AVL", "AVM": "AVM (Atomicals)", "AVME": "AVME", "AVN": "AVNRich", "AVO": "Avoteo", "AVR": "Avrora Metaverse", + "AVRK": "Avarik Saga", "AVS": "Aves", "AVT": "Aventus", "AVTM": "Aventis Metaverse", "AVXL": "Avaxlauncher", "AVXT": "Avaxtars Token", + "AWARDCOIN": "Award", + "AWARE": "ChainAware.ai", "AWAX": "AWAX", "AWC": "Atomic Wallet Coin", + "AWE": "AWE Network", "AWK": "Awkward Monkey Base", "AWM": "Another World", "AWNEX": "AWNEX token", "AWO": "AiWork", "AWORK": "Aworker", "AWP": "Ansem Wif Photographer", - "AWR": "Award", - "AWS": "AurusSILVER", - "AWT": "Airdrop World", + "AWR": "All Will Retire", + "AWS": "Agentwood Studios", + "AWT": "Abyss World", "AWX": "AurusX", "AX": "AlphaX", "AXC": "AXIA Coin", @@ -1057,8 +1225,10 @@ "AZA": "Kaliza", "AZART": "Azart", "AZBI": "AZBI CORE", + "AZER": "Azerop", "AZERO": "Aleph Zero", "AZIT": "Azit", + "AZNX": "AstraZeneca xStock", "AZR": "Azure", "AZU": "Azultec", "AZUKI": "Azuki", @@ -1067,16 +1237,19 @@ "AZUR": "Azuro Protocol", "AZURE": "Azure Wallet", "AZY": "Amazy", - "B": "BankCoin", + "B": "BUILDon", "B01": "b0rder1ess", "B1P": "B ONE PAYMENT", + "B2": "B² Network", "B20": "B20", "B21": "B21", "B26": "B26 Finance", "B2G": "Bitcoiin2Gen", "B2M": "Bit2Me", "B2X": "SegWit2x", - "B3": "B3 Coin", + "B3": "B3", + "B3COIN": "B3 Coin", + "B3TR": "VeBetterDAO", "B3X": "Bnext Token", "B91": "B91", "BA": "BAHA", @@ -1084,19 +1257,23 @@ "BAB": "Babacoin", "BABI": "Babylons", "BABL": "Babylon Finance", - "BABY": "BabySwap", + "BABY": "Babylon", "BABYANDY": "Baby Andy", "BABYB": "Baby Bali", "BABYBI": "Baby Bitcoin", "BABYBINANCE": "BABYBINANCE", "BABYBITC": "BabyBitcoin", "BABYBNB": "BabyBNB", + "BABYBNBBABY": "BabyBNB", "BABYBNBTIGER": "BabyBNBTiger", "BABYBO": "BabyBonk", "BABYBOB": "Baby Bob", "BABYBOME": "Book of Baby Memes", "BABYBOMEOW": "Baby of BOMEOW", "BABYBONK": "Baby Bonk", + "BABYBROC": "Baby Broccoli", + "BABYBROCCOL": "Baby Broccoli", + "BABYBROCCOLI": "BabyBroccoli", "BABYBTC": "BABYBTC", "BABYC": "Baby Cat", "BABYCAT": "Baby Cat Coin", @@ -1110,6 +1287,7 @@ "BABYD": "Baby Dragon", "BABYDENG": "Baby Moo Deng", "BABYDOGE": "BabyDoge", + "BABYDOGE2": "Baby Doge 2.0", "BABYDOGEINU": "BABY DOGE INU", "BABYDOGEZILLA": "BabyDogeZilla", "BABYDRAGON": "Baby Dragon", @@ -1130,21 +1308,28 @@ "BABYJERRY": "Baby Jerry", "BABYJESUS": "BabyJesusCoin", "BABYKABOSU": "Baby Kabosu", + "BABYKEKIUS": "Baby Kekius Maximus", "BABYKITTY": "BabyKitty", + "BABYKOMA": "Baby Koma", + "BABYLABUBU": "BABY LABUBU", "BABYLONG": "Baby Long", "BABYM": "BabyMAGA", "BABYMAGA": "Baby Maga", + "BABYMANYU": "Baby Manyu", "BABYME": "Baby Meme Coin", "BABYMEME": "Baby Memecoin", "BABYMIGGLES": "Baby Miggles", "BABYMO": "Baby Moon Floki", "BABYMU": "Baby Musk", + "BABYMUB": "Baby Mubarak", "BABYMUSK": "Baby Musk", "BABYMYRO": "Babymyro", "BABYNEIRO": "Baby Neiro", + "BABYNEIROB": "Baby Neiro", "BABYOKX": "BABYOKX", "BABYP": "BabyPepe", "BABYPEIPEI": "Baby PeiPei", + "BABYPENGU": "BABY PENGU", "BABYPEPE": "Babypepe (BSC)", "BABYPNUT": "Baby Pnut", "BABYPOPCAT": "Baby PopCat", @@ -1153,14 +1338,17 @@ "BABYRWA": "BabyRWA", "BABYS": "Baby Slerf", "BABYSAITAMA": "Baby Saitama", - "BABYSHARK": "Baby Shark", + "BABYSHARK": "Baby Shark Meme", + "BABYSHARKBSC": "Baby Shark", "BABYSHIB": "Baby Shiba Inu", "BABYSHIBAINU": "Baby Shiba Inu", "BABYSHIRO": "Baby Shiro Neko", "BABYSHIV": "Baby Shiva", "BABYSLERF": "BabySlerf", + "BABYSNAKE": "Baby Snake BSC", "BABYSOL": "Baby Solana", "BABYSORA": "Baby Sora", + "BABYSWAP": "BabySwap", "BABYSWEEP": "BabySweep", "BABYT": "BABYTRUMP", "BABYTK": "Baby Tiger King", @@ -1176,15 +1364,20 @@ "BACK": "DollarBack", "BACOIN": "BACoin", "BACON": "BaconDAO (BACON)", + "BACX": "Bank of America xStock", "BAD": "Bad Idea AI", "BADA": "Bad Alien Division", + "BADAI": "BAD Coin", "BADC": "BADCAT", "BADCAT": "Andy’s Alter Ego", + "BADDEST": "Baddest Alpha Ape Bundle", "BADGER": "Badger DAO", + "BADM": "Badmad Robots", "BAFC": "BabyApeFunClub", "BAG": "Bag", "BAGS": "Basis Gold Share", "BAHAMAS": "Bahamas", + "BAHIA": "Esporte Clube Bahia Fan Token", "BAI": "BearAI", "BAICA": "Baica", "BAJU": "Bajun Network", @@ -1194,39 +1387,50 @@ "BAKED": "Baked", "BAKEDB": "Baked Beans Token", "BAKEDTOKEN": "Baked", + "BAKENEKO": "BAKENEKO", "BAKSO": "Disney Sumatran Tiger", "BAKT": "Backed Protocol", "BAL": "Balancer", "BALA": "Shambala", + "BALANCE": "Balance AI", "BALD": "Bald", "BALIN": "Balin Bank", - "BALL": "Game 5 BALL", + "BALKANCOIN": "Balkancoin", + "BALL": "BitBall", "BALLZ": "Wolf Wif", "BALN": "Balanced", "BALPHA": "bAlpha", "BALT": "Brett's cat", "BALTO": "Balto Token", + "BALVI": "Balvi", "BAMA": "BabyAMA", "BAMBIT": "BAMBIT", "BAMBOO": "BambooDeFi", + "BAMF": "BAMF", "BAMITCOIN": "Bamit", - "BAN": "Banano", + "BAN": "Comedian", "BANANA": "Banana Gun", + "BANANACHARITY": "BANANA", "BANANAF": "Banana For Scale", "BANANAS": "Monkey Peepo", + "BANANAS31": "Banana For Scale", + "BANANO": "Banano", "BANC": "Babes and Nerds", "BANCA": "BANCA", "BAND": "Band Protocol", "BANDEX": "Banana Index", "BANDIT": "Bandit on Base", + "BANDO": "Bandot", "BANG": "BANG", "BANGY": "BANGY", "BANK": "Float Protocol", "BANKA": "Bank AI", + "BANKBRC": "BANK Ordinals", "BANKC": "Bankcoin", "BANKER": "BankerCoinAda", "BANKETH": "BankEth", "BANKSY": "BANKSY", + "BANNED": "BANNED", "BANNER": "BannerCoin", "BANUS": "Banus.Finance", "BANX": "Banx.gg", @@ -1237,6 +1441,7 @@ "BAOS": "BaoBaoSol", "BAR": "FC Barcelona Fan Token", "BARA": "Capybara", + "BARAKATUH": "Barakatuh", "BARC": "The Blu Arctic Water Company", "BAREBEARS": "BAREBEARS", "BARIO": "Bario", @@ -1249,10 +1454,12 @@ "BARY": "Bary", "BAS": "Basis Share", "BASEAI": "BaseAI", + "BASEBEAR": "BBQ", "BASECAT": "BASE CAT", "BASECOIN": "BASECOIN", "BASED": "Based Money", "BASEDAI": "BasedAI", + "BASEDALF": "Based Alf", "BASEDCHILL": "Based Chill Guy", "BASEDCOPE": "COPE", "BASEDFINANCE": "Based", @@ -1260,6 +1467,7 @@ "BASEDP": "Based Pepe", "BASEDR": "Based Rabbit", "BASEDS": "BasedSwap", + "BASEDTURBO": "Based Turbo", "BASEDV1": "Based Money v1", "BASEHEROES": "Baseheroes", "BASEPROTOCOL": "Base Protocol", @@ -1271,11 +1479,13 @@ "BASHOS": "Bashoswap", "BASIC": "BASIC", "BASID": "Basid Coin", + "BASIL": "Basilisk", "BASIS": "Basis", "BASK": "BasketDAO", "BAST": "Bast", "BASTET": "Bastet Goddess", "BAT": "Basic Attention Token", + "BATCH": "BATCH Token", "BATH": "Battle Hero", "BATMAN": "BATMAN", "BATO": "Batonex Token", @@ -1283,6 +1493,7 @@ "BAVA": "Baklava", "BAX": "BABB", "BAXS": "BoxAxis", + "BAXV1": "BABB v1", "BAY": "BitBay", "BAYSE": "coynbayse", "BAZED": "Bazed Games", @@ -1291,12 +1502,14 @@ "BBADGER": "Badger Sett Badger", "BBANK": "BlockBank", "BBB": "BitBullBot", + "BBBTC": "Big Back Bitcoin", "BBC": "Bull BTC Club", "BBCC": "BaseballCardCoin", "BBCG": "BBC Gold Coin", "BBCH": "Binance Wrapped BCH", "BBCT": "TraDove B2BCoin", "BBDC": "Block Beats Network", + "BBDOGITO": "BabyBullDogito", "BBDT": "BBD Token", "BBEER": "BABY BEERCOIN", "BBF": "Bubblefong", @@ -1308,19 +1521,23 @@ "BBL": "beoble", "BBN": "BBNCOIN", "BBO": "Bigbom", + "BBOB": "BabyBuilder", "BBONK": "BitBonk", "BBOS": "Blackbox Foundation", "BBP": "BiblePay", + "BBQ": "BBQ COIN", "BBR": "Boolberry", "BBRETT": "Baby Brett", + "BBROCCOLI": "Baby Broccoli", "BBS": "BBSCoin", "BBSOL": "Bybit Staked SOL", - "BBT": "BitBook", + "BBT": "BabyBoomToken", "BBTC": "Binance Wrapped BTC", "BBTF": "Block Buster Tech Inc", "BBUSD": "BounceBit USD", "BBYDEV": "The Dev is a Baby", - "BC": "Bitcoin Confidential", + "BC": "Blood Crystal", + "BC3M": "Backed GOVIES 0-6 Months Euro Investment Grade", "BCA": "Bitcoin Atom", "BCAC": "Business Credit Alliance Chain", "BCAI": "Bright Crypto Ai", @@ -1355,12 +1572,17 @@ "BCO": "BridgeCoin", "BCOIN": "Bombcrypto", "BCOINM": "Bomb Crypto (MATIC)", + "BCOINSOL": "Bomb Crypto (SOL)", + "BCOINTON": "Bomb Crypto (TON)", "BCOQ": "BLACK COQINU", - "BCP": "BitcashPay", + "BCP": "BlockChainPeople", + "BCPAY": "Bitcashpay", "BCPT": "BlockMason Credit Protocol", + "BCPV1": "BitcashPay", "BCR": "BitCredit", "BCRO": "Bonded Cronos", "BCS": "Business Credit Substitute", + "BCSPX": "Backed CSPX Core S&P 500", "BCT": "Toucan Protocol: Base Carbon Tonne", "BCUBE": "B-cube.ai", "BCUG": "Blockchain Cuties Universe Governance", @@ -1375,19 +1597,25 @@ "BDAY": "Birthday Cake", "BDB": "Big Data Block", "BDC": "BILLION•DOLLAR•CAT", + "BDCA": "BitDCA", "BDCC": "BDCC COIN", "BDCLBSC": "BorderCollieBSC", - "BDG": "BitDegree", + "BDG": "Beyond Gaming", "BDID": "BDID", + "BDIN": "BendDAO BDIN", "BDL": "Bitdeal", "BDOG": "Bulldog Token", + "BDOGITO": "BullDogito", "BDOT": "Binance Wrapped DOT", "BDP": "Big Data Protocol", "BDPI": "Interest Bearing Defi Pulse Index", "BDR": "BlueDragon", "BDRM": "Bodrumspor Fan Token", "BDROP": "BlockDrop", + "BDSM": "BTC DOGE SOL MOON", + "BDTC": "BDTCOIN", "BDX": "Beldex", + "BDXN": "Bondex Token", "BDY": "Buddy DAO", "BEA": "Beagle Inu", "BEACH": "BeachCoin", @@ -1395,24 +1623,36 @@ "BEAM": "Beam", "BEAMMW": "Beam", "BEAN": "Bean", - "BEANS": "Moonbeans", + "BEANS": "SUNBEANS (BEANS)", + "BEAR": "Bear Inu", + "BEARIN": "Bear in Bathrobe", "BEAST": "MrBeast", "BEAT": "BEAT Token", + "BEATAI": "eBeat AI", "BEATLES": "JohnLennonC0IN", "BEATS": "Sol Beats", + "BEAVER": "beaver", "BEBE": "BEBE", + "BEBEETH": "BEBE", + "BEBEV1": "BEBE v1", "BEC": "Betherchip", "BECH": "Beauty Chain", + "BECKOS": "Beckos", "BECN": "Beacon", "BECO": "BecoSwap Token", "BECX": "BETHEL", "BED": "Bankless BED Index", + "BEDROCK": "Bedrock", "BEE": "Herbee", "BEEF": "PepeBull", "BEEG": "Beeg Blue Whale", + "BEENZ": "BEENZ", "BEEP": "BEEP", + "BEEPBOOP": "Boop", "BEER": "BEERCOIN", + "BEER2": "Beercoin 2", "BEERUSCAT": "BeerusCat", + "BEES": "BEEs", "BEET": "BEETroot", "BEETLE": "Beetle Coin", "BEETOKEN": "Bee Token", @@ -1454,7 +1694,11 @@ "BEPE": "Blast Pepe", "BEPR": "Blockchain Euro Project", "BEPRO": "BEPRO Network", + "BERA": "Berachain", + "BERAETH": "Berachain Staked ETH", + "BERASTONE": "StakeStone Berachain Vault Token", "BERF": "BERF", + "BERG": "Bloxberg", "BERN": "BERNcash", "BERNIE": "BERNIE SENDERS", "BERRY": "Berry", @@ -1500,17 +1744,25 @@ "BFT": "BF Token", "BFTB": "Brazil Fan Token", "BFTC": "BITS FACTOR", + "BFTOKEN": "BOSS FIGHTERS", + "BFWOG": "Based Fwog (basedfwog.info)", "BFX": "BitFinex Tokens", "BG": "BunnyPark Game", "BGB": "Bitget token", "BGBP": "Binance GBP Stable Coin", "BGBV1": "Bitget Token v1", "BGC": "Bee Token", + "BGCI": "Bloomberg Galaxy Crypto Index", + "BGEO": "BGEO", "BGG": "BGG Token", "BGLD": "Based Gold", + "BGME": "Backed GameStop", "BGONE": "BigONE Token", + "BGOOGL": "Backed Alphabet Class A", "BGPT": "BlockGPT", + "BGR": "Bitgrit", "BGS": "Battle of Guardians Share", + "BGSC": "BugsCoin", "BGSOL": "Bitget SOL Staking", "BGUY": "The Big Guy", "BGVT": "Bit Game Verse Token", @@ -1518,25 +1770,31 @@ "BHAT": "BH Network", "BHAX": "Bithashex", "BHBD": "bHBD", - "BHC": "BillionHappiness", + "BHC": "Billion Happiness", + "BHCV1": "Billion Happiness v1", "BHEROES": "BombHeroes coin", "BHIG": "BuckHathCoin", + "BHIGH": "Backed HIGH € High Yield Corp Bond", "BHIRE": "BitHIRE", "BHIVE": "Hive", "BHO": "Bholdus Token", "BHP": "Blockchain of Hash Power", "BHPC": "BHPCash", - "BIAO": "Biaocoin", + "BIAO": "BIAO", + "BIAOCOIN": "Biaocoin", "BIB": "BIB Token", + "BIB01": "Backed IB01 $ Treasury Bond 0-1yr", "BIBI": "BIBI", + "BIBI2025": "Bibi", "BIBL": "Biblecoin", "BIBO": "Bible of Memes", + "BIBTA": "Backed IBTA $ Treasury Bond 1-3yr", "BIC": "Bikercoins", "BICHO": "bicho", "BICITY": "BiCity AI Projects", "BICO": "Biconomy", "BICS": "Biceps", - "BID": "TopBidder", + "BID": "CreatorBid", "BIDAO": "Bidao", "BIDCOM": "Bidcommerce", "BIDEN": "Dark Brandon", @@ -1548,19 +1806,27 @@ "BIDZV1": "BIDZ Coin v1", "BIFI": "Beefy.Finance", "BIFIF": "BiFi", + "BIFIV1": "Beefy v1", "BIG": "Big Eyes", + "BIGBALLS": "Edward Coristine", "BIGBANGCORE": "BigBang Core", "BIGCOIN": "BigCoin", + "BIGDOG": "Big Dog", + "BIGFACTS": "BIGFACTS", "BIGFOOT": "BigFoot Town", + "BIGGIE": "Biggie", "BIGHAN": "BighanCoin", + "BIGJIM": "BIG JIM", "BIGLEZ": "THE BIG LEZ SHOW", "BIGMIKE": "Big Mike", + "BIGPUMP": "Big Pump", "BIGSB": "BigShortBets", "BIGTIME": "Big Time", "BIGUP": "BigUp", "BIH": "BitHostCoin", "BIHU": "Key", "BIIS": "biis (Ordinals)", + "BIKE": "White Bike", "BIKI": "BIKI", "BILL": "TillBilly", "BILLI": "Billi", @@ -1568,8 +1834,11 @@ "BILLY": "Billy ", "BILLYBSC": "BILLY", "BIM": "BitminerCoin", + "BINA": "Binance Mascort Dog", + "BINAN": "Binance Mascot", "BINANCED": "BinanceDog On Sol", "BINANCEDOG": "Binancedog", + "BINANCIENS": "Binanciens", "BIND": "Compendia", "BINEM": "Binemon", "BINGO": "Tomorrowland", @@ -1578,7 +1847,7 @@ "BINS": "Bitsense", "BINTEX": "Bintex Futures", "BINU": "Blast Inu", - "BIO": "BITONE", + "BIO": "Bio Protocol", "BIOB": "BioBar", "BIOC": "BioCrypt", "BIOCOIN": "Biocoin", @@ -1591,9 +1860,12 @@ "BIPX": "Bispex", "BIR": "Birake", "BIRB": "Birb", - "BIRD": "Bird.Money", + "BIRD": "BIRD", "BIRDCHAIN": "Birdchain", + "BIRDD": "BIRD DOG", "BIRDDOG": "Bird Dog", + "BIRDEI": "Birdei", + "BIRDMONEY": "Bird.Money", "BIRDO": "Bird Dog", "BIS": "Bismuth", "BISKIT": "Biskit Protocol", @@ -1605,22 +1877,29 @@ "BITASEAN": "BitAsean", "BITB": "BeanCash", "BITBEDR": "Bitcoin EDenRich", + "BITBO": "BitBook", + "BITBOARD": "Bitboard", "BITBOOST": "BitBoost", "BITBULL": "Bitbull", "BITBURN": "Bitburn", "BITC": "BitCash", "BITCAR": "BitCar", "BITCAT": "Bitcat", + "BITCATONSOL": "Bitcat", "BITCCA": "Bitcci Cash", "BITCI": "Bitcicoin", "BITCM": "Bitcomo", "BITCNY": "bitCNY", "BITCO": "Bitcoin Black Credit Card", "BITCOINC": "Bitcoin Classic", + "BITCOINCONFI": "Bitcoin Confidential", + "BITCOINOTE": "BitcoiNote", "BITCOINP": "Bitcoin Private", "BITCOINV": "BitcoinV", "BITCONNECT": "BitConnect Coin", + "BITCORE": "BitCore", "BITCRATIC": "Bitcratic Token", + "BITDEGREE": "BitDegree", "BITE": "Bitether", "BITF": "Bit Financial", "BITFLIP": "BitFlip", @@ -1633,6 +1912,7 @@ "BITNEW": "BitNewChain", "BITO": "BitoPro Exchange Token", "BITOK": "BitOKX", + "BITONE": "BITONE", "BITORB": "BitOrbit", "BITRA": "Bitratoken", "BITRADIO": "Bitradio", @@ -1641,6 +1921,7 @@ "BITRUE": "Bitrue Coin", "BITS": "BitstarCoin", "BITSD": "Bits Digit", + "BITSEEDS": "BitSeeds", "BITSERIAL": "BitSerial", "BITSILVER": "bitSilver", "BITSPACE": "Bitspace", @@ -1648,24 +1929,29 @@ "BITT": "BiTToken", "BITTO": "BITTO", "BITTON": "Bitton", - "BITUNE": "Bitune", + "BITTY": "The Bitcoin Mascot", + "BITUPTOKEN": "BitUP Token", "BITUSD": "bitUSD", "BITV": "Bitvolt", "BITVOLT": "BitVolt", "BITWORLD": "Bit World Token", "BITX": "BitScreener", - "BITZ": "Bitz Coin", + "BITXOXO": "Bitxoxo", + "BITZ": "MARBITZ", + "BITZBIZ": "Bitz Coin", "BIUT": "Bit Trust System", "BIVE": "BIZVERSE", "BIX": "BiboxCoin", "BIXB": "BIXBCOIN", "BIXI": "Bixi", + "BIXV1": "BiboxCoin v1", "BIZA": "BizAuto", "BIZZ": "BIZZCOIN", "BJ": "Blocjerk", + "BJC": "Bjustcoin", "BJK": "Beşiktaş", "BKBT": "BeeKan", - "BKC": "Balkancoin", + "BKC": "BKC Token", "BKING": "King Arthur", "BKK": "BKEX Token", "BKN": "Brickken", @@ -1682,12 +1968,14 @@ "BLACK": "BLACKHOLE PROTOCOL", "BLACKD": "Blackder AI", "BLACKDRAGON": "Black Dragon", + "BLACKP": "BlackPool Token", "BLACKR": "BLACK ROCK", "BLACKROCK": "BlackRock", "BLACKSALE": "Black Sale", "BLACKST": "Black Stallion", "BLACKSWAN": "BlackSwan AI", - "BLADE": "BladeWarrior", + "BLADE": "BladeGames", + "BLADEW": "BladeWarrior", "BLAKEBTC": "BlakeBitcoin", "BLANK": "Blank Token", "BLAS": "BlakeStar", @@ -1695,7 +1983,8 @@ "BLASTA": "BlastAI", "BLASTUP": "BlastUP", "BLAUNCH": "B-LAUNCH", - "BLAZE": "Blaze", + "BLAZE": "StoryFire", + "BLAZECOIN": "Blaze", "BLAZEX": "BlazeX", "BLAZR": "BlazerCoin", "BLBY": "Badluckbaby", @@ -1711,6 +2000,7 @@ "BLHC": "BlackholeCoin", "BLI": "BALI TOKEN", "BLID": "Bolide", + "BLIFFY": "BLIFFY", "BLIN": "Blin Metaverse", "BLIND": "Blindsight", "BLING": "PLEB DREKE", @@ -1730,10 +2020,13 @@ "BLOCK": "Blockasset", "BLOCKB": "Block Browser", "BLOCKF": "Block Farm Club", + "BLOCKG": "BlockGames", "BLOCKIFY": "Blockify.Games", + "BLOCKMAX": "BLOCKMAX", "BLOCKN": "BlockNet", "BLOCKPAY": "BlockPay", "BLOCKS": "BLOCKS", + "BLOCKSSPACE": "Blocks Space", "BLOCKSTAMP": "BlockStamp", "BLOCKT": "Blocktools", "BLOCKW": "Blockwise", @@ -1749,8 +2042,10 @@ "BLOX": "BLOX", "BLOXT": "Blox Token", "BLP": "BullPerks", + "BLPAI": "BullPerks AI", + "BLPT": "Blockprompt", "BLRY": "BillaryCoin", - "BLS": "Blocks Space", + "BLS": "BloodLoop", "BLST": "Crypto Legions Bloodstone", "BLT": "Blocto Token", "BLTC": "BABYLTC", @@ -1758,11 +2053,13 @@ "BLTV": "BLTV Token", "BLU": "BlueCoin", "BLUB": "BLUB", - "BLUE": "Blue Protocol", + "BLUE": "Bluefin", + "BLUEBASE": "Blue", "BLUEBUTT": "BLUE BUTT CHEESE", "BLUEG": "Blue Guy", "BLUEM": "BlueMove", "BLUEN": "Blue Norva", + "BLUEPROTOCOL": "Blue Protocol", "BLUES": "Blueshift", "BLUESC": "BluesCrypto", "BLUESPARROW": "BlueSparrow Token", @@ -1770,6 +2067,7 @@ "BLUEW": "Blue Whale", "BLUFF": "BluffCat", "BLUI": "Blui", + "BLUM": "Blum", "BLUR": "Blur", "BLURT": "Blurt", "BLUSD": "Boosted LUSD", @@ -1788,6 +2086,7 @@ "BMARS": "Binamars", "BMBO": "Bamboo Coin", "BMC": "Blackmoon Crypto", + "BMCHAIN": "BMChain", "BMDA": "Bermuda", "BME": "BitcoMine", "BMEX": "BitMEX", @@ -1802,18 +2101,24 @@ "BMONEY": "B-money", "BMP": "Brother Music Platform", "BMS": "BMS COIN", - "BMT": "BMChain", + "BMSFT": "Backed Microsoft", + "BMSTR": "Backed MicroStrategy", + "BMT": "Bubblemaps", "BMTC": "Metabit", "BMW": "BMW", "BMWUKONG": "Black Myth WuKong", "BMX": "BitMart Token", "BMXT": "Bitmxittz", "BMXX": "Multiplier", + "BN": "TNA Protocol", "BNA": "BananaTok", "BNANA": "Chimpion", "BNB": "Binance Coin", + "BNBAI": "BNB Agents", + "BNBAICLUB": "BNB AI Agent", "BNBBONK": "BNB BONK", "BNBBUNNY": "BNB BUNNY", + "BNBCARD": "BNB Card", "BNBCAT": "BNBcat", "BNBCH": "BNB Cash", "BNBD": "BNBDOG", @@ -1821,23 +2126,30 @@ "BNBDOGE": "BNBdoge", "BNBDRGN": "BNBDragon", "BNBE": "BNBEE", + "BNBETF": "BNB ETF", "BNBFLOKI": "BNB FLOKI", "BNBFROG": "BNBFROG", "BNBH": "BnbHeroes Token", "BNBLION": "BNB LION", "BNBOLYMPIC": "BNB OLYMPIC", "BNBP": "BNBPot", + "BNBPRINTER": "BNBPrinter", "BNBSNAKE": "BNB SNAKE", "BNBSONGOKU": "BNBsongoku", "BNBTC": "BNbitcoin", + "BNBULL": "BNBULL", "BNBVEGETA": "BNB VEGETA", "BNBWHALES": "BNB Whales", "BNBX": "Stader BNBx", + "BNBXBT": "BNBXBT", "BNC": "Bifrost Native Coin", "BND": "Bened", "BNF": "BonFi", + "BNIU": "Backed Niu Technologies", "BNIX": "BNIX Token", "BNK": "Bankera", + "BNKR": "BankrCoin", + "BNKV1": "Bankera v1", "BNN": "Banyan Network", "BNOM": "BitNomad", "BNP": "BenePit", @@ -1857,7 +2169,9 @@ "BNTY": "Bounty0x", "BNU": "ByteNext", "BNUSD": "Balanced Dollars", + "BNVDA": "Backed NVIDIA", "BNX": "BinaryX", + "BNXV1": "BinaryX v1", "BNY": "TaskBunny", "BOA": "BOSAGORA", "BOAI": "BOLICAI", @@ -1873,11 +2187,15 @@ "BOBE": "BOOK OF BILLIONAIRES", "BOBER": "BOBER", "BOBFUN": "BOB", + "BOBLS": "Boblles", + "BOBMARLEY": "Bob Marley Meme", "BOBO": "BOBO", "BOBOT": "Bobo The Bear", "BOBS": "Bob's Repair", "BOBT": "BOB Token", + "BOBTHE": "Bob The Builder", "BOBUKI": "Bobuki Neko", + "BOBY": "BOBY", "BOC": "BOCOIN", "BOCA": "BookOfPussyCats", "BOCAC": "BocaChica token", @@ -1899,6 +2217,8 @@ "BOGE": "Boge", "BOGEY": "Bogey", "BOGGY": "Boggy Coin", + "BOHR": "BOHR", + "BOHRV1": "BOHR v1", "BOJAK": "Based Wojak", "BOJI": "BOJI Token", "BOJIV1": "BOJI Token v1", @@ -1909,14 +2229,17 @@ "BOLD": "Bold", "BOLI": "BolivarCoin", "BOLT": "Bolt", + "BOLTAI": "Bolt AI", "BOLTT": "BolttCoin", "BOM": "Book Of Matt Furie", "BOMA": "Book of Maga", - "BOMB": "BOMB", + "BOMB": "Bombie", "BOMBC": "BombCoin", + "BOMBLOONG": "Bombloong", "BOMBM": "Bomb Money", "BOMBO": "BOMBO", "BOMBS": "Bomb Shelter Inu", + "BOMBTOKEN": "BOMB", "BOME": "BOOK OF MEME", "BOME2": "Book of Meme 2.0", "BOMEDOGE": "BOOK OF DOGE MEMES", @@ -1924,13 +2247,17 @@ "BOMES": "BOOK OF MEMES", "BOMET": "BOME TRUMP", "BOMK": "BOMK", + "BOMO": "BOMO", + "BOMT": "Baby One More Time", "BON": "Bonpay", "BONA": "Bonafi", "BOND": "BarnBridge", "BONDAPPETIT": "BondAppetit", "BONDLY": "Bondly", "BONDLYV1": "Bondly Finance", + "BONDX": "BondX", "BONE": "Bone ShibaSwap", + "BONEBONE": "Bone", "BONES": "Moonshots Farm", "BONESCOIN": "BonesCoin", "BONESV1": "Squirrel Finance", @@ -1958,8 +2285,12 @@ "BONUSCAKE": "Bonus Cake", "BOO": "Spookyswap", "BOOB": "BooBank", + "BOOCHIE": "Boochie by Matt Furie", "BOOE": "Book of Ethereum", + "BOOF": "Boofus by Virtuals", "BOOFI": "Boo Finance", + "BOOG": "BOOG base", + "BOOGIE": "Boogie", "BOOK": "Solbook", "BOOKIE": "BookieBot", "BOOKO": "Book of Pets", @@ -1969,7 +2300,8 @@ "BOOMDAO": "BOOM DAO", "BOOMER": "Boomer", "BOONS": "BOONSCoin", - "BOOP": "Boop", + "BOOP": "BOOP", + "BOOPA": "Boopa", "BOOS": "Boost Trump Campaign", "BOOST": "PodFast", "BOOSTCO": "Boost", @@ -1981,8 +2313,10 @@ "BOPPY": "BOPPY", "BOR": "BoringDAO", "BORA": "BORA", + "BORAV1": "BORA v1", "BORED": "Bored Museum", "BORG": "SwissBorg", + "BORGY": "BORGY", "BORING": "BoringDAO", "BORK": "Bork", "BORKIE": "Borkie", @@ -1996,22 +2330,26 @@ "BOSONC": "BosonCoin", "BOSS": "BitBoss", "BOSSBABY": "BossBaby", + "BOSSBURGER": "Boss Burger", "BOSSCOQ": "THE COQFATHER", "BOST": "BoostCoin", "BOSU": "Bosu Inu", "BOT": "Bot Planet", "BOTC": "BotChain", + "BOTIFY": "BOTIFY", "BOTS": "ArkDAO", "BOTTO": "Botto", "BOTX": "BOTXCOIN", "BOU": "Boulle", "BOUNCE": "Bounce Token", + "BOUNTY": "ChainBounty", "BOUTS": "BoutsPro", "BOW": "Archer Swap", "BOWE": "Book of Whales", "BOWSC": "BowsCoin", "BOWSER": "Bowser", - "BOX": "ContentBox", + "BOX": "DeBoxToken", + "BOXCAT": "BOXCAT", "BOXETH": "Cat-in-a-Box Ether", "BOXT": "BOX Token", "BOXX": "Blockparty", @@ -2046,8 +2384,9 @@ "BPRIVA": "Privapp Network", "BPRO": "BitCloud Pro", "BPS": "BitcoinPoS", + "BPSCRT": "Secret (Binance Bridge)", "BPSHIB": "Binance-Peg Shiba Inu (Binance Bridge)", - "BPT": "BlackPool Token", + "BPT": "Best Patent Token", "BPTC": "Business Platform Tomato Coin", "BPUNI": "Binance-Peg Uniswap Protocol Token (Binance Bridge)", "BPUSDC": "Binance-Peg USD Coin (Binance Bridge)", @@ -2057,21 +2396,25 @@ "BQQQ": "Bitsdaq Token", "BQT": "Blockchain Quotations Index Token", "BQTX": "BQT", - "BR": "BOHR", + "BR": "Bedrock", "BR34P": "BR34P", "BRACE": "Bitci Racing Token", + "BRAI": "Brain Frog", "BRAIN": "BrainCoin", "BRAINERS": "Brainers", "BRAINLET": "Brainlet", + "BRAINROT": "AI Brainrot", "BRAINZ": "Brainz Finance", "BRAM": "Defibox bRAM", "BRANA": "Branaverse", "BRAND": "BrandProtect", + "BRANDY": "BRANDY", "BRAT": "Peak Brat", "BRATT": "Son of Brett", "BRAWL": "BitBrawl", "BRAZ": "Brazio", "BRC": "Baer Chain", + "BRCG": "Bitcoin Roller Coaster Guy", "BRCP": "BRCP Token", "BRCST": "BRCStarter", "BRCT": "BRC App", @@ -2099,11 +2442,13 @@ "BRIA": "Briacoin", "BRIAN": "Brian Arm Strong", "BRIANWIF": "Brianwifhat", - "BRIC": "BrightCoin", + "BRIC": "Redbrick", "BRICK": "Brickchain FInance", "BRICKS": "MyBricks", + "BRICS": "BRICS Chain", "BRIDGE": "Bridge Bot", "BRIGHT": "Bright Token", + "BRIGHTCOIN": "BrightCoin", "BRIGHTU": "Bright Union", "BRIK": "BrikBit", "BRIL": "Brilliantcrypto", @@ -2115,21 +2460,33 @@ "BRIUN": "Briun Armstrung", "BRIX": "OpenBrix", "BRK": "BreakoutCoin", + "BRKBX": "Berkshire Hathaway xStock", "BRKL": "Brokoli Token", "BRMV": "BRMV Token", "BRN": "BRN Metaverse", "BRNK": "Brank", "BRNX": "Bronix", "BRO": "Bro the cat", + "BROAK": "Broak on Base", + "BROC": "Broccoli (broc.wtf)", + "BROCC": "Broccoli", + "BROCCO": "Broccoli (firstbroccoli.com)", + "BROCCOL": "Broccoli (broccolibsc.com)", + "BROCCOLI": "CZ'S Dog (broccoli.gg)", + "BROCCOLIBNB": "BROCCOLI (broccolibnb.xyz)", + "BROCCOLICZ": "Broccoli (broccoli_cz)", + "BROCCOLIVIP": "Broccoli(broccoli.vip)", "BROCK": "Bitrock", "BROGG": "Brett's Dog", "BROKE": "Broke Again", "BROKIE": "Brokie", "BRONZ": "BitBronze", + "BROOBEE": "ROOBEE", "BROOT": "BROOT", "BROTHER": "BROTHER", "BROWN": "BrowniesSwap", "BROZ": "Brozinkerbell", + "BRP": "BananaRepublic", "BRRR": "Burrow", "BRS": "Broovs Projects", "BRT": "Bikerush", @@ -2140,6 +2497,7 @@ "BRUSH": "PaintSwap", "BRUV": "Bruv", "BRWL": "Blockchain Brawlers", + "BRWS": "Browsr Ai", "BRX": "Breakout Stake", "BRY": "Berry Data", "BRYLL": "Bryllite", @@ -2149,6 +2507,7 @@ "BS": "BlackShadowCoin", "BSAFE": "BlockSafe", "BSAFU": "BlockSAFU", + "BSAI": "Bitcoin Silver AI", "BSATOSHI": "BabySatoshi", "BSB": "Based Street Bets", "BSC": "BSC Layer", @@ -2165,6 +2524,7 @@ "BSCV": "Bscview", "BSDETH": "Based ETH", "BSE": "base season", + "BSEN": "Baby Sen by Sentio", "BSEND": "BitSend", "BSFM": "BABY SAFEMOON", "BSG": "Baby Squid Game", @@ -2177,6 +2537,7 @@ "BSKT": "BasketCoin", "BSL": "BankSocial", "BSOL": "BlazeStake Staked SOL", + "BSOP": "Bsop", "BSOV": "BitcoinSoV", "BSP": "BallSwap", "BSPM": "Bitcoin Supreme", @@ -2194,7 +2555,7 @@ "BSW": "Biswap", "BSWAP": "BaseSwap", "BSWT": "BaySwap", - "BSX": "Basilisk", + "BSX": "BSX", "BSY": "Bestay", "BSYS": "BSYS", "BT": "BT.Finance", @@ -2214,11 +2575,14 @@ "BTCA": "BITCOIN ADDITIONAL", "BTCAB": "Bitcoin Avalanche Bridged", "BTCACT": "BITCOIN Act", + "BTCAI": "BTC AI Agent", "BTCAS": "BitcoinAsia", "BTCAT": "Bitcoin Cat", "BTCB": "Bitcoin BEP2", + "BTCBASE": "Bitcoin on Base", "BTCBR": "Bitcoin BR", "BTCBRV1": "Bitcoin BR v1", + "BTCBULL": "BTC Bull", "BTCC": "Bitcoin Core", "BTCD": "BitcoinDark", "BTCDRAGON": "BTC Dragon", @@ -2234,15 +2598,19 @@ "BTCL": "BTC Lite", "BTCM": "BTCMoon", "BTCMT": "Minto", - "BTCN": "BitcoiNote", + "BTCN": "Bitcorn", "BTCNOW": "Blockchain Technology Co.", + "BTCONETH": "bitcoin on Ethereum", "BTCP": "Bitcoin Palladium", "BTCPAY": "Bitcoin Pay", + "BTCPR": "Bitcoin Pro", + "BTCPT": "Bitcoin Platinum", "BTCPX": "BTC Proxy", "BTCR": "BitCurrency", "BTCRED": "Bitcoin Red", "BTCRY": "BitCrystal", "BTCS": "Bitcoin Scrypt", + "BTCSR": "BTC Strategic Reserve", "BTCST": "BTC Standard Hashrate Token", "BTCT": "Bitcoin Token", "BTCUS": "Bitcoinus", @@ -2263,6 +2631,7 @@ "BTL": "Bitlocus", "BTLC": "BitLuckCoin", "BTM": "Bytom", + "BTMETA": "BTCASH", "BTMG": "Bitcademy Football", "BTMI": "BitMiles", "BTMK": "BitMark", @@ -2273,6 +2642,7 @@ "BTNYX": "BitOnyx Token", "BTO": "Bottos", "BTOP": "Botopia.Finance", + "BTORO": "Bitoro Network", "BTP": "Bitpaid", "BTPL": "Bitcoin Planet", "BTQ": "BitQuark", @@ -2285,10 +2655,13 @@ "BTRS": "Bitball Treasure", "BTRST": "Braintrust", "BTRU": "Biblical Truth", + "BTRUMP": "Baron Trump", "BTS": "Bitshares", "BTSC": "BTS Chain", "BTSE": "BTSE Token", "BTSG": "BitSong", + "BTSGV1": "BitSong v1", + "BTSLA": "Backed Tesla", "BTT": "BitTorrent", "BTTF": "Coin to the Future", "BTTOLD": "BitTorrent", @@ -2297,7 +2670,7 @@ "BTU": "BTU Protocol", "BTV": "Bitvote", "BTW": "BitWhite", - "BTX": "BitCore", + "BTX": "Bitradex Token", "BTXC": "Bettex coin", "BTY": "Bityuan", "BTYC": "BigTycoon", @@ -2306,12 +2679,16 @@ "BTZN": "Bitzon", "BU": "BUMO", "BUB": "BUBCAT", + "BUBB": "Bubb", "BUBBA": "Bubba", "BUBBLE": "Bubble", + "BUBBLES": "BUBBLES", "BUBO": "Budbo", "BUBU": "BUBU", + "BUBV1": "BUBCAT v1", "BUC": "Beau Cat", - "BUCK": "Coinbuck", + "BUCK": "GME Mascot", + "BUCKAZOIDS": "Buckazoids", "BUCKS": "SwagBucks", "BUCKY": "Bucky", "BUD": "Buddy", @@ -2327,24 +2704,33 @@ "BUGATTI": "BUGATTI", "BUGG": "Bugg Inu", "BUGS": "Bugs Bunny", - "BUIDL": "Starter.xyz", + "BUI": "Build forward", + "BUIDL": "BlackRock USD Institutional Digital Liquidity Fund", + "BUIDLI": "BlackRock USD Institutional Digital Liquidity Fund - I Class", + "BUIL": "BUILD", "BUILD": "BuildAI", "BUILDIN": "Buildin Token", + "BUILDON": "Build On BNB", "BUILDTEAM": "BuildTeam", + "BUILT": "Built Different", "BUK": "CryptoBuk", "BUL": "bul", "BULDAK": "Buldak", "BULEI": "Bulei", - "BULL": "Bullieverse", + "BULL": "Tron Bull", + "BULLA": "BULLA", + "BULLBEAR": "BullBear AI", "BULLC": "BuySell", "BULLF": "BULL FINANCE", "BULLI": "Bullish On Ethereum", + "BULLIEVERSE": "Bullieverse", "BULLINU": "Bull inu", - "BULLION": "BullionFX", + "BULLIONFX": "BullionFX", "BULLISH": "bullish", "BULLMOON": "Bull Moon", "BULLPEPE": "Bullpepe", "BULLS": "Bull Coin", + "BULLSEYE": "bulls-eye", "BULLSH": "Bullshit Inu", "BULLY": "Dolos The Bully", "BULLYINGCAT": "Bullying Cat", @@ -2356,7 +2742,9 @@ "BUND": "Bund V2.0", "BUNDL": "Bundl Tools", "BUNI": "Bunicorn", - "BUNN": "Bunni", + "BUNKER": "BunkerCoin", + "BUNNI": "Bunni", + "BUNNIV1": "Timeless", "BUNNY": "Pancake Bunny", "BUNNYINU": "Bunny Inu", "BUNNYM": "BUNNY MEV BOT", @@ -2372,17 +2760,22 @@ "BURNZ": "BURNZ", "BURP": "CoinBurp", "BURRRD": "BURRRD", + "BURT": "BURT", "BUSD": "Binance USD", "BUSDC": "BUSD", "BUSY": "Busy DAO", - "BUT": "BitUP Token", + "BUT": "Bucket Token", "BUTT": "Buttercat", + "BUTTCOIN": "The Next Bitcoin", + "BUTTHOLE": "Butthole Coin", "BUX": "BUX", "BUXCOIN": "Buxcoin", "BUY": "Burency", "BUYI": "Buying.com", "BUYT": "Buy the DIP", - "BUZZ": "BuzzCoin", + "BUZ": "BUZ", + "BUZZ": "Hive AI", + "BUZZCOIN": "BuzzCoin", "BV3A": "Buccaneer V3 Arbitrum", "BVC": "BeaverCoin", "BVM": "BVM", @@ -2417,8 +2810,10 @@ "BXX": "Baanx", "BXY": "Beaxy", "BYAT": "Byat", + "BYB": "BiorBank", "BYC": "ByteCent", "BYG": "Black Eye Galaxy", + "BYIN": "BYIN", "BYT": "ByteAI", "BYTE": "Byte", "BYTES": "Neo Tokyo", @@ -2464,9 +2859,12 @@ "CAG": "Change", "CAGA": "Crypto Asset Governance Alliance", "CAH": "Moon Tropica", - "CAI": "Cai Token", + "CAI": "Chasm", "CAID": "ClearAid", + "CAILA": "Caila", "CAIR": "Crypto-AI-Robo.com", + "CAITOKEN": "Cai Token", + "CAIV": "CARVIS", "CAIX": "CAIx", "CAIZ": "Caizcoin", "CAKE": "PancakeSwap", @@ -2474,21 +2872,25 @@ "CAKEMOON": "CakeMoon", "CAKESWAP": "CakeSwap", "CAKEW": "CakeWSwap", - "CAL": "Calcium", + "CAL": "FitBurn", "CALC": "CaliphCoin", + "CALCI": "Calcium", "CALI": "CaliCoin", "CALL": "Global Crypto Alliance", + "CALLS": "OnlyCalls by Virtuals", "CALO": "Calo", "CAM": "Consumption Avatar Matrix", "CAMC": "Camcoin", "CAMEL": "The Camel", + "CAMINO": "Camino Network", "CAMLY": "Camly Coin", "CAMP": "Camp", "CAMT": "CAMELL", "CAN": "Channels", "CANCER": "Cancer", "CAND": "Canary Dollar", - "CANDLE": "Candle Cat", + "CANDLE": "Candle TV", + "CANDLECAT": "Candle Cat", "CANDY": "UnicornGo Candy", "CANDYLAD": "Candylad", "CANN": "CannabisCoin", @@ -2505,17 +2907,24 @@ "CAPRICOIN": "CapriCoin", "CAPS": "Ternoa", "CAPT": "Bitcoin Captain", + "CAPTAINBNB": "CaptainBNB", "CAPTAINPLANET": "Captain Planet", "CAPY": "Capybara", - "CAR": "CarBlock", - "CARAT": "Carats Token", + "CAPYBARA": "Capybara", + "CAPYBARA1995": "Capybara", + "CAR": "Central African Republic Meme", + "CARAT": "AlaskaGoldRush", + "CARATSTOKEN": "Carats Token", + "CARBLOCK": "CarBlock", "CARBO": "CleanCarbon", - "CARBON": "Carboncoin", + "CARBON": "Carbon", + "CARBONCOIN": "Carboncoin", "CARBONGEMS": "Carbon GEMS", "CARD": "Cardstack", "CARDS": "Cardstarter", "CARDSWAP": "CardSwap", - "CARE": "Carebit", + "CARE": "CareCoin", + "CAREBIT": "Carebit", "CARES": "CareCoin", "CARL": "Carl", "CARLO": "Carlo", @@ -2523,10 +2932,12 @@ "CAROL": "CAROLToken", "CARPE": "CarpeDiemCoin", "CARR": "Carnomaly", - "CARROT": "CarrotSwap", + "CARROT": "Carrot by Puffer", + "CARROTSWAP": "CarrotSwap", "CART": "CryptoArt.Ai", "CARTAXI": "CarTaxi", "CARTERCOIN": "CarterCoin", + "CARTIER": "Cartier", "CARV": "CARV", "CAS": "Cashaa", "CASH": "CashCoin", @@ -2535,6 +2946,7 @@ "CASINU": "Casinu Inu", "CASIO": "CasinoXMetaverse", "CASPER": "Casper DeFi", + "CASPERTOKEN": "Casper Token", "CAST": "Castello Coin", "CASTLE": "bitCastle", "CAT": "Simon's Cat", @@ -2552,17 +2964,21 @@ "CATCO": "CatCoin", "CATCOIN": "CatCoin", "CATCOINETH": "Catcoin", + "CATCOINOFSOL": "Cat Coin", "CATCOINV2": "CatCoin Cash", "CATDOG": "Cat-Dog", "CATDOGE": "CAT DOGE", + "CATE": "Cate on ETH", "CATEC": "Cate Coin", "CATECOIN": "CateCoin", "CATELON": "CatElonMars", "CATEX": "CATEX", "CATFISH": "Catfish", + "CATG": "Crypto Agent Trading", "CATGAME": "Cookie Cat Game", "CATGIRL": "Catgirl", "CATGOKU": "Catgoku", + "CATGOLD": "Cat Gold Miner", "CATGPT": "CatGPT", "CATHAT": "catwifhat", "CATHEON": "Catheon Gaming", @@ -2576,15 +2992,17 @@ "CATO": "CATO", "CATPAY": "CATpay", "CATPEPE": "CAT PEPE", - "CATS": "CatCoin Token", + "CATS": "Cats", "CATSC": "Catscoin", "CATSHIRA": "Shira Cat", "CATSO": "Cats Of Sol", "CATSON": "Catson", "CATSV1": "CatCoin Token v1", + "CATSV2": "CatCoin Token", "CATSY": "CAT SYLVESTER", "CATT": "Catex", "CATTO": "Cat Token", + "CATTON": "Catton AI", "CATVAX": "Catvax", "CATVILLS": "Catvills Coin", "CATW": "Cat wif Hands", @@ -2593,6 +3011,8 @@ "CATX": "CAT.trade Protocol", "CATZ": "CatzCoin", "CAU": "Canxium", + "CAUSE": "Causecoin", + "CAV1": "Coupon Assets v1", "CAVA": "Cavapoo", "CAVADA": "Cavada", "CAVE": "Deepcave", @@ -2645,6 +3065,7 @@ "CCC": "CCCoin", "CCCX": "Clipper Coin Capital", "CCD": "Concordium", + "CCDOG": "Courage The Dog", "CCDS": "CCDS INTERNATIONAL", "CCE": "CloudCoin", "CCGDS": "CCGDS", @@ -2668,7 +3089,9 @@ "CCXC": "CoolinDarkCoin", "CCXX": "CounosX", "CDAI": "Compound Dai", + "CDBIO": "CDbio", "CDCETH": "Crypto.com Staked ETH", + "CDCSOL": "Crypto.com Staked SOL", "CDEX": "Cryptodex", "CDL": "CoinDeal Token", "CDN": "Canada eCoin", @@ -2687,6 +3110,7 @@ "CEICAT": "CEILING CAT", "CEJI": "Ceji", "CEL": "Celsius Network", + "CELA": "Cellula Token", "CELEB": "CELEBPLUS", "CELL": "Cellframe", "CELO": "Celo", @@ -2705,9 +3129,11 @@ "CEODOGE": "CEO DOGE", "CERBER": "CERBEROGE", "CERE": "Cere Network", + "CEREB": "Cerebrum", "CERES": "Ceres", "CES": "swap.coffee", "CESC": "Crypto Escudo", + "CESS": "CESS Token", "CET": "CoinEx Token", "CETH": "Compound Ethereum", "CETI": "CETUS Coin", @@ -2719,7 +3145,7 @@ "CFD": "Confido", "CFF": "Coffe", "CFG": "Centrifuge", - "CFI": "Cofound.it", + "CFI": "CyberFi Token", "CFL365": "CFL365 Finance", "CFLASH": "Flash", "CFLO": "Chain Flowers", @@ -2731,21 +3157,26 @@ "CFXT": "Chainflix", "CFun": "CFun", "CGA": "Cryptographic Anomaly", + "CGAI": "GDAI Agent", "CGAR": "CryptoGuards", "CGG": "Chain Guardians", "CGL": "Crypto Gladiator Shards", "CGLD": "Celo Gold", "CGO": "Comtech Gold", "CGPT": "ChainGPT", - "CGPU": "CloudGPU", + "CGPU": "ChainGPU", "CGS": "Crypto Gladiator Shards", "CGT": "Coin Gabbar Token", + "CGTV1": "Curio Governance", + "CGTV2": "Curio Gas Token", "CGU": "Crypto Gaming United", "CGV": "Cogito Finance", + "CGX": "Forkast", "CHA": "Charity Coin", "CHACHA": "Chacha", "CHAD": "Chad Coin", "CHADCAT": "CHAD CAT", + "CHADETTE": "Chadette", "CHADS": "CHADS VC", "CHAI": "Chroma AI", "CHAIN": "Chain Games", @@ -2756,6 +3187,7 @@ "CHAMPZ": "Champz", "CHAN": "ChanCoin", "CHANCE": "Ante Casino", + "CHANEL": "Chanel", "CHANG": "Chang", "CHANGE": "ChangeX", "CHAO": "23 Skidoo", @@ -2772,6 +3204,7 @@ "CHAT": "Solchat", "CHATAI": "ChatAI Token", "CHATGPT": "AI Dragon", + "CHATOSHI": "chAtoshI", "CHATTY": "ChatGPT's Mascot", "CHB": "COINHUB TOKEN", "CHBR": "CryptoHub", @@ -2784,14 +3217,17 @@ "CHEDDA": "Chedda", "CHEEKS": "CHEEKS", "CHEEL": "Cheelee", - "CHEEMS": "Cheems", + "CHEEMS": "Cheems (cheems.pet)", + "CHEEMSCO": "Cheems", + "CHEEMSV1": "Cheems (cheems.pet) v1", "CHEEPEPE": "CHEEPEPE", "CHEERS": "DICAPRIO CHEERS", "CHEESE": "Cheese", "CHEESEBALL": "Cheeseball the Wizard", "CHEESECOIN": "Cheesecoin", "CHEESUS": "Cheesus", - "CHEF": "Chefdotfun", + "CHEF": "CoinChef", + "CHEFDOTFUN": "Chefdotfun", "CHENG": "Chengshi", "CHEQ": "CHEQD Network", "CHER": "Cherry Network", @@ -2822,8 +3258,11 @@ "CHILDAI": "Singularity's Child gonzoai", "CHILI": "CHILI", "CHILL": "ChillPill", + "CHILLAX": "Chillax", "CHILLGUY": "Chill Guy", + "CHILLHOUSE": "Chill House", "CHIM": "Chimera", + "CHINA": "China Coin", "CHINAU": "Chinau", "CHINAZILLA": "ChinaZilla", "CHINGON": "Mexico Chingon", @@ -2832,7 +3271,8 @@ "CHIPI": "chipi", "CHIPPY": "Chippy", "CHIPS": "CHIPS", - "CHIRP": "Chirp", + "CHIRP": "Chirp Token", + "CHIRPFI": "Chirp", "CHIRPY": "Chirpy Boy", "CHITAN": "Chitan", "CHITCAT": "ChitCAT", @@ -2856,9 +3296,11 @@ "CHOPPER": "Chopper Inu", "CHOPPY": "Choppy", "CHORIZO": "Chorizo", + "CHORUZ": "Choruz AI", "CHOW": "Chow Chow Finance", "CHOY": "Bok Choy", "CHP": "CoinPoker Token", + "CHPD": "Chirppad", "CHR": "Chroma", "CHRETT": "Chinese BRETT", "CHRISPUMP": "Christmas Pump", @@ -2902,6 +3344,7 @@ "CIRRUS": "Cirrus", "CIRUS": "Cirus", "CIRX": "Circular Protocol", + "CITADAIL": "Griffain New Hedge Fund", "CITI": "CITI Fediverse", "CITY": "Manchester City Fan Token", "CIV": "Civilization", @@ -2928,14 +3371,17 @@ "CLAS": "Classic USDC", "CLASH": "Clashub", "CLASS": "Class Coin", - "CLAY": "Clay Nation", + "CLAY": "Clayton", + "CLAYN": "Clay Nation", "CLB": "Cloudbric", "CLBR": "Colibri Protocol", + "CLBTC": "clBTC", "CLCT": "CollectCoin", "CLD": "Cloud", "CLDX": "Cloverdex", - "CLEAR": "Clear Water", + "CLEAR": "Everclear", "CLEARPOLL": "ClearPoll", + "CLEARWATER": "Clear Water", "CLEG": "Chain of Legends", "CLEO": "Cleo Tech", "CLEV": "CLever Token", @@ -2955,6 +3401,7 @@ "CLM": "CoinClaim", "CLMRS": "Crolon Mars", "CLN": "Colu Local Network", + "CLND": "COLEND", "CLNX": "Coloniume Network", "CLNY": "Colony", "CLO": "Callisto Network", @@ -2963,6 +3410,7 @@ "CLOKI": "CATLOKI", "CLORE": "Clore.ai", "CLOUD": "Cloud", + "CLOUDGPU": "CloudGPU", "CLOUT": "BitClout", "CLOUTIO": "Clout", "CLOW": "Clown Pepe", @@ -2974,6 +3422,8 @@ "CLU": "CluCoin", "CLUB": "ClubCoin", "CLUD": "CludCoin", + "CLUSTR": "Clustr Labs", + "CLUTCH": "Clutch", "CLV": "Clover Finance", "CLVA": "Clever DeFi", "CLVX": "Calvex", @@ -2982,6 +3432,7 @@ "CMA": "Crypto Market Ads", "CMC": "CosmosCoin", "CMCC": "CMC Coin", + "CMCSAX": "Comcast xStock", "CMCT": "Crowd Machine", "CMCX": "CORE MultiChain", "CMDX": "Comdex", @@ -3001,6 +3452,7 @@ "CMP": "Caduceus", "CMPCO": "CampusCoin", "CMPT": "Spatial Computing", + "CMPV2": "Caduceus Protocol", "CMQ": "Communique", "CMS": "COMSA", "CMSN": "The Commission", @@ -3048,6 +3500,10 @@ "COCK": "Shibacock", "COCO": "COCO COIN", "COCONUT": "Coconut", + "COCOR": "Cocoro", + "COCORO": "Cocoro", + "COCOROBNB": "Cocoro", + "COCOROERC": "COCORO", "COD": "Chief of Deswamp", "CODA": "CODA", "CODAI": "CODAI", @@ -3063,14 +3519,17 @@ "COFFEECOIN": "CoffeeCoin", "COFI": "CoinFi", "COFIX": "CoFIX", + "COFOUNDIT": "Cofound.it", "COG": "Cognitio", "COGE": "Cogecoin", "COGEN": "Cogenero", "COGI": "COGI", "COGS": "Cogmento", "COI": "Coinnec", + "COINAI": "Coinbase AI Agent", "COINB": "Coinbidex", "COINBT": "CoinBot", + "COINBUCK": "Coinbuck", "COINDEFI": "Coin", "COING": "Coingrid", "COINH": "Coinhound", @@ -3080,23 +3539,28 @@ "COINSCOPE": "Coinscope", "COINSL": "CoinsLoot", "COINVEST": "Coinvest", + "COINX": "Coinbase xStock", "COINYE": "Coinye West", "COJ": "Cojam", "COK": "Cat Own Kimono", "COKE": "Cocaine Cowboy Shards", + "COKEONS": "Coke on Sol", "COL": "Clash of Lilliput", "COLA": "Cola", + "COLISEUM": "Coliseum", "COLL": "Collateral Pay", "COLLAR": "PolyPup Finance", + "COLLAT": "Collaterize", "COLLE": "Collective Care", "COLLEA": "Colle AI", "COLLECT": "CoinCollect", "COLLG": "Collateral Pay Governance", "COLON": "Colon", "COLR": "colR Coin", + "COLS": "Cointel", "COLT": "Collateral Network", "COLX": "ColossusCoinXT", - "COM": "Coliseum", + "COM": ".com", "COMAI": "Commune AI", "COMB": "Combo", "COMBO": "COMBO", @@ -3106,14 +3570,16 @@ "COMEW": "Coin In Meme World", "COMFI": "CompliFi", "COMM": "Community Coin", + "COMMS": "CallofMeme", "COMMUNITYCOIN": "Community Coin", - "COMP": "Compound Governance Token", + "COMP": "Compound", "COMPCOIN": "Compcoin", "COMPD": "Compound Coin", "COMPU": "Compute Network", "COMT": "Community Token", "CONAN": "Conan", "CONC": "Concentrator", + "CONCHO": "Sapo Concho", "CONDENSATE": "Condensate", "CONDO": "CONDO", "CONE": "BitCone", @@ -3123,14 +3589,18 @@ "CONK": "ShibaPoconk", "CONS": "ConSpiracy Coin", "CONSENTIUM": "Consentium", + "CONTENTBOX": "ContentBox", "CONTROL": "Control Token", "CONV": "Convergence", + "CONVO": "Prefrontal Cortex Convo Agent by Virtuals", "CONX": "Connex", + "CONY": "Cony", "COO": "Cool Cats MILK", "COOCHIE": "Cucci", "COOHA": "CoolHash", - "COOK": "Cook", + "COOK": "COOK", "COOKIE": "Cookie", + "COOKTOKEN": "Cook", "COOL": "CoolCoin", "COOP": "Coop Network", "COPA": "COCO PARK", @@ -3138,11 +3608,15 @@ "COPI": "Cornucopias", "COPIO": "Copiosa Coin", "COPIUM": "Copium", + "COPPER": "COPPER", "COPS": "Cops Finance", "COPYCAT": "Copycat Finance", "COQ": "Coq Inu", "COR": "Coreto", - "CORAL": "CoralPay", + "CORA": "Cora by Virtuals", + "CORAL": "Coral Protocol", + "CORALPAY": "CoralPay", + "CORALSWAP": "Coral Swap", "CORE": "Core", "COREC": "CoreConnect", "COREDAO": "coreDAO", @@ -3153,10 +3627,13 @@ "CORGIAI": "CorgiAI", "CORGIB": "The Corgi of PolkaBridge", "CORION": "Corion", - "CORN": "CORN", + "CORN": "Corn", "CORNELLA": "CORNELLA", + "CORNFIELDFARM": "CORN", "CORSI": "Cane Corso", + "CORTEX": "Cortex Protocol", "CORX": "CorionX", + "CORXB": "CorionX BSC", "COS": "Contentos", "COSHI": "CoShi Inu", "COSM": "CosmoChain", @@ -3169,6 +3646,7 @@ "COSX": "Cosmecoin", "COT": "CoTrader", "COTI": "COTI", + "COTS": "Children Of The Sky", "COU": "Couchain", "COUNOS": "Counos Coin", "COUNOSBIT": "Counos Bit", @@ -3219,6 +3697,7 @@ "CPTN": "Captain Max", "CPU": "CPUcoin", "CPX": "Apex Token", + "CPXTB": "Coin Prediction Tool On Base", "CPY": "COPYTRACK", "CQST": "ConquestCoin", "CQT": "Covalent", @@ -3235,11 +3714,13 @@ "CRAIG": "CraigsCoin", "CRAMER": "Cramer Coin", "CRANEPAY": "Cranepay", + "CRAPPY": "CrappyBird", "CRASH": "Solana Crash", "CRASHBOYS": "CRASHBOYS", "CRAVE": "CraveCoin", "CRAYRABBIT": "CrazyRabbit", "CRAZ": "CRAZY FLOKI", + "CRAZE": "Craze", "CRAZYB": "Crazy Bunny", "CRAZYBONK": "CRAZY BONK", "CRAZYBUNNY": "Crazy Bunny", @@ -3254,6 +3735,8 @@ "CRBN": "Carbon", "CRBRUS": "Cerberus", "CRC": "CryCash", + "CRCL": "Circle", + "CRCLX": "Circle xStock", "CRD": "CRD Network", "CRDC": "Cardiocoin", "CRDN": "Cardence", @@ -3279,6 +3762,7 @@ "CREP": "Compound Augur", "CREPE": "Crepe Coin", "CRES": "Cresio", + "CRESV1": "Cresio v1", "CREV": "CryptoRevolution", "CREVA": "Creva Coin", "CREW": "CREW INU", @@ -3300,6 +3784,7 @@ "CRL": "Cryptelo Coin", "CRM": "Cream", "CRMS": "Cryptomus", + "CRMX": "Salesforce xStock", "CRNCHY": "Crunchy Network", "CRNK": "CrankCoin", "CRO": "Cronos", @@ -3314,14 +3799,18 @@ "CRONA": "CronaSwap", "CRONK": "CRONK", "CROPPER": "CropperFinance", + "CROS": "Cros Token", + "CROSS": "Cross", + "CROW": "cr0w by Virtuals", "CROWD": "CrowdCoin", "CROWDWIZ": "Crowdwiz", "CROWN": "Crown by Third Time Games", + "CROWWITH": "crow with knife", "CROX": "CroxSwap", "CRP": "Crypton", "CRPS": "CryptoPennies", "CRPT": "Crypterium", - "CRS": "CRYSTALS", + "CRS": "CYRUS", "CRSP": "CryptoSpots", "CRT": "Carr.Finance", "CRTAI": "CRT AI Network", @@ -3339,24 +3828,34 @@ "CRVY": "Curve Inu", "CRW": "Crown Coin", "CRWD": "CRWD Network", + "CRWDX": "CrowdStrike xStock", "CRWNY": "Crowny Token", "CRX": "ChronosCoin", "CRY": "Crypto News Flash AI", + "CRYBB": "CryBaby", "CRYN": "CRYN", "CRYO": "CryoDAO", "CRYP": "CrypticCoin", + "CRYPSURE": "CrypSure", "CRYPT": "CryptCoin", + "CRYPTAL": "CrypTalk", "CRYPTER": "Crypteriumcoin", + "CRYPTOA": "CryptoAI", + "CRYPTOAGENT": "CRYPTO AGENT TRUMP", "CRYPTOAI": "CryptoAI", "CRYPTOB": "Crypto Burger", "CRYPTOBEAST": "CryptoBeast", "CRYPTOBL": "CryptoBlades Kingdoms", + "CRYPTOBR": "Crypto Bro", "CRYPTOBULLION": "CryptoBullion", + "CRYPTODELIVERY": "Crypto Delivery", "CRYPTOE": "Cryptoenter", "CRYPTOEM": "Crypto Emperor Trump", "CRYPTOF": "CryptoFarmers", + "CRYPTOFIGHT": "Crypto Fight Club", "CRYPTOH": "CryptoHunterTrading", "CRYPTOJ": "Crypto Journey", + "CRYPTOJESUS": "Crypto Jesus Trump", "CRYPTON": "CRYPTON", "CRYPTONITE": "Cryptonite", "CRYPTOOFFICIAL": "Crypto", @@ -3366,15 +3865,18 @@ "CRYPTOS": "CryptoSoul", "CRYPTOSDG": "Crypto SDG", "CRYPTOT": "Crypto Trump", + "CRYPTOTANKS": "CryptoTanks", "CRYPTOU": "CryptoUnity", "CRYSTAL": "Crystal", "CRYSTALCLEAR": "Crystal Clear Token", + "CRYSTALS": "CRYSTALS", "CRYSTL": "Crystl Finance", "CS": "Child Support", "CSAC": "Credit Safe Application Chain", "CSAI": "Compound SAI", "CSAS": "csas (Ordinals)", "CSC": "CasinoCoin", + "CSCOX": "Cisco xStock", "CSEN": "Sentient Coin", "CSH": "CashOut", "CSI": "CSI888", @@ -3390,9 +3892,12 @@ "CSQ": "cosquare", "CSR": "Cashera", "CSS": "CoinSwap Token", + "CST": "Crypto Samurai", + "CSTAR": "COINSTAR", "CSTC": "CryptosTribe", "CSTL": "Castle", "CSTR": "CoreStarter", + "CSUSDL": "Coinshift USDL Morpho Vault", "CSUSHI": "cSUSHI", "CSW": "Crosswalk", "CSWAP": "ChainSwap", @@ -3408,6 +3913,7 @@ "CTEX": "Crypto tex", "CTF": "CyberTime Finance", "CTG": "City Tycoon Games", + "CTH": "Changcoin", "CTI": "ClinTex CTi", "CTIC": "Coinmatic", "CTK": "Shentu", @@ -3417,6 +3923,7 @@ "CTLX": "Cash Telex", "CTN": "Continuum Finance", "CTO": "BaseCTO", + "CTOAI": "ClustroAI", "CTOK": "Codyfight", "CTP": "Ctomorrow Platform", "CTPL": "Cultiplan", @@ -3432,21 +3939,25 @@ "CTX": "Cryptex", "CTXC": "Cortex", "CTY": "Connecty", + "CTYN": "Canyont", "CU": "Crypto Unicorns", "CUAN": "CuanSwap.com", "CUB": "Cub Finance", - "CUBE": "Cube Network", + "CUBE": "Somnium Space CUBEs", "CUBEAUTO": "Cube", "CUBEB": "CubeBase", + "CUBENETWORK": "Cube Network", "CUCCI": "Cat in Gucci", "CUCK": "Cuckadoodledoo", + "CUDIS": "Cudis", "CUDOS": "Cudos", "CUE": "CUE Protocol", "CUEX": "Cuex", "CUFF": "Jail Cat", "CULO": "CULO", "CULOETH": "CULO", - "CULT": "Cult DAO", + "CULT": "Milady Cult Coin", + "CULTDAO": "Cult DAO", "CULTUR": "Cultur", "CUM": "Cumbackbears", "CUMINU": "CumInu", @@ -3455,12 +3966,12 @@ "CURA": "Cura Network", "CURE": "Curecoin", "CURI": "Curium", - "CURIO": "Curio Governance", "CURLY": "Curly", "CURR": "Curry", "CURRY": "CurrySwap", "CUSD": "Carbon", "CUSDC": "Compound USD Coin", + "CUSDO": "Compounding Open Dollar", "CUSDT": "cUSDT", "CUSDTBULL": "3X Long Compound USDT Token", "CUST": "Custody Token", @@ -3492,11 +4003,13 @@ "CVX": "Convex Finance", "CVXCRV": "Convex CRV", "CVXFXS": "Convex FXS", + "CVXX": "Chevron xStock", "CW": "CardWallet", "CWA": "Chris World Asset", "CWAR": "Cryowar Token", "CWBTC": "Compound Wrapped BTC", "CWD": "CROWD", + "CWDV1": "Linkflow", "CWEB": "Coinweb", "CWEX": "Crypto Wine Exchange", "CWIF": "catwifhat", @@ -3530,9 +4043,11 @@ "CYBERWAY": "CyberWay", "CYBONK": "CYBONK", "CYBR": "CYBR", + "CYBRO": "Cybro Token", "CYC": "Cyclone Protocol", "CYCAT": "Chi Yamada Cat", "CYCE": "Crypto Carbon Energy", + "CYCEV1": "Crypto Carbon Energy v1", "CYCLE": "Cycle Finance", "CYCLUB": "Cyclub", "CYCON": "CONUN", @@ -3552,7 +4067,9 @@ "CYS": "BlooCYS", "CYT": "Cryptokenz", "CZ": "CHANGPENG ZHAO (changpengzhao.club)", + "CZBROCCOLI": "Cz Broccoli", "CZC": "Crazy Coin", + "CZDOG": "CZ Dog", "CZF": "CZodiac Farming Token", "CZGOAT": "CZ THE GOAT", "CZKING": "CZKING", @@ -3562,7 +4079,7 @@ "CZSHARES": "CZshares", "CZUSD": "CZUSD", "CZZ": "ClassZZ", - "D": "Denarius", + "D": "Dar Open Network", "D11": "DeFi11", "D2O": "DAM Finance", "D2T": "Dash 2 Trade", @@ -3591,6 +4108,7 @@ "DAFI": "Dafi Protocol", "DAFT": "DaftCoin", "DAG": "Constellation", + "DAGESTAN": "Dagestan And Forget", "DAGO": "Dago Mining", "DAGS": "Dagcoin", "DAGT": "Digital Asset Guarantee Token", @@ -3602,7 +4120,9 @@ "DAIN": "Dain Token", "DAIQ": "Daiquilibrium", "DAISY": "Daisy Launch Pad", + "DAIWO": "D.A.I.Wo", "DAK": "dak", + "DAKU": "Der Daku", "DAL": "DAOLaunch", "DALI": "Dalichain", "DALMA": "Dalma Inu", @@ -3613,6 +4133,7 @@ "DAMOON": "Damoon Coin", "DAN": "Daneel", "DANA": "Ardana", + "DANCING": "Dancing Michi", "DANG": "Guangdang", "DANGEL": "dAngel Fund", "DANJ": "Danjuan Cat", @@ -3622,13 +4143,15 @@ "DAO1": "DAO1", "DAOACT": "ACT", "DAOB": "DAOBet", + "DAOLITY": "Daolity", "DAOP": "Dao Space", "DAOSOL": "MonkeDAO", "DAOVC": "DAO.VC", "DAOX": "Daox", - "DAPP": "LiquidApps", + "DAPP": "Pencils Protocol", "DAPPSY": "Dappsy", "DAPPT": "Dapp Token", + "DAPPTOKEN": "LiquidApps", "DAPPX": "dAppstore", "DAPS": "DAPS Coin", "DAR": "Mines of Dalarnia", @@ -3641,11 +4164,15 @@ "DARED": "Daredevil Dog", "DARICO": "Darico", "DARIK": "Darik", - "DARK": "Dark", + "DARK": "Dark Eclipse", + "DARKCOIN": "Dark", "DARKEN": "Dark Energy Crystals", + "DARKF": "Dark Frontiers", "DARKMAGACOIN": "DARK MAGA", "DARKT": "Dark Trump", + "DARKTOKEN": "DarkToken", "DART": "dART Insurance", + "DARWIN": "Darwin", "DARX": "Bitdaric", "DAS": "DAS", "DASC": "DasCoin", @@ -3655,8 +4182,11 @@ "DASIAv": "DASIA", "DAT": "Datum", "DATA": "Streamr", + "DATAB": "Databot", + "DATAMALL": "Datamall Coin", "DATAO": "Data Ownership Protocol", "DATAWALLET": "DataWallet", + "DATBOI": "Dat Boi", "DATOM": "Drop Staked ATOM", "DATP": "Decentralized Asset Trading Platform", "DATX": "DATx", @@ -3664,10 +4194,12 @@ "DAV": "DAV", "DAVE": "DAVE", "DAVID": "David", + "DAVINC": "DaVinci Protocol", "DAVINCI": "Davincigraph", "DAVIS": "Davis Cup Fan Token", "DAVP": "Davion", "DAW": "DAWKOINS", + "DAWAE": "DaWae", "DAWCURRENCY": "Daw Currency", "DAWG": "Dawg Coin", "DAWGS": "SpaceDawgs", @@ -3708,6 +4240,7 @@ "DCCT": "DocuChain", "DCD": "DecideAI", "DCE": "Decentra Ecosystem", + "DCF": "Decentralized Finance", "DCHEFSOL": "Degen Chef", "DCHEWY": "Drop Chewy", "DCHF": "DeFi Franc", @@ -3719,7 +4252,7 @@ "DCN": "Dentacoin", "DCNT": "Decanect", "DCNTR": "Decentrahub Coin", - "DCOIN": "Crypto Delivery", + "DCOIN": "Dogcoin", "DCR": "Decred", "DCRE": "DeltaCredits", "DCRN": "Decred-Next", @@ -3738,6 +4271,7 @@ "DDIM": "DuckDaoDime", "DDK": "DDKoin", "DDL": "Donocle", + "DDM": "DDM Deutsche Mark", "DDMT": "Dongdaemun Token", "DDN": "Den Domains", "DDOS": "disBalancer", @@ -3755,6 +4289,7 @@ "DEBT": "The Debt Box", "DEC": "Decentr", "DECENTRALG": "Decentral Games ICE", + "DECENTRALIZED": "DECENTRALIZED", "DECHAT": "Dechat", "DECI": "Maximus DECI", "DECL": "Decimal token", @@ -3763,15 +4298,27 @@ "DEDE": "Dede", "DEDI": "Dedium", "DEDPRZ": "DEDPRZ", + "DEE": "Deep AI", "DEEBO": "Deebo the Bear", "DEED": "Deed (Ordinals)", "DEEM": "iShares MSCI Emerging Markets ETF Defichain", "DEEP": "DeepBook Protocol", "DEEPCLOUD": "DeepCloud AI", "DEEPG": "Deep Gold", + "DEEPS": "DeepSeek AI", + "DEEPSE": "DeepSeek AI Assistant", + "DEEPSEARCH": "Grok 3 DeepSearch", + "DEEPSEE": "DeepSeek AI", + "DEEPSEEK": "Global DePIN Chain", + "DEEPSEEKAI": "DeepSeek AI Agent", + "DEEPSEEKR1": "DeepSeek R1", "DEER": "ToxicDeer Finance", + "DEERSEIZED": "Deer Seized by US Government", + "DEESSE": "Deesse", "DEEX": "DEEX", "DEEZ": "DEEZ NUTS", + "DEFAI": "DEFAI", + "DEFAIDAO": "DeFAI", "DEFC": "Defi Coin", "DEFEND": "Blockdefend AI", "DEFI": "DeFi", @@ -3792,7 +4339,10 @@ "DEFY": "DEFY", "DEG": "Degis", "DEGA": "Dega", + "DEGATE": "DeGate", + "DEGE": "DegeCoinc", "DEGEN": "Degen", + "DEGENAI": "Degen Spartan AI", "DEGENR": "DegenReborn", "DEGO": "Dego Finance", "DEGOD": "degod", @@ -3802,6 +4352,8 @@ "DEI": "Deimos", "DEK": "DekBox", "DEL": "Decimal", + "DELABS": "Delabs Games", + "DELAY": "DegenLayer", "DELCHAIN": "DelChain", "DELFI": "DeltaFi", "DELI": "NFTDeli", @@ -3814,13 +4366,13 @@ "DEMI": "DeMi", "DEMIR": "Adana Demirspor Token", "DEMOS": "DEMOS", + "DENARIUS": "Denarius", "DENT": "Dent", "DENTX": "DENTNet", "DEO": "Demeter", "DEOD": "Decentrawood", "DEOR": "Decentralized Oracle", "DEP": "DEAPCOIN", - "DEPA": "Department Of Government Efficiency", "DEPINU": "Depression Inu", "DEPO": "Depo", "DEPTH": "Depth Token", @@ -3831,7 +4383,8 @@ "DERO": "Dero", "DERP": "Derp", "DES": "DeSpace Protocol", - "DESCI": "DeSci Meme", + "DESCI": "SUI Desci Agents", + "DESCIMEME": "DeSci Meme", "DESI": "Desico", "DESO": "Decentralized Social", "DESTINY": "Destiny", @@ -3842,9 +4395,11 @@ "DETH": "DarkEther", "DETO": "Delta Exchange", "DEUR": "DigiEuro", + "DEURO": "DecentralizedEURO", "DEUS": "DEUS Finance", "DEUSD": "Elixir deUSD", "DEV": "Deviant Coin", + "DEVAI": "DEV AI", "DEVCOIN": "DevCoin", "DEVE": "Develocity Finance", "DEVI": "DEVITA", @@ -3853,9 +4408,11 @@ "DEVVE": "Devve", "DEVX": "Developeo", "DEX": "DEX", + "DEX223": "DEX223", "DEXA": "DEXA COIN", "DEXC": "DexCoyote Legends", "DEXE": "DeXe", + "DEXEV1": "DeXe v1", "DEXG": "Dextoken Governance", "DEXIO": "Dexioprotocol", "DEXM": "Dexmex", @@ -3871,6 +4428,7 @@ "DFBT": "DentalFix", "DFC": "DeFinder Capital", "DFD": "DefiDollar DAO", + "DFDVX": "DFDV xStock", "DFG": "Defigram", "DFGL": "DeFi Gold", "DFH": "DeFiHorse", @@ -3887,6 +4445,8 @@ "DFSOCIAL": "DefiSocial (OLD)", "DFSPORTS": "Digital Fantasy Sports", "DFT": "DigiFinexToken", + "DFTV1": "DigiFinexToken v1", + "DFUN": "DashFun Coin", "DFX": "DFX Finance", "DFY": "Defi For You", "DFYN": "Dfyn Network", @@ -3914,12 +4474,14 @@ "DGPT": "DigiPulse", "DGTA": "Digitra.com Token", "DGTX": "Digitex Token", + "DGV1": "Decentral Games v1", "DGVC": "DegenVC", "DGX": "Digix Gold token", "DHLT": "DeHealth", "DHN": "Dohrnii", "DHP": "dHealth", "DHR": "DeHR Network", + "DHRX": "Danaher xStock", "DHS": "Dirham Crypto", "DHT": "dHedge DAO", "DHV": "DeHive", @@ -3927,8 +4489,10 @@ "DIA": "DIA", "DIAB": "Diablo IV Solana", "DIABLO": "Diablo IV", - "DIAM": "Diamond", + "DIAM": "DIAM", "DIAMND": "Projekt Diamond", + "DIAMO": "Diamond Launch", + "DIAMON": "Diamond", "DIAMOND": "Diamond Coin", "DIAMONDINU": "Diamond", "DIBBLE": "Dibbles", @@ -3938,6 +4502,7 @@ "DICEM": "DICE Money", "DICETRX": "TRONbetDice", "DICK": "adDICKted", + "DICKBUTT": "Dickbutt", "DICKCOIN": "DickCoin", "DID": "Didcoin", "DIDDY": "DIDDY", @@ -3952,12 +4517,15 @@ "DIGAU": "Dignity Gold", "DIGEX": "Digex", "DIGG": "DIGG", - "DIGI": "Digiverse", + "DIGGAI": "DIGGER AI", + "DIGI": "Digicoin", "DIGIC": "DigiCube", "DIGIF": "DigiFel", + "DIGIMON": "Digimon", "DIGIT": "Digital Asset Rights Token", "DIGITAL": "Digital Reserve Currency", "DIGITS": "Digits DAO", + "DIGIV": "Digiverse", "DIGNITY": "Dignity", "DIGS": "Diggits", "DIK": "DikDok", @@ -3968,13 +4536,17 @@ "DIM": "DIMCOIN", "DIME": "DimeCoin", "DIMO": "DIMO", - "DIN": "Dinero", + "DIN": "DIN", + "DINE": "Dinero", + "DINER": "TESLA DINER", "DINERO": "Dinero", "DINEROBET": "Dinerobet", "DINGER": "Dinger Token", "DINGO": "Dingocoin", - "DINO": "DinoSwap", + "DINNER": "Trump Dinner", + "DINO": "DinoLFG", "DINOS": "Dinosaur Inu", + "DINOSWAP": "DinoSwap", "DINT": "DinarTether", "DINU": "Dogey-Inu", "DINW": "Dinowars", @@ -3989,6 +4561,7 @@ "DISK": "Dark Lisk", "DISPEPE": "Disabled Pepe", "DISTR": "Distributed Autonomous Organization", + "DISTRIBUTE": "DISTRIBUTE", "DIT": "Ditcoin", "DITH": "Dither AI", "DIVA": "DIVA Protocol", @@ -4000,6 +4573,7 @@ "DIYAR": "Diyarbekirspor Token", "DJED": "Djed", "DJI": "Doge Jones Industrial Average", + "DJI6930": "DOWGE", "DJT": "Save America", "DK": "Dominant Kong", "DKA": "dKargo", @@ -4008,13 +4582,14 @@ "DKEY": "DKEY Bank", "DKKT": "DKK Token", "DKNIGHT": "Dark Knight", + "DKP": "Dragginz", "DKS": "DarkShield", "DKT": "Duelist King", "DKUMA": "KumaDex Token", "DLA": "Dolla", "DLANCE": "DeeLance", "DLB": "DiemLibre", - "DLC": "Diamond Launch", + "DLC": "DeepLink", "DLCBTC": "DLC.Link", "DLISK": "Dlisk", "DLLR": "Sovryn Dollar", @@ -4033,7 +4608,7 @@ "DMAGA": "Dark MAGA", "DMAIL": "DMAIL Network", "DMAR": "DMarket", - "DMC": "Dream21", + "DMC": "DeLorean", "DMCC": "DiscoverFeed", "DMCH": "DARMA Cash", "DMCK": "Diamond Castle", @@ -4045,6 +4620,7 @@ "DMLG": "Demole", "DMOD": "Demodyfi Token", "DMOON": "Dollarmoon", + "DMR": "dmr", "DMS": "Documentchain", "DMT": "Dream Machine Token", "DMTC": "Demeter Chain", @@ -4053,6 +4629,7 @@ "DMZ": "DeMon Token", "DN8": "Pldgr", "DNA": "Metaverse", + "DNAPEPE": "DNA PEPE", "DND": "Diamond DND", "DNET": "DeNet", "DNF": "DNFT Protocol", @@ -4062,6 +4639,7 @@ "DNO": "Denaro", "DNODE": "DecentraNode", "DNOTES": "Dnotes", + "DNOW": "DuelNow", "DNS": "BitDNS", "DNT": "district0x", "DNTX": "DNAtix", @@ -4074,6 +4652,7 @@ "DOBBY": "Dobby", "DOBEN": "dark boden", "DOBO": "DogeBonk", + "DOBUY": "Just do buy", "DOC": "Dochain", "DOCAINEURON": "Doc.ai Neuron", "DOCC": "Doc Coin", @@ -4081,6 +4660,7 @@ "DOCK": "Dock.io", "DOCSWAP": "Dex on Crypto", "DOCT": "DocTailor", + "DOCTO": "DoctorX", "DOD": "Day Of Defeat 2.0", "DOD100": "Day of Defeat Mini 100x", "DODI": "DoubleDice", @@ -4103,10 +4683,13 @@ "DOGE1SAT": "DOGE-1SATELLITE", "DOGE2": "Dogecoin 2.0", "DOGE20": "Doge 2.0", + "DOGEAI": "DOGEai", "DOGEB": "DogeBonk", + "DOGEBASE": "Doge Base", "DOGEBNB": "DogeBNB", "DOGEC": "DogeCash", "DOGECAST": "Dogecast", + "DOGECAUCUS": "Doge Caucus", "DOGECEO": "Doge CEO", "DOGECO": "Dogecolony", "DOGECOIN": "Buff Doge Coin", @@ -4115,19 +4698,25 @@ "DOGED": "DogeCoinDark", "DOGEDAO": "DogeDao", "DOGEDASH": "Doge Dash", + "DOGEDI": "Doge Dividends", "DOGEFA": "DOGEFATHER", "DOGEFATHER": "Dogefather", "DOGEFORK": "DogeFork", "DOGEGF": "DogeGF", + "DOGEGOV": "Department Of Government Efficiency (dogegov.com)", "DOGEGROK": "Doge Grok", "DOGEGROKAI": "Doge Of Grok AI", "DOGEI": "Dogei", "DOGEIN": "Doge In Glasses", + "DOGEINU": "Doge Inu", + "DOGEIUS": "DOGEIUS", "DOGEKING": "DogeKing", "DOGELEGION": "DOGE LEGION", "DOGEM": "Doge Matrix", + "DOGEMARS": "DOGE TO MARS", "DOGEMETA": "Dogemetaverse", "DOGEMOB": "DOGEMOB", + "DOGEMOON": "DOGE TO MOON", "DOGENFT": "The Doge NFT", "DOGEP": "Doge Protocol", "DOGEPAY": "Doge Payment", @@ -4137,6 +4726,7 @@ "DOGERA": "Dogera", "DOGES": "Dogeswap", "DOGESWAP": "Dogeswap Token (HECO)", + "DOGETF": "DOGE ETF", "DOGETH": "EtherDoge", "DOGEVERSE": "DogeVerse", "DOGEWHALE": "Dogewhale", @@ -4151,21 +4741,26 @@ "DOGGYCOIN": "DOGGY", "DOGH": "a dog in a hoodie", "DOGI": "dogi", + "DOGIMUS": "Tesla Dog", "DOGIN": "Doginhood", "DOGINC": "dog in cats world", "DOGINME": "doginme", + "DOGINWOTAH": "doginwotah", "DOGIRA": "Dogira", "DOGK": "Dagknight Dog", "DOGLAI": "Doglaikacoin", "DOGMI": "DOGMI", "DOGO": "DogemonGo", + "DOGONB": "Dog on Base", "DOGPAD": "DogPad Finance", + "DOGPU": "DogeGPU", "DOGRMY": "DogeArmy", "DOGS": "Dogs", "DOGSROCK": "Dogs Rock", "DOGSS": "DOGS SOL", "DOGSSO": "DOGS Solana", "DOGSWAG": "DogSwaghat", + "DOGUN": "Dogun", "DOGW": "DOGWIFHOOD", "DOGWIFHAT": "dogwifhat", "DOGWIFSEAL": "dogwifseal", @@ -4179,16 +4774,19 @@ "DOLLAR": "Dollar", "DOLLARCOIN": "DollarCoin", "DOLLUR": "Dollur Go Brrr", + "DOLLY": "DOLLY", + "DOLO": "Dolomite", "DOLPHY": "Dolphy", "DOLZ": "DOLZ", - "DOM": "Ancient Kingdom", + "DOM": "DomusAI", "DOME": "Everdome", "DOMI": "Domi", "DOMO": "Dony Montana", - "DON": "Donnie Finance", + "DON": "TheDonato Token", "DONA": "DONASWAP", "DONAL": "Donald Pump", "DONALD": "DONALD TRUMP", + "DONALDP": "Donald Pump", "DONALDT": "Donald The Trump", "DONATION": "DonationCoin", "DONG": "DongCoin", @@ -4196,11 +4794,14 @@ "DONJR": "Don Jr.", "DONK": "Don-key", "DONKE": "DONKE", + "DONNIEFIN": "Donnie Finance", "DONS": "The Dons", "DONT": "Donald Trump (dont.cash)", "DONU": "Donu", "DONUT": "Donut", "DONUTS": "The Simpsons", + "DOOD": "Doodles", + "DOODI": "Doodipals", "DOODOO": "Doodoo", "DOOGLE": "Doogle", "DOOH": "Bidooh", @@ -4210,9 +4811,11 @@ "DOPE": "Dopamine App", "DOPEC": "DOPE Coin", "DOPECOIN": "DopeCoin", + "DOPEX": "DOPE", "DOPU": "DOPU The Dog with A Purpose", "DOR": "Dorado", "DORA": "Dora Factory", + "DORAEMON": "Doraemon", "DORAV1": "Dora Factory v1", "DORK": "DORK", "DORKL": "DORK LORD", @@ -4232,14 +4835,18 @@ "DOVIS": "Dovish Finance", "DOVU": "DOVU", "DOWS": "Shadows", + "DOYOUR": "Do Your Own Research", "DP": "DigitalPrice", "DPAD": "Dpad Finance", "DPAY": "Devour", + "DPCORE": "DeepCore AI", "DPDBC": "PDBC Defichain", "DPET": "My DeFi Pet", "DPEX": "DPEX", "DPI": "DeFiPulse Index", "DPIE": "DeFiPie", + "DPIN": "DPIN", + "DPINO": "DarkPino", "DPLAT": "zbyte", "DPLN": "DePlan", "DPLTR": "Palantir Tokenized Stock Defichain", @@ -4252,11 +4859,12 @@ "DPX": "Dopex", "DPY": "Delphy", "DQQQ": "Invesco QQQ Trust Defichain", - "DRA": "DraculaCoin", + "DRA": "Decentralized Retirement Account", "DRAC": "DRAC Network", "DRACE": "DeathRoad", "DRACO": "DT Token", "DRACOO": "DracooMaster", + "DRACULA": "Dracula", "DRAFTC": "Draftcoin", "DRAGGY": "Draggy", "DRAGON": "Dragon", @@ -4264,6 +4872,7 @@ "DRAGONKING": "DragonKing", "DRAGONMA": "Dragon Mainland Shards", "DRAGONX": "DragonX", + "DRAGONZ": "Dragonz Land", "DRAGU": "DRAGU", "DRAGY": "Dragy", "DRAKO": "Drako", @@ -4273,16 +4882,20 @@ "DRBT": "DeFi-Robot", "DRC": "DRC Mobility", "DRCT": "Ally Direct", + "DRDR": "DRDR Token", "DRE": "DoRen", "DREAM": "DREAM", + "DREAM21": "Dream21", "DREAMS": "Dreams Quest", "DREP": "DREP", "DRF": "Drife", "DRG": "Dragon Coin", "DRGN": "Dragonchain", "DRIFT": "Drift protocol", - "DRINK": "DrinkChain", - "DRIP": "Drip Network", + "DRINK": "DRINK", + "DRINKCHAIN": "DrinkChain", + "DRIP": "Metadrip", + "DRIPNET": "Drip Network", "DRIV": "DRIVEZ", "DRIVECRYPTO": "Drive Crypto", "DRKC": "DarkCash", @@ -4291,13 +4904,18 @@ "DRM8": "Dream8Coin", "DROGGY": "Droggy", "DRONE": "Drone Coin", - "DROP": "Dropil", + "DROP": "DROP", + "DROPIL": "Dropil", "DROPS": "Drops", "DROVERS": "Drover Inu", "DRP": "DCORP", "DRPU": "DRP Utility", + "DRPXBT": "Hunter by Virtuals", "DRS": "Digital Rupees", "DRT": "DomRaider", + "DRUGS": "Big Pharmai", + "DRV": "Derive", + "DRX": "DRX Token", "DRXNE": "Droxne", "DRZ": "Droidz", "DS": "DeStorage", @@ -4311,6 +4929,7 @@ "DSG": "Dinosaureggs", "DSH": "Dashcoin", "DSHARE": "Dibs Share", + "DSHELL": "diamondshell", "DSHIB": "DOLLAR SHIBA INU", "DSK": "Darüşşafaka Spor Kulübü Token", "DSLA": "DSLA Protocol", @@ -4324,7 +4943,7 @@ "DSTR": "Dynamic Supply Tracker", "DSUN": "DsunDAO", "DSYNC": "Destra Network", - "DT": "DarkToken", + "DT": "Drift Zone", "DT1": "Dollar Token 1", "DTA": "Data", "DTB": "Databits", @@ -4355,13 +4974,16 @@ "DUBI": "Decentralized Universal Basic Income", "DUBX": "DUBXCOIN", "DUC": "DucatusCoin", + "DUCAT": "Ducat", "DUCATO": "Ducato Protocol Token", "DUCK": "Unit Protocol New", + "DUCKAI": "Duck AI", "DUCKC": "DuckCoin", "DUCKD": "DuckDuckCoin", "DUCKER": "Ducker", "DUCKIES": "Yellow Duckies", "DUCKO": "Duck Off Coin", + "DUCKV1": "COL", "DUCKY": "Ducky Duck", "DUCX": "DucatusX", "DUDE": "DuDe", @@ -4372,6 +4994,7 @@ "DUET": "Duet Protocol", "DUG": "DUG", "DUGE": "DUGE", + "DUK": "DUKE COIN", "DUK+": "Dukascoin", "DUKE": "Duke Inu", "DUKO": "DUKO", @@ -4379,13 +5002,16 @@ "DUN": "Dune", "DUNG": "Scarab Tools", "DUO": "ParallelCoin", + "DUOLINGOAI": "DUOLINGO AI", "DUOT": "DUO Network", + "DUPE": "Dupe", "DUREV": "Povel Durev", "DUROV": "FREE DUROV", "DURTH": "iShares MSCI World ETF Tokenized Stock Defichain", "DUSD": "Decentralized USD", "DUSK": "Dusk Network", "DUST": "DUST Protocol", + "DUSTY": "Dusty", "DUX": "DuxCoin", "DUZCE": "Duzce Token", "DV": "Dreamverse", @@ -4406,6 +5032,7 @@ "DVT": "DeVault", "DVTC": "DivotyCoin", "DVX": "Derivex", + "DWAIN": "DWAIN", "DWARFY": "Dwarfy", "DWARS": "Dynasty Wars", "DWC": "Digital Wallet", @@ -4434,6 +5061,7 @@ "DYAD": "Dyad Stable", "DYC": "Dycoin", "DYDX": "dYdX", + "DYDXV1": "dYdX v1", "DYM": "Dymension", "DYN": "Dynamic", "DYNA": "Dynamix", @@ -4450,6 +5078,7 @@ "DYST": "Dystopia", "DYT": "DoYourTip", "DYZILLA": "DYZilla", + "DZA": "DZA", "DZAR": "Digital Rand", "DZCC": "DZCC", "DZDD": "DZD", @@ -4460,20 +5089,26 @@ "E1INCH": "1inch (Energi Bridge)", "E21": "E21 Coin", "E2C": "Electronic Energy Coin", + "E4C": "E4C", "E8": "Energy8", "EA": "EagleCoin", "EAC": "Education Assessment Cult", "EADX": "EADX Token", + "EAFIN": "EAFIN", "EAG": "Emerging Assets Group", "EAGLE": "Eagle Token", "EAGS": "EagsCoin", "EAI": "Eagle AI", "EARLY": "Early Risers", "EARLYF": "EarlyFans", - "EARN": "EarnGuild", + "EARN": "Earn Network", + "EARNB": "Earn BTC", + "EARNGUILD": "EarnGuild", + "EARNM": "EARNM", "EARTH": "Earth Token", "EARTHCOIN": "EarthCoin", "EASYF": "EasyFeedback", + "EASYMINE": "EasyMine", "EAT": "EDGE Activity Token", "EATH": "Eartherium", "EAURIC": "Eauric", @@ -4486,6 +5121,7 @@ "EBEN": "Green Ben", "EBET": "EthBet", "EBIT": "eBit", + "EBITCOIN": "eBitcoin", "EBK": "Ebakus", "EBOX": "Ethbox Token", "EBS": "EbolaShare", @@ -4494,7 +5130,7 @@ "EBSO": "eBlockStock", "EBST": "eBoost", "EBT": "ELON BUYS TWITTER", - "EBTC": "eBitcoin", + "EBTC": "Ether.fi Staked BTC", "EBULL": "ETHEREUM IS GOOD", "EBYT": "EarthByt", "EBZ": "Ebitz", @@ -4507,13 +5143,15 @@ "ECET": "Evercraft Ecotechnologies", "ECG": "EcoSmart", "ECH": "EthereCash", + "ECHO": "Echo", "ECHOBOT": "ECHO BOT", "ECHOD": "EchoDEX", "ECHT": "e-Chat", "ECI": "Euro Cup Inu", "ECL": "ECLAT", "ECLD": "Ethernity Cloud", - "ECLIP": "Eclipse", + "ECLIP": "Eclipse Fi", + "ECLIPSE": "Eclipse", "ECO": "Ormeus Ecosystem", "ECOB": "EcoBit", "ECOC": "ECOcoin", @@ -4521,6 +5159,7 @@ "ECOFI": "EcoFi", "ECOIN": "Ecoin", "ECOM": "Omnitude", + "ECOR": "Ecorpay token", "ECOREAL": "Ecoreal Estate", "ECOTERRA": "ecoterra", "ECOX": "ECOx", @@ -4542,7 +5181,9 @@ "EDEXA": "edeXa Security Token", "EDFI": "EdFi", "EDG": "Edgeless", - "EDGE": "EDGE", + "EDGE": "Definitive", + "EDGEN": "LayerEdge", + "EDGENET": "EDGE", "EDGESOL": "Edgevana Staked SOL", "EDGEW": "Edgeware", "EDGT": "Edgecoin", @@ -4561,12 +5202,16 @@ "EDUCOIN": "EduCoin", "EDUM": "EDUM", "EDUX": "Edufex", + "EDWIN": "Edwin", "EDX": "Equilibrium", + "EEFS": "Eefs", + "EEG": "EEG Token", "EER": "Ethereum eRush", "EETH": "ether fi", "EFBAI": "EuroFootball AI", "EFC": "Everton Fan Token", "EFCR": "EFLANCER", + "EFFECT": "Effect AI", "EFFT": "Effort Economy ", "EFI": "Efinity", "EFIL": "Ethereum Wrapped Filecoin", @@ -4575,6 +5220,7 @@ "EFR": "End Federal Reserve", "EFT": "ETH Fan Token Ecosystem", "EFX": "The Effect.ai", + "EFYT": "Ergo", "EG": "EG Token", "EGAME": "Every Game", "EGAS": "ETHGAS", @@ -4591,8 +5237,10 @@ "EGGY": "EGGY", "EGI": "eGame", "EGL": "The Eagle Of Truth", + "EGL1": "EGL1", "EGLD": "eGold", - "EGO": "EGOcoin", + "EGO": "Paysenger EGO", + "EGOCOIN": "EGOcoin", "EGOD": "EgodCoin", "EGOLD": "EGOLD", "EGON": "EgonCoin", @@ -4607,6 +5255,7 @@ "EHRT": "Eight Hours Token", "EIFI": "EIFI FINANCE", "EIGEN": "EigenLayer", + "EIGENP": "Eigenpie", "EIM": "Expert Infra", "EIQT": "IQ Prediction", "EJAC": "EJA Coin", @@ -4632,6 +5281,7 @@ "ELCASH": "Electric Cash", "ELD": "Electrum Dark", "ELDA": "Eldarune", + "ELDE": "Elderglade", "ELE": "Elementrem", "ELEC": "Electrify.Asia", "ELECTRON": "Electron (Atomicals)", @@ -4649,7 +5299,8 @@ "ELI": "GoCrypto", "ELIC": "Elicoin", "ELITE": "EthereumLite", - "ELIX": "Elixir", + "ELIX": "Elixir Games", + "ELIXI": "Elixir", "ELIXIR": "Starchi", "ELIZ": "Eliza (ai16zeliza)", "ELIZA": "Eliza (elizawakesup.ai)", @@ -4665,6 +5316,7 @@ "ELON": "Dogelon Mars", "ELON2024": "ELON 2024(BSC)", "ELON404": "Elon404", + "ELON4AFD": "Elon for AfD", "ELONCAT": "ELON CAT COIN", "ELOND": "ELON DOGE", "ELONDOGE": "ELON DOGE", @@ -4680,6 +5332,7 @@ "ELONMU": "Elon Musk", "ELONONE": "AstroElon", "ELONPEPE": "Elon Pepe Robot", + "ELONRWA": "ElonRWA", "ELONTRUMP": "ELON TRUMP", "ELP": "Ellerium", "ELS": "Ethlas", @@ -4690,9 +5343,12 @@ "ELU": "Elumia", "ELUSKMON": "Elusk Mon", "ELV": "Elvantis", + "ELVIS": "ELVIS", "ELVN": "11Minutes", - "ELX": "Energy Ledger", - "ELY": "Elysian", + "ELX": "Elixir Network", + "ELY": "Elysium", + "ELYS": "Elys Network", + "ELYSIAN": "Elysian", "ELYSIUM": "Elysium", "EM": "Eminer", "EMAID": "MaidSafeCoin", @@ -4701,7 +5357,8 @@ "EMATIC": "Wrapped Polygon (Energi Bridge)", "EMAX": "EthereumMax", "EMB": "Overline Emblem", - "EMBER": "EmberCoin", + "EMBER": "Ember", + "EMBERCOIN": "EmberCoin", "EMBR": "Embr", "EMC": "Edge Matrix Computing", "EMC2": "Einsteinium", @@ -4724,10 +5381,11 @@ "EMR": "Emorya Finance", "EMRLD": "The Emerald Company", "EMRX": "Emirex Token", - "EMT": "EasyMine", + "EMT": "EMAIL Token", "EMU": "eMusic", "EMV": "Ethereum Movie Venture", "EMX": "EMX", + "EMYC": "E Money", "ENA": "Ethena", "ENC": "Encores Token", "ENCD": "Encircled", @@ -4741,6 +5399,7 @@ "ENE": "EneCoin", "ENEAR": "Near (Energiswap)", "ENEDEX": "Enedex", + "ENERGYLEDGER": "Energy Ledger", "ENERGYX": "Safe Energy", "ENG": "Enigma", "ENGT": "Engagement Token", @@ -4754,6 +5413,7 @@ "ENQ": "Enecuum", "ENQAI": "enqAI", "ENRG": "EnergyCoin", + "ENRON": "Enron", "ENRX": "Enrex", "ENS": "Ethereum Name Service", "ENT": "Eternity", @@ -4769,6 +5429,7 @@ "ENV": "ENVOY", "ENVIENTA": "Envienta", "ENVION": "Envion", + "ENVOY": "Envoy A.I", "ENX": "ENEX", "EOC": "EveryonesCoin", "EON": "Exscudo", @@ -4783,14 +5444,18 @@ "EOX": "EXTRA ORDINARY", "EPAN": "Paypolitan Token", "EPANUS": "Epanus", + "EPENDLE": "Equilibria Pendle", "EPEP": "Epep", "EPETS": "Etherpets", - "EPIC": "Epic Cash", + "EPIC": "Epic Chain", + "EPICCASH": "Epic Cash", "EPIK": "EPIK Token", "EPIKO": "Epiko", "EPIX": "Byepix", "EPK": "EpiK Protocol", "EPS": "Ellipsis (OLD)", + "EPSTAIN": "Jeffrey Epstain", + "EPT": "Balance", "EPTT": "Evident Proof Transaction Token", "EPX": "Ellipsis X", "EPY": "Empyrean", @@ -4811,11 +5476,13 @@ "EQUITOKEN": "EQUI Token", "EQX": "EQIFi", "EQZ": "Equalizer", - "ERA": "ETHA", + "ERA": "Caldera", "ERA7": "Era Token", + "ERASWAP": "Era Swap Token", "ERB": "ERBCoin", "ERC": "EuropeCoin", "ERC20": "ERC20", + "ERC20V1": "ERC20 v1", "ERD": "Elrond", "ERE": "Erecoin", "EREAL": "eREAL", @@ -4837,9 +5504,10 @@ "ERW": "ZeLoop Eco Reward", "ERY": "Eryllium", "ERZ": "Erzurumspor Token", - "ES": "Era Swap Token", + "ES": "Eclipse", "ESAI": "Ethscan AI", "ESBC": "ESBC", + "ESCC": "Eos Stable Coin Chain", "ESCE": "Escroco Emerald", "ESCROW": "Cryptegrity DAO", "ESCU": "EYESECU AI", @@ -4850,10 +5518,14 @@ "ESGC": "ESG Chain", "ESH": "Switch", "ESHIB": "Euro Shiba Inu", + "ESIM": "EvoSimGame", + "ESM": "EL SALVADOR MEME", "ESN": "Ethersocial", "ESNC": "Galaxy Arena Metaverse", + "ESOL": "Earn Solana", "ESP": "Espers", "ESPL": "ESPL ARENA", + "ESPORTS": "Yooldo Games", "ESPR": "Espresso Bot", "ESRC": "ESR Coin", "ESS": "Essentia", @@ -4861,6 +5533,7 @@ "ESTATE": "AgentMile", "ESTEE": "Kaga No Fuuka Go Sapporo Kagasou", "ESW": "eSwitch®", + "ESX": "EstateX", "ESZ": "EtherSportz", "ET": "ENDO", "ET4": "Eticket4", @@ -4891,7 +5564,7 @@ "ETHERDELTA": "EtherDelta", "ETHERE": "Ethereal", "ETHEREM": "Etherempires", - "ETHEREUM": "Solana Ethereum Meme", + "ETHEREUMMEME": "Solana Ethereum Meme", "ETHEREUMP": "ETHEREUMPLUS", "ETHERINC": "EtherInc", "ETHERKING": "Ether Kingdoms Token", @@ -4913,6 +5586,7 @@ "ETHPOW": "ETHPoW", "ETHPR": "Ethereum Premium", "ETHPY": "Etherpay", + "ETHR": "Ethereal", "ETHS": "EthereumScrypt", "ETHSHIB": "Eth Shiba", "ETHV": "Ethverse", @@ -4926,6 +5600,7 @@ "ETM": "En-Tan-Mo", "ETN": "Electroneum", "ETNA": "ETNA Network", + "ETNY": "Ethernity", "ETP": "Metaverse", "ETPOS": "EtherPOS", "ETR": "Electric Token", @@ -4957,6 +5632,7 @@ "EUROP": "Europa Coin", "EURQ": "Quantoz EURQ", "EURR": "StablR Euro", + "EURRV1": "StablR Euro v1", "EURS": "STASIS EURS", "EURT": "Euro Tether", "EURTV1": "Euro Tether v1", @@ -4967,8 +5643,10 @@ "EV": "EVAI", "EVA": "Evadore", "EVAI": "EVA Intelligence", + "EVAL": "Chromia's EVAL by Virtuals", "EVAN": "Evanesco Network", "EVAULT": "EthereumVault", + "EVAV1": "Evadore v1", "EVC": "Eventchain", "EVCC": "Eco Value Coin", "EVCOIN": "EverestCoin", @@ -4991,11 +5669,12 @@ "EVIN": "Evin Token", "EVMOS": "Evmos", "EVN": "Evn Token", - "EVO": "EvoVerses", + "EVO": "Devomon", "EVOAI": "EvolveAI", "EVOC": "EVOCPLUS", "EVOL": "EVOL NETWORK", "EVOS": "EVOS", + "EVOVERSES": "EvoVerses", "EVR": "Everus", "EVRICE": "Evrice", "EVRM": "Evrmore", @@ -5033,6 +5712,8 @@ "EXOS": "Exobots", "EXP": "Expanse", "EXPAND": "Gems", + "EXPERIENCE": "Experience Points", + "EXPERT": "EXPERT_MONEY", "EXPO": "Exponential Capital", "EXRD": "Radix", "EXRN": "EXRNchain", @@ -5045,6 +5726,7 @@ "EYE": "MEDIA EYE", "EYES": "Eyes Protocol", "EYETOKEN": "EYE Token", + "EYWA": "EYWA", "EZ": "EasyFi V2", "EZC": "EZCoin", "EZEIGEN": "Restaked EIGEN", @@ -5053,9 +5735,12 @@ "EZM": "EZMarket", "EZPZ": "Eazy Peazy", "EZSOL": "Renzo Restaked SOL", + "EZSWAP": "EZswap Protocol", + "EZSWAPV1": "EZswap Protocol v1", "EZT": "EZToken", "EZY": "EzyStayz", "ElvishMagic": "EMAGIC", + "F": "SynFutures", "F16": "F16Coin", "F1C": "Future1coin", "F2C": "Ftribe Fighters", @@ -5065,21 +5750,27 @@ "F9": "Falcon Nine", "FAB": "FABRK Token", "FABA": "Faba Invest", + "FABIENNE": "Fabienne", "FABRIC": "MetaFabric", "FAC": "Flying Avocado Cat", - "FACE": "FaceDAO", + "FACEDAO": "FaceDAO", "FACETER": "Faceter", "FACT": "Orcfax", "FACTOM": "Factom", "FACTORY": "ChainFactory", "FACTR": "Defactor", + "FACTRPAY": "FactR", "FADO": "FADO Go", + "FAFO": "FAFO", + "FAFOSOL": "Fafo", "FAG": "PoorFag", "FAH": "Falcons", - "FAI": "Fairum", + "FAI": "Freysa AI", "FAIR": "FairCoin", + "FAIR3": "Fair and Free", "FAIRC": "Faireum Token", "FAIRG": "FairGame", + "FAIRUM": "Fairum", "FAKE": "FAKE COIN", "FAKEAI": "DeepFakeAI", "FAKT": "Medifakt", @@ -5096,6 +5787,8 @@ "FANC": "fanC", "FAND": "Fandomdao", "FANG": "FANG Token", + "FANS": "Fantasy Cash", + "FANTOM": "Fantom Maker", "FANV": "FanVerse", "FANX": "FrontFanz", "FANZ": "FanChain", @@ -5109,11 +5802,17 @@ "FARME": "Farmers Only", "FARMING": "Farming Bad", "FARMS": "Farmsent", + "FARTAI": "Fart AI", + "FARTBOY": "Fartboy", "FARTCOIN": "Fartcoin", + "FARTDEV": "Fart Dev", + "FARTIMUS": "Fartimus Prime", + "FARTING": "Farting Unicorn", "FAS": "fast construction coin", "FAST": "Fastswap", "FASTAI": "Fast And Ai", "FASTMOON": "FastMoon", + "FASTUSD": "Sei fastUSD", "FASTV1": "Fastswap v1", "FAT": "Fatcoin", "FATCAKE": "FatCake", @@ -5126,7 +5825,7 @@ "FAYD": "Fayda", "FAYRE": "Fayre", "FAZZ": "FazzCoin", - "FB": "Fenerbahçe Token", + "FB": "Fractal Bitcoin", "FBA": "Firebird Aggregator", "FBB": "FilmBusinessBuster", "FBG": "Fort Block Games", @@ -5143,6 +5842,7 @@ "FCF": "French Connection Finance", "FCH": "Freecash", "FCK": "Find & Check", + "FCK925": "FCK925", "FCL": "Fractal", "FCN": "FantomCoin", "FCO": "Fanatico", @@ -5153,11 +5853,13 @@ "FCS": "CryptoFocus", "FCT": "FirmaChain", "FCTC": "FaucetCoin", + "FCTR": "FactorDAO", "FDC": "Fidance", "FDLS": "FIDELIS", "FDM": "Fandom", "FDO": "Firdaos", "FDR": "French Digital Reserve", + "FDS": "Foodie Squirrel", "FDT": "Frutti Dino", "FDUSD": "First Digital USD", "FDX": "fidentiaX", @@ -5165,17 +5867,18 @@ "FEAR": "Fear", "FEARNOT": "FEAR NOT", "FECES": "FECES", - "FEE": "FEED EVERY GORILLA", "FEED": "Feeder Finance", "FEENIXV2": "ProjectFeenixv2", "FEES": "UNIFEES", "FEFE": "Fefe", - "FEG": "FEG Token", + "FEG": "FEED EVERY GORILLA", "FEGV1": "FEG Token v1", + "FEGV2": "FEG Token", "FEI": "Fei Protocol", "FELIX": "FelixCoin", "FELIX2": "Felix 2.0 ETH", "FEN": "First Ever NFT", + "FENE": "Fenerbahçe Token", "FENOMY": "Fenomy", "FENTANYL": "Chinese Communist Dragon", "FER": "Ferro", @@ -5187,6 +5890,7 @@ "FET": "Artificial Superintelligence Alliance", "FETCH": "Fetch", "FETS": "FE TECH", + "FEUSD": "Felix feUSD", "FEVR": "RealFevr", "FEX": "FEX Token", "FEY": "Feyorra", @@ -5206,10 +5910,12 @@ "FGT": "Flozo Game Token", "FGZ": "Free Game Zone", "FHB": "FHB", + "FHE": "MindNetwork FHE Token", "FHM": "FantOHM", "FI": "Fideum", "FIA": "FIA Protocol", "FIBO": "FibSWAP DEx", + "FIBOS": "FIBOS", "FIBRE": "FIBRE", "FIC": "Filecash", "FID": "Fidira", @@ -5220,10 +5926,11 @@ "FIELD": "Fieldcoin", "FIERO": "Fieres", "FIF": "flokiwifhat", + "FIFA": "FIFA", "FIFTY": "FIFTYONEFIFTY", "FIG": "FlowCom", "FIGH": "FIGHT FIGHT FIGHT", - "FIGHT": "Crypto Fight Club", + "FIGHT": "Fight to MAGA", "FIGHTMAGA": "FIGHT MAGA", "FIGHTPEPE": "FIGHT PEPE", "FIGHTRUMP": "FIGHT TRUMP", @@ -5232,6 +5939,7 @@ "FIL": "FileCoin", "FILDA": "Filda", "FILES": "Solfiles", + "FILEST": "FileStar", "FILL": "Fillit", "FILM": "Filmpass", "FILST": "Filecoin Standard Hashrate Token", @@ -5248,29 +5956,36 @@ "FINK": "FINK", "FINN": "Huckleberry", "FINOM": "Finom FIN Token", + "FINOMNOM": "Finom NOM Token", "FINS": "AutoShark DEX", "FINT": "FintraDao", "FINU": "Formula Inu", + "FINVESTA": "Finvesta", "FIO": "FIO Protocol", "FIONA": "Fiona", "FIONABSC": "Fiona", "FIRA": "Defira", "FIRE": "Matr1x Fire", "FIRECOIN": "FireCoin", + "FIREP": "Fire Protocol", "FIREW": "Fire Wolf", "FIRO": "Firo", "FIRSTHARE": "FirstHare", "FIRU": "Firulais Finance", "FIS": "Stafi", "FISH": "Polycat Finance", + "FISH2": "FISH2", "FISHK": "Fishkoin", + "FISHW": "Fishwar", "FIST": "Fistbump", "FISTBUMP": "FistBump", "FIT": "Financial Investment Token", "FITC": "Fitcoin", + "FITCOIN": "FITCOIN", "FITFI": "Step App", "FITT": "Fitmint", "FIU": "beFITTER", + "FIUSD": "Sygnum FIUSD Liquidity Fund", "FIWA": "Defi Warrior", "FIX00": "FIX00", "FJB": "Freedom. Jobs. Business.", @@ -5295,6 +6010,7 @@ "FLAS": "Flas Exchange Token", "FLASH": "Flashstake", "FLASHC": "FLASH coin", + "FLASHT": "FlashToken", "FLAVIA": "Flavia Is Online", "FLAY": "Flayer", "FLC": "FlowChainCoin", @@ -5324,7 +6040,10 @@ "FLO": "Flo", "FLOAT": "Float Protocol", "FLOCHI": "Flochi", + "FLOCK": "FLock.io", "FLOCKA": "Waka Flocka", + "FLOCKE": "Flockerz", + "FLOCO": "flocoin", "FLOKA": "FLOKA", "FLOKEI": "FLOKEI", "FLOKI": "Floki Inu", @@ -5335,14 +6054,20 @@ "FLOKINY": "Floki New Year", "FLOKIPEPE": "FlokiPepe", "FLOKITA": "FLOKITA", + "FLOKIV1": "Floki v1", + "FLOKIV2": "Floki v2", + "FLOKIV3": "Floki v3", "FLOKIX": "FLOKI X", "FLOOF": "FLOOF", "FLOOR": "FloorDAO", "FLOP": "Big Floppa", + "FLOPPA": "Floppa Cat", "FLORK": "FLORK BNB", "FLORKY": "Florky", "FLOSHIDO": "FLOSHIDO INU", "FLOT": "FireLotto", + "FLOTUS47": "Melania Trump", + "FLOURI": "Flourishing AI", "FLOVI": "Flovi inu", "FLOVM": "FLOV MARKET", "FLOW": "Flow", @@ -5354,12 +6079,14 @@ "FLRBRG": "Floor Cheese Burger", "FLRS": "Flourish Coin", "FLS": "Flits", + "FLSH": "FlashWash", "FLT": "Fluence", "FLUFFI": "Fluffington", "FLUFFY": "FLUFFY", "FLUFFYS": "Fluffys", "FLUI": "Fluidity", "FLUID": "Fluid", + "FLUIDTRADE": "Fluid", "FLURRY": "Flurry Finance", "FLUT": "Flute", "FLUTTERCOIN": "FlutterCoin", @@ -5382,6 +6109,7 @@ "FML": "FormulA", "FMT": "Finminity", "FN": "Filenet", + "FNA": "FinTech AI", "FNB": "FNB protocol", "FNC": "Fancy Games", "FNCT": "Financie Token", @@ -5400,10 +6128,11 @@ "FNX": "FinNexus", "FNXAI": "Finanx AI", "FNZ": "Fanzee", - "FO": "FIBOS", + "FO": "Official FO", "FOA": "Fragments of arker", "FOAM": "Foam", "FOC": "TheForce Trade", + "FOCAI": "focai.fun", "FOCV": "FOCV", "FODL": "Fodl Finance", "FOF": "Future Of Fintech", @@ -5415,8 +6144,11 @@ "FOIN": "Foin", "FOL": "Folder Protocol", "FOLD": "Manifold Finance", + "FOLGORYUSD": "FolgoryUSD", + "FOLGORYUSDV1": "FolgoryUSD", "FOLO": "Alpha Impact", - "FOMO": "FOMO BULL CLUB", + "FOM": "FOMO BULL CLUB", + "FOMO": "Fomo", "FOMON": "FOMO Network", "FOMOSOL": "FOMOSolana", "FON": "INOFI", @@ -5443,20 +6175,24 @@ "FOREX": "handle.fi", "FOREXCOIN": "FOREXCOIN", "FORK": "Gastro Advisor Token", - "FORM": "Formation FI", + "FORM": "Four", + "FORMATION": "Formation FI", + "FORMNET": "Form", "FORS": "Forus", "FORT": "Forta", "FORTH": "Ampleforth Governance Token", "FORTHB": "ForthBox", + "FORTKNOX": "Fort Knox", "FORTUNA": "Fortuna", "FORTUNE": "Fortune", "FORWARD": "Forward Protocol", "FOTA": "Fight Of The Ages", "FOTO": "Unique Photo", "FOTTIE": "Fottie", + "FOU": "Four", "FOUND": "ccFound", "FOUNTAIN": "Fountain", - "FOUR": "4THPILLAR TECHNOLOGIES", + "FOUR": "4", "FOX": "ShapeShift FOX Token", "FOXAI": "FOXAI", "FOXD": "Foxdcoin", @@ -5469,17 +6205,21 @@ "FOXV2": "FoxFinanceV2", "FOXXY": "FOXXY", "FOXY": "Foxy", - "FP": "Fren Pet", + "FP": "Forgotten Playland", "FPAD": "FantomPAD", "FPC": "Futurepia", "FPEPE": "Based Father Pepe", "FPFT": "Peruvian National Football Team Fan Token", "FPI": "Frax Price Index", + "FPIBANK": "FPIBANK", "FPIS": "Frax Price Index Share", + "FPS": "WEB3WAR Token", "FQS": "FQSwap V2", "FR": "Freedom Reserve", "FRA": "Findora", "FRAC": "FractalCoin", + "FRAG": "Fragmetric", + "FRANK": "Frank", "FRATT": "Frogg and Ratt", "FRAX": "Frax", "FRAZ": "FrazCoin", @@ -5491,11 +6231,13 @@ "FREAK": "Freakoff", "FREC": "Freyrchain", "FRECNX": "FreldoCoinX", - "FRED": "FREDEnergy", + "FRED": "First Convicted Raccon Fred", "FREDDY": "FREDDY", + "FREDE": "FREDEnergy", "FREE": "FREE coin", "FREED": "FreedomCoin", "FREEDO": "Freedom", + "FREEDOG": "Freedogs", "FREEDOM": "Freedom Protocol Token", "FREELA": "DecentralFree", "FREEPAVEL": "Free Pavel", @@ -5503,13 +6245,17 @@ "FREET": "FreeTrump", "FREL": "Freela", "FREN": "FREN", + "FRENC": "Frencoin", "FRENCH": "French On Base", + "FRENPET": "Fren Pet", "FRENS": "Farmer Friends", "FRESCO": "Fresco", "FRF": "France REV Finance", + "FRGB": "Pepe's Frogbar", "FRGST": "Froggies Token", "FRGX": "FRGX", - "FRIC": "Frictionless", + "FRIC": "Fric", + "FRICTION": "Frictionless", "FRIEND": "Friend.tech", "FRIES": "Soltato FRIES", "FRIN": "Fringe Finance", @@ -5519,15 +6265,18 @@ "FRM": "Ferrum Network", "FRN": "Francs", "FRNT": "Final Frontier", + "FROC": "Based Froc", "FROG": "FrogSwap", "FROGB": "Frog Bsc", "FROGCEO": "Frog Ceo", "FROGE": "Froge Finance", "FROGEX": "FrogeX", + "FROGGER": "FROGGER", "FROGGY": "Froggy", "FROGLIC": "Pink Hood Froglicker", "FROGO": "Frogo", "FROK": "Frok.ai", + "FROKAI": "FrokAI", "FRONK": "Fronk", "FRONT": "Frontier", "FROP": "Popo The Frog", @@ -5545,6 +6294,7 @@ "FRV": "Fitrova", "FRWC": "Frankywillcoin", "FRXETH": "Frax Ether", + "FRXUSD": "Frax USD", "FRZ": "Frozy Inu", "FRZSS": "Frz Solar System", "FRZSSCOIN": "FRZ Solar System Coin", @@ -5559,6 +6309,7 @@ "FSO": "FSociety", "FST": "Futureswap", "FSTC": "FastCoin", + "FSTR": "Fourth Star", "FSW": "Falconswap", "FT": "Fracton Protocol", "FTB": "Fit&Beat", @@ -5575,7 +6326,7 @@ "FTO": "FuturoCoin", "FTON": "Fanton", "FTP": "FuturePoints", - "FTR": "FactR", + "FTR": "Fautor", "FTRB": "Faith Tribe", "FTRC": "FutureCoin", "FTS": "Fortress Lending", @@ -5586,18 +6337,23 @@ "FTVT": "FashionTV Token", "FTW": "FutureWorks", "FTX": "FintruX", + "FTXAI": "FTX AI Agent", "FTXT": "FUTURAX", "FU": "FU Money", "FUBAO": "FUBAO", "FUCK": "Fuck Token", - "FUD": "FUD.finance", - "FUEL": "Jetfuel Finance", + "FUCKTRUMP": "FUCK TRUMP", + "FUD": "Fud the Pug", + "FUDFINANCE": "FUD.finance", + "FUEGO": "FUEGO", + "FUEL": "Fuel Network", "FUELX": "Fuel", "FUFU": "Fufu Token", "FUG": "FUG", "FUJIN": "Fujinto", "FUKU": "FUKU-KUN", "FUL": "Fulcrom Finance", + "FULLSEND": "Fullsend Community Coin", "FUMO": "Alien Milady Fumo", "FUN": "FUN Token", "FUNASSYI": "Funassyi", @@ -5615,6 +6371,7 @@ "FUNK": "Cypherfunks Coin", "FUR": "Furio", "FURIE": "Matt Furie", + "FURM": "Furmula", "FURU": "Furucombo", "FURUKURU": "Furukuru", "FURY": "Engines of Fury", @@ -5623,6 +6380,7 @@ "FUSD": "Fantom USD", "FUSDC": "Fluidity", "FUSE": "Fuse Network Token", + "FUSIO": "FUSIO", "FUSION": "FusionBot", "FUSO": "Fusotao", "FUT": "FuturesAI", @@ -5642,12 +6400,14 @@ "FWT": "Freeway Token", "FWW": "Farmers World Wood", "FX": "Function X", + "FXAKV": "Akiverse Governance", "FXB": "FxBox", "FXC": "Flexacoin", "FXD": "Fathom Dollar", "FXDX": "FXDX", "FXF": "Finxflo", "FXI": "FX1 Sports", + "FXN": "FXN", "FXP": "FXPay", "FXS": "Frax Share", "FXST": "FX Stock Token", @@ -5655,6 +6415,7 @@ "FXUSD": "f(x) Protocol fxUSD", "FXY": "Floxypay", "FYD": "FYDcoin", + "FYDE": "Fyde", "FYDO": "Fly Doge", "FYN": "Affyn", "FYP": "FlypMe", @@ -5664,6 +6425,7 @@ "G1X": "GoldFinX", "G3": "GAM3S.GG", "G50": "G50", + "G7": "Game7", "G8C": "ONEG8.ONE", "G999": "G999", "GAC": "Green Art Coin", @@ -5691,14 +6453,18 @@ "GALO": "Clube Atlético Mineiro Fan Token", "GALT": "Galtcoin", "GAM": "Gambit coin", + "GAMA": "GAMA Coin", "GAMB": "GAMB", "GAMBI": "Gambi Fi", "GAMBIT": "Gambit", "GAMBL": "Metagamble", "GAME": "GameBuild", + "GAME5BALL": "Game 5 BALL", "GAMEBUD": "GAMEBUD", + "GAMEBYV": "GAME by Virtuals", "GAMEC": "Game", "GAMECO": "Game.com", + "GAMECOIN": "Game Coin", "GAMECRED": "GameCredits", "GAMEF": "Game Fantasy Token", "GAMEFI": "GameFi Token", @@ -5710,8 +6476,10 @@ "GAMEST": "GameStop Coin", "GAMESTARS": "Game Stars", "GAMESTO": "GameStop", + "GAMESTOP": "GameStop", "GAMESTUMP": "GAMESTUMP", "GAMET": "GAME Token", + "GAMETA": "Gameta", "GAMEX": "GameX", "GAMI": "GAMI World", "GAMIN": "Gaming Stars", @@ -5735,9 +6503,12 @@ "GAS": "Gas", "GASDAO": "Gas DAO", "GASG": "Gasgains", - "GASP": "gAsp", + "GASP": "GASP", + "GASPCOIN": "gAsp", + "GASS": "Gasspas", "GASTRO": "GastroCoin", - "GAT": "GATCOIN", + "GAT": "Gather", + "GATCOIN": "GATCOIN", "GATE": "GATENet", "GATEWAY": "Gateway Protocol", "GATHER": "Gather", @@ -5790,6 +6561,7 @@ "GDCC": "GLOBAL DIGITAL CLUSTER COIN", "GDDY": "Giddy", "GDE": "Golden Eagle", + "GDIGIT": "GoldDigitStandart", "GDL": "GodlyCoin", "GDO": "GroupDao", "GDOG": "GDOG", @@ -5803,9 +6575,10 @@ "GE": "GEchain", "GEA": "Goldea", "GEAR": "Gearbox Protocol", - "GEC": "Geco.one", + "GEC": "Gecko Inu", "GECKO": "Gecko Coin", "GECKY": "Gecky", + "GECO": "GECOIN", "GEEK": "De:Lithe Last Memories", "GEEQ": "Geeq", "GEF": "GemFlow", @@ -5841,12 +6614,14 @@ "GENX": "Genx Token", "GENXNET": "Genesis Network", "GENZ": "GENZ Token", + "GENZAI": "GENZAI", "GEO": "GeoCoin", "GEOD": "GEODNET", "GEODB": "GeoDB", "GEOJ": "Geojam", "GEOL": "GeoLeaf", "GEON": "Geon", + "GEORGE": "GEORGE", "GEP": "Gaia", "GER": "GermanCoin", "GERA": "Gera Coin", @@ -5854,7 +6629,7 @@ "GERO": "GeroWallet", "GES": "Galaxy eSolutions", "GESE": "Gese", - "GET": "Guaranteed Entrance Token", + "GET": "Global Entertainment Token", "GETA": "Getaverse", "GETH": "Guarded Ether", "GETLIT": "LIT", @@ -5868,6 +6643,7 @@ "GFCS": "Global Funeral Care", "GFI": "Goldfinch", "GFLY": "BattleFly", + "GFM": "GoFundMeme", "GFN": "Graphene", "GFOX": "Galaxy Fox", "GFT": "Gifto", @@ -5880,6 +6656,7 @@ "GGC": "Global Game Coin", "GGCM": "Gold Guaranteed Coin", "GGG": "Good Games Guild", + "GGGG": "Good Game Gary Gensler", "GGH": "Green Grass Hopper", "GGM": "Monster Galaxy", "GGMT": "GG MetaGame", @@ -5890,6 +6667,7 @@ "GGT": "Goat Gang", "GGTK": "GGDApp", "GGTKN": "GG Token", + "GGX": "GG3", "GHA": "Ghast", "GHC": "Galaxy Heroes Coin", "GHCV1": "Galaxy Heroes Coin v1", @@ -5898,6 +6676,14 @@ "GHD": "Giftedhands", "GHDV1": "Giftedhands v1", "GHE": "GHETTO PEPE", + "GHHS": "GHHS Healthcare", + "GHI": "Ghibli HeYi", + "GHIB": "GhibliCZ", + "GHIBL": "Ghibli Zao", + "GHIBLI": "Ghiblification", + "GHIBLIAI": "Ghibli AI Agent", + "GHIBLIDOGE": "Ghibli Doge", + "GHIBLIELON": "Ghibli Elon", "GHNY": "Grizzly Honey", "GHO": "GHO", "GHOAD": "GhoadCoin", @@ -5919,8 +6705,10 @@ "GIFT": "GiftNet", "GIG": "GigaCoin", "GIGA": "Gigachad", + "GIGABRAIN": "Gigabrain by virtuals", "GIGACAT": "GIGACAT", "GIGACHAD": "GigaChad", + "GIGAG": "GIGAGEEK", "GIGASWAP": "GigaSwap", "GIGGLE": "Giggle Academy", "GIGS": "Climate101", @@ -5932,8 +6720,10 @@ "GIMMERV1": "Gimmer v1", "GIN": "GINcoin", "GINGER": "GINGER", + "GINI": "Kalp", "GINNAN": "Ginnan The Cat", "GINOA": "Ginoa", + "GINU": "Green Shiba Inu", "GINUX": "Green Shiba Inu", "GINZA": "GINZA NETWORK", "GIO": "Graviocoin", @@ -5944,7 +6734,9 @@ "GITH": "GitHub's Mascot Octocat", "GIV": "Giveth", "GIVE": "GiveCoin", + "GIX": "GoldFinX", "GIZ": "GIZMOcoin", + "GIZA": "Giza", "GIZMO": "GIZMO•IMAGINARY• KITTEN (Runes)", "GJC": "Global Jobcoin", "GKAPPA": "Golden Kappa", @@ -5952,6 +6744,7 @@ "GKI": "GKi", "GL": "Lemmings", "GLA": "Gladius", + "GLASS": "Glass Chain", "GLAX": "BLOCK GALAXY NETWORK", "GLAZE": "Glaze", "GLB": "Golden Ball", @@ -5960,8 +6753,8 @@ "GLD": "Goldario", "GLDGOV": "Gold DAO", "GLDR": "Golder Coin", - "GLDS": "Gdigit", - "GLDX": "Goldex", + "GLDS": "Glades", + "GLDX": "Gold xStock", "GLDY": "Buzzshow", "GLE": "Green Life Energy", "GLEEC": "Gleec Coin", @@ -5972,6 +6765,7 @@ "GLIESE": "GlieseCoin", "GLINK": "Gemlink", "GLINT": "BeamSwap", + "GLIZZY": "GLIZZY", "GLM": "Golem Network Token", "GLMR": "Moonbeam", "GLMV1": "Golem Network Token v1", @@ -5985,8 +6779,9 @@ "GLOWSHA": "GlowShares", "GLQ": "GraphLinq Protocol", "GLR": "Glory Finance", - "GLS": "Glass Chain", + "GLS": "Glacier", "GLT": "GlobalToken", + "GLUE": "Glue", "GLX": "GalaxyCoin", "GLYPH": "GlyphCoin", "GM": "GM", @@ -6004,7 +6799,7 @@ "GMEPEPE": "GAMESTOP PEPE", "GMETHERFRENS": "GM", "GMETRUMP": "GME TRUMP", - "GMEX": "Game Coin", + "GMEX": "Gamestop xStock", "GMFAM": "GMFAM", "GMFI": "Golden Magfi", "GMI": "GamiFi", @@ -6015,6 +6810,7 @@ "GMNT": "Gmining", "GMPD": "GamesPad", "GMR": "GAMER", + "GMRT": "Gamertag Token", "GMRV1": "GAMER v1", "GMRV2": "GAMER v2", "GMRX": "Gaimin", @@ -6022,11 +6818,12 @@ "GMT": "STEPN", "GMTO": "Game Meteor Coin", "GMTT": "GMT Token", + "GMUBARAK": "Ghibli Mubarak", "GMUSD": "GND Protocol", "GMX": "GMX", "GN": "GN", "GNBT": "Genebank Token", - "GNC": "Greencoin", + "GNC": "Greenchie", "GND": "GND Protoco", "GNFT": "GNFT", "GNG": "GreenGold", @@ -6044,35 +6841,43 @@ "GNX": "Genaro Network", "GNY": "GNY", "GO": "GoChain", + "GO4": "GameonForge", "GOA": "GoaCoin", - "GOAL": "GOAL token", + "GOAL": "TopGoal Token", "GOALBON": "Goal Bonanza", "GOALS": "UnitedFans", + "GOALTOKEN": "GOAL token", "GOAT": "Goatseus Maximus", "GOATAI": "GOAT AI", "GOATCOIN": "Goat", + "GOATS": "GOATS", "GOATSE": "GOATSE", - "GOB": "Goons of Balatroon", + "GOB": "gob", "GOC": "GoCrypto", "GOCHU": "Gochujangcoin", "GOD": "Bitcoin God", + "GODC": "Godcoin", "GODCAT": "GodcatExplodingKittens", "GODE": "Gode Chain", "GODEX": "GUARD OF DECENT", - "GODL": "GODL", + "GODL": "RoOLZ", + "GODLAPP": "GODL", "GODS": "Gods Unchained", "GODZ": "Cryptogodz", "GOETH": "Algomint", "GOF": "Golff", "GOFF": "Gift Off Token", + "GOFINDXR": "Gofind XR", "GOFX": "GooseFX", "GOG": "Guild of Guardians", "GOGLZ": "GOGGLES", "GOGO": "GOGO Finance", "GOGU": "GOGU Coin", + "GOHOME": "GOHOME", "GOIN": "GOinfluencer", "GOJOCOIN": "Gojo Coin", - "GOKU": "Goku", + "GOKU": "Goku Super Saiyan", + "GOKUINU": "Goku (gokuinu.io)", "GOL": "GogolCoin", "GOLC": "GOLCOIN", "GOLD": "CyberDragon Gold", @@ -6080,7 +6885,9 @@ "GOLDCOINETH": "Gold", "GOLDE": "GOLDEN AGE", "GOLDEN": "Golden Inu", + "GOLDENC": "GoldenCat", "GOLDENG": "Golden Goose", + "GOLDEX": "Goldex", "GOLDF": "Gold Fever", "GOLDMIN": "GoldMiner", "GOLDN": "GoLondon", @@ -6111,11 +6918,15 @@ "GOODMO": "Good Morning", "GOOG": "Googly Cat", "GOOGLE": "Deepmind Ai", + "GOOGLX": "Alphabet xStock", "GOOGLY": "Googly Cat", "GOOMPY": "Goompy by Matt Furie", "GOON": "Goonies", + "GOONC": "gooncoin", + "GOONS": "Goons of Balatroon", "GOP": "The Republican Party", "GOPX": "GOPX Token", + "GOR": "Gorbagana", "GORA": "Gora", "GOREC": "GoRecruit", "GORGONZOLA": "Heroes 3 Foundation", @@ -6123,7 +6934,9 @@ "GORILLA": "Gorilla", "GORILLAD": "Gorilla Diamond", "GORILLAINU": "Gorilla Inu", + "GORK": "New XAI gork", "GORPLE": "GorplesCoin", + "GORTH": "Gorth", "GOS": "Gosama", "GOSS": "GOSSIP-Coin", "GOST": "SoulCoin", @@ -6144,13 +6957,16 @@ "GPAWS": "Golden Paws", "GPBP": "Genius Playboy Billionaire Philanthropist", "GPCX": "Good Person Coin", + "GPECTRA": "Pectra Giraffe", "GPKR": "Gold Poker", "GPL": "Gold Pressed Latinum", "GPLX": "Gplx", "GPN": "Gamepass Network", "GPO": "GoldPesa Option", "GPPT": "Pluto Project Coin", - "GPS": "Triffic", + "GPRO": "GoldPro", + "GPS": "GoPlus Security", + "GPSTOKEN": "GPS Token", "GPT": "QnA3.AI", "GPT4O": "GPT-4o", "GPTG": "GPT Guru", @@ -6162,11 +6978,13 @@ "GPX": "GPEX", "GQ": "Galactic Quadrant", "GR": "GROM", + "GRAB": "GRABWAY", "GRACY": "Gracy", "GRAI": "Gravita Protocol", "GRAIL": "Camelot Token", "GRAIN": "Granary", "GRAM": "Gram", + "GRAND": "Grand Theft Ape", "GRANDCOIN": "GrandCoin", "GRANDMA": "Grandma", "GRAPE": "GrapeCoin", @@ -6178,10 +6996,12 @@ "GRBE": "Green Beli", "GRBT": "Grinbit", "GRC": "GreenCoin.AI", + "GRDM": "GridiumAI", "GRE": "GreenCoin", "GREARN": "GrEarn", "GREE": "Green God Candle", "GREEN": "GreenX", + "GREENCOIN": "Greencoin", "GREENH": "Greenheart CBD", "GREENMMT": "Green Mining Movement Token", "GREENPOWER": "GreenPower", @@ -6196,11 +7016,14 @@ "GRID": "Grid+", "GRIDCOIN": "GridCoin", "GRIDZ": "GridZone.io", + "GRIFFAIN": "GRIFFAIN", + "GRIFT": "ORBIT", "GRIM": "GRIMREAPER", "GRIMACE": "Grimace", "GRIMEVO": "Grim EVO", "GRIMEX": "SpaceGrime", "GRIN": "Grin", + "GRIND": "Self Improving", "GRL": "Greelance", "GRLC": "Garlicoin", "GRM": "GridMaster", @@ -6212,6 +7035,8 @@ "GROGGO": "Groggo By Matt Furie", "GROK": "Grok", "GROK2": "GROK 2.0", + "GROK3": "Grok 3", + "GROKAI": "Grok AI Agent", "GROKBANK": "Grok Bank", "GROKBOY": "GrokBoy", "GROKCAT": "Grok Cat", @@ -6228,15 +7053,19 @@ "GROKOLAUS": "GROKolaus", "GROKQUEEN": "Grok Queen", "GROKSORAX": "GROKSORAX", + "GROKVANCE": "GROK VANCE", "GROKX": "GROKX", "GROKXAI": "Grok X Ai", "GRON": "Gron Digital", "GROOOOOK": "Groooook", "GROOVE": "GROOVE", - "GROW": "GrownCoin", + "GROW": "Grow Token", + "GROWAI": "SocialGrowAI", + "GROWNCOIN": "GrownCoin", "GROWTH": "GROWTH DeFi", "GROYPER": "Groyper", "GRP": "Grape", + "GRPH": "Soul Graph", "GRPL": "Golden Ratio Per Liquidity", "GRS": "Groestlcoin", "GRT": "The Graph", @@ -6286,20 +7115,24 @@ "GTIB": "Global Trust Coin", "GTK": "GoToken", "GTN": "GlitzKoin", + "GTO": "Gifto", "GTON": "GTON Capital", "GTR": "Gturbo", "GTRUMP": "Giga Trump", "GTSE": "Global Tourism Sharing Ecology", "GTTM": "Going To The Moon", "GTX": "GALLACTIC", + "GTY": "G-Agents AI", "GUA": "GUA", "GUAC": "Guacamole", + "GUAN": "Guanciale by Virtuals", "GUAP": "Guapcoin", "GUAR": "Guarium", "GUARD": "Guardian", "GUARDAI": "GuardAI", "GUC": "Green Universe Coin", "GUCCI": "GUCCI", + "GUDTEK": "ai16zterminalfartARCzereLLMswarm", "GUE": "GuerillaCoin", "GUESS": "Peerguess", "GUGU": "gugu", @@ -6307,15 +7140,18 @@ "GUILD": "BlockchainSpace", "GUISE": "GUISE", "GULF": "GulfCoin", + "GULL": "GULL", "GUM": "Gourmet Galaxy", "GUMMIES": "GUMMIES", "GUMMY": "GUMMY", "GUMSHOOS": "GUMSHOOS TRUMP", - "GUN": "GunCoin", + "GUN": "GUNZ", + "GUNCOIN": "GunCoin", "GUNS": "GeoFunders", "GUP": "Guppy", "GURL": "Gently Used Girl", "GURU": "Guru Network", + "GUS": "Gus", "GUSD": "Gemini Dollar", "GUSDT": "Global Utility Smart Digital Token", "GUT": "Genesis Universe", @@ -6332,10 +7168,12 @@ "GWGW": "GoWrap", "GWT": "Galaxy War", "GX": "GameX", + "GX3": "GX3ai", "GXA": "Galaxia", "GXC": "GXChain", "GXE": "XENO Governance", "GXT": "Gem Exchange And Trading", + "GYAT": "Gyat Coin", "GYEN": "GYEN", "GYM": "GYM Token", "GYMNET": "Gym Network", @@ -6352,6 +7190,8 @@ "GZT": "Golden Zen Token", "GZX": "GreenZoneX", "Glo Dollar": "USDGLO", + "H": "Humanity", + "H1DR4": "H1DR4 by Virtuals", "H2O": "H2O Dao", "H2ON": "H2O Securities", "H3O": "Hydrominer", @@ -6365,6 +7205,7 @@ "HACHIKO": "Hachiko Inu Token", "HACHIONB": "Hachi On Base", "HACK": "HACK", + "HAEDAL": "Haedal Protocol", "HAGGIS": "New Born Haggis Pygmy Hippo", "HAHA": "Hasaki", "HAI": "Hacken Token", @@ -6374,20 +7215,23 @@ "HAKU": "HakuSwap", "HAL": "Halcyon", "HALF": "0.5X Long Bitcoin Token", + "HALFP": "Half Pizza", "HALFSHIT": "0.5X Long Shitcoin Index Token", "HALLO": "Halloween Coin", "HALLOWEEN": "HALLOWEEN", "HALO": "Halo Coin", "HALOPLATFORM": "Halo Platform", "HAM": "Hamster", + "HAMBURG": "Hamburg Eyes", "HAMI": "Hamachi Finance", "HAMMY": "SAD HAMSTER", "HAMS": "HamsterCoin", - "HAMSTER": "Space Hamster", + "HAMSTER": "Hamster", "HAMSTERB": "HamsterBase", "HAMSTR": "Hamster Coin", "HAN": "HanChain", - "HANA": "Hanacoin", + "HANA": "Hana", + "HANACOIN": "Hanacoin", "HANAETHCTO": "HANA", "HAND": "ShowHand", "HANDY": "Handy", @@ -6397,6 +7241,7 @@ "HAP": "Happy Train", "HAPI": "HAPI", "HAPPY": "Happy Cat", + "HAPPYC": "HappyCoin", "HAR": "Harambe Coin", "HARAM": "HARAM", "HARAMBE": "Harambe on Solana", @@ -6404,18 +7249,22 @@ "HARE": "Hare Token", "HAREPLUS": "Hare Plus", "HAROLD": "Harold", + "HAROLDDUCK": "Harold", "HARPER": "Harper", "HARR": "HARRIS DOGS", "HARRIS": "KAMALA HARRIS", "HARRISV": "Harris V Trump", + "HARRYBOLZ": "Harry Bolz", "HARRYP": "HarryPotterObamaSonic10Inu (ERC20)", + "HARRYPO": "HarryPotterObamaPacMan8Inu", "HART": "HARA", "HASBIK": "Hasbulla", "HASH": "Provenance Blockchain", "HASHAI": "HashAI", + "HASHNET": "HashNet BitEco", "HASHT": "HASH Token", "HASUI": "Haedal", - "HAT": "Hawala.Exchange", + "HAT": "TOP HAT", "HATAY": "Hatayspor Token", "HATCHY": "Hatchyverse", "HATI": "Hati", @@ -6423,6 +7272,7 @@ "HAVOC": "Havoc", "HAVY": "Havy", "HAW": "Hawk Tuah", + "HAWALA": "HAWALA", "HAWK": "Hawksight", "HAWKCITY": "Hawk", "HAWKPTAH": "Hawk Ptah", @@ -6452,6 +7302,7 @@ "HBX": "Hyperbridge", "HBZ": "HBZ Coin", "HC": "HyperCash", + "HCAT": "Hover Cat", "HCC": "HappyCreatorCoin", "HCT": "HurricaneSwap Token", "HCXP": "HCX PAY", @@ -6463,13 +7314,14 @@ "HDRN": "Hedron", "HDRO": "Hydro Protocol", "HDV": "Hydraverse", - "HDX": "HydraDX", + "HDX": "Home Depot xStock", "HE": "Heroes & Empires", "HEA": "Healium", "HEAL": "Etheal", "HEALT": "Healthmedi", "HEART": "Humans", "HEARTBOUT": "HeartBout Pay", + "HEARTN": "Heart Number", "HEARTR": "Heart Rate", "HEAT": "Heat Ledger", "HEAVEN": "Heaven Token", @@ -6484,6 +7336,7 @@ "HEGG": "Hummingbird Egg", "HEGIC": "Hegic", "HEHE": "hehe", + "HEI": "Heima", "HEL": "Hello Puppy", "HELA": "Science Cult Mascot", "HELI": "Helion", @@ -6496,21 +7349,33 @@ "HEM": "Hemera", "HEMAN": "HE-MAN", "HEMULE": "Hemule", + "HENAI": "HenjinAI Token", + "HENG": "HengCoin", + "HENL": "henlo", + "HENLO": "Henlo", + "HENLOV1": "Henlo v1", "HEP": "Health Potion", - "HER": "Hero Node", + "HER": "Her.AI", "HERA": "Hero Arena", + "HERAF": "Hera Finance", "HERB": "HerbCoin", "HERBE": "Herbee", "HERME": "Hermes DAO", "HERMES": "Hermes Protocol", + "HERMIONE": "Hermione", + "HERMY": "Hermy The Stallion", "HERO": "Metahero", "HEROC": "HEROcoin", "HEROES": "Dehero Community Token", + "HEROESAI": "HEROES AI", "HEROESC": "HeroesChained", "HEROI": "Heroic Saga Shiba", + "HERONODE": "Hero Node", + "HEST": "Hash Epoch Sports Token", "HET": "HavEther", "HETA": "HetaChain", "HETH": "Huobi Ethereum", + "HEU": "Heurist AI", "HEWE": "Health & Wealth", "HEX": "HEX", "HEXC": "HexCoin", @@ -6552,6 +7417,7 @@ "HIGAZERS": "hiGAZERS", "HIGH": "Highstreet", "HIGHER": "Higher", + "HIGHKEY": "HighKey", "HIH": "HiHealth", "HIKARI": "Hikari Protocol", "HILL": "President Clinton", @@ -6564,7 +7430,9 @@ "HIMO": "Himo World", "HIMOONBIRDS": "hiMOONBIRDS", "HINA": "Hina Inu", - "HINT": "Hintchain", + "HINAGI": "Hinagi", + "HINT": "Hive Intelligence", + "HINTCH": "Hintchain", "HINU": "HajiIni", "HIOD": "hiOD", "HIODBS": "hiODBS", @@ -6584,6 +7452,7 @@ "HITOP": "Hitop", "HIUNDEAD": "hiUNDEAD", "HIVE": "Hive", + "HIVP": "HiveSwap", "HIX": "HELIX Orange", "HK": "Hongkong", "HKB": "HongKong BTC bank", @@ -6593,6 +7462,7 @@ "HKFLOKI": "hong kong floki", "HKG": "Hacker Gold", "HKN": "Hacken", + "HKU5": "New Coronavirus", "HLC": "HalalChain", "HLD": "HyperLending", "HLDY": "HOLIDAY", @@ -6600,6 +7470,8 @@ "HLINK": "Chainlink (Harmony One Bridge)", "HLM": "Helium", "HLN": "Holonus", + "HLO": "Halo", + "HLOV1": "Halo v1", "HLP": "Purpose Coin", "HLPR": "HELPER COIN", "HLPT": "HLP Token", @@ -6624,7 +7496,7 @@ "HMTT": "Hype Meme Token", "HMU": "hit meeee upp", "HMX": "HMX", - "HNB": "HashNet BitEco", + "HNB": "HNB Protocol", "HNC": "Hellenic Coin", "HNCN": "Huncoin", "HND": "Hundred Finance", @@ -6632,6 +7504,7 @@ "HNST": "Honest", "HNT": "Helium", "HNTR": "Hunter", + "HNTV1": "Helium v1", "HNX": "HeartX Utility Token", "HNY": "Honey", "HNZO": "Hanzo Inu", @@ -6642,23 +7515,31 @@ "HOBO": "HOBO THE BEAR", "HOCAI": "Heroes of Crypto AI", "HOD": "HoDooi.com", - "HODL": "HOdlcoin", + "HODLC": "HOdlcoin", + "HODLV1": "HODL v1", + "HODLV2": "HODL", "HOG": "Hog", "HOGE": "Hoge Finance", + "HOGONSOLANA": "HOG", "HOHOHO": "Santa Floki v2.0", "HOICHI": "Hoichi", "HOKA": "Hokkaido Inu", "HOKK": "Hokkaidu Inu", "HOL": "Hololoot", "HOLA": "Hola Token", - "HOLD": "HOLD", + "HOLD": "Holdcoin", + "HOLDCO": "HOLD", "HOLDEX": "Holdex Finance", + "HOLDON4": "HoldOn4DearLife", + "HOLDS": "Holdstation", "HOLY": "Holy Trinity", "HOM": "Homeety", - "HOME": "OtterHome", + "HOME": "Home", + "HOMEBREW": "Homebrew Robotics Club", "HOMER": "Homer Simpson", "HOMERB": "Homer BSC", "HOMERO": "Homer Of Meme", + "HOMERS": "Homer", "HOMI": "HOMIHELP", "HOMIECOIN": "Homie Wars", "HOMMIES": "HOMMIES", @@ -6670,12 +7551,17 @@ "HONK": "Honk", "HONKLER": "Honkler", "HONOR": "HonorLand", + "HONX": "Honeywell xStock", + "HOODOG": "Hoodog", + "HOODRAT": "Hoodrat Coin", + "HOODX": "Robinhood xStock", "HOOF": "Metaderby Hoof", "HOOK": "Hooked Protocol", "HOOP": "Chibi Dinos", "HOOPS": "Hoops", "HOOT": "HOOT", "HOP": "Hop Protocol", + "HOPECOIN": "Hopecoin", "HOPPY": "Hoppy", "HOPPYTOKEN": "Hoppy", "HOPR": "HOPR", @@ -6685,6 +7571,7 @@ "HORUS": "HorusPay", "HOS": "Hotel of Secrets", "HOSHI": "Dejitaru Hoshi", + "HOSICO": "Hosico Cat", "HOSKY": "Hosky", "HOSTAI": "Host AI", "HOT": "Holo", @@ -6693,21 +7580,24 @@ "HOTMOON": "HotMoon Token", "HOTN": "HotNow", "HOTT": "HOT Token", - "HOUSE": "Klaymore Stakehouse", + "HOUND": "BaseHoundBot by Virtuals", + "HOUSE": "Housecoin", "HOW": "HowInu", "HOWL": "Coyote", "HP": "HeroPark", "HPAD": "HarmonyPad", "HPAY": "HedgePay", "HPB": "High Performance Blockchain", - "HPC": "HappyCoin", + "HPC": "Helal Para Coin", "HPL": "HappyLand (HPL)", "HPN": "HyperonChain", "HPO": "Hippocrat", + "HPOWSB10I": "HarryPotterObamaWallStreetBets10Inu", "HPT": "Huobi Pool Token", "HPX": "HUPAYX", "HPY": "Hyper Pay", "HPYPEPE": "Happy Pepe Token", + "HQ": "Metaverse HQ", "HQR": "Hayya Qatar", "HQT": "HyperQuant", "HQX": "HOQU", @@ -6725,6 +7615,7 @@ "HSAI": "HealthSci.AI", "HSC": "HashCoin", "HSF": "Hillstone Finance", + "HSK": "HashKey Platform Token", "HSN": "Hyper Speed Network", "HSP": "Horse Power", "HSS": "Hashshare", @@ -6740,11 +7631,12 @@ "HTDF": "Orient Walt", "HTE": "Hepton", "HTER": "Biogen", + "HTERM": "Hiero Terminal", "HTK": "Hard To Kill", "HTM": "Hatom", "HTML": "HTML Coin", "HTMOON": "HTMOON", - "HTN": "Heart Number", + "HTN": "Hoosat Network", "HTO": "Heavenland HTO", "HTR": "Hathor", "HTT": "Hello Art", @@ -6761,9 +7653,12 @@ "HUGO": "Hugo Inu", "HUH": "HUH Token", "HUHCAT": "huhcat", + "HULEZHI": "HU LE ZHI", "HUM": "Humanscape", + "HUMA": "Huma Finance", "HUMAI": "Humanoid AI", "HUMP": "Hump", + "HUMV1": "Humanscape v1", "HUND": "HUND MEME COIN", "HUNDRED": "HUNDRED", "HUNNY": "Pancake Hunny", @@ -6773,8 +7668,10 @@ "HUSBY": "HUSBY", "HUSD": "HUSD", "HUSH": "Hush", + "HUSHR": "hushr", "HUSKY": "Husky", "HUSL": "Hustle Token", + "HUSTLE": "Agent Hustle", "HUT": "Hibiki Run", "HVC": "HeavyCoin", "HVCO": "High Voltage Coin", @@ -6782,6 +7679,7 @@ "HVE2": "Uhive", "HVH": "HAVAH", "HVI": "Hungarian Vizsla Inu", + "HVLO": "Hivello", "HVN": "Hiveterminal Token", "HVNT": "HiveNet Token", "HVT": "HyperVerse", @@ -6801,20 +7699,27 @@ "HYCO": "HYPERCOMIC", "HYD": "HYDRA", "HYDRA": "Hydra", + "HYDRADX": "HydraDX", "HYDRO": "Hydro", "HYDROMINER": "Hydrominer", "HYDROP": "Hydro Protocol", "HYGH": "HYGH", "HYN": "Hyperion", - "HYP": "HyperStake", + "HYP": "HyperX", "HYPC": "HyperCycle", - "HYPE": "Hype", - "HYPER": "HyperChainX", + "HYPE": "Hyperliquid", + "HYPER": "Hyperlane", "HYPERAI": "HyperHash AI", + "HYPERC": "HyperChainX", "HYPERCOIN": "HyperCoin", "HYPERD": "HyperDAO", + "HYPERF": "HyperFly", + "HYPERIONX": "HyperionX", "HYPERS": "HyperSpace", + "HYPERSKIDS": "HYPERSKIDS", + "HYPERSTAKE": "HyperStake", "HYPES": "Supreme Finance", + "HYPEV1": "Hype v1", "HYPR": "Hypr Network", "HYS": "Heiss Shares", "HYT": "HoryouToken", @@ -6829,18 +7734,23 @@ "I7": "ImpulseVen", "I9C": "i9 Coin", "IAG": "IAGON", + "IAGV1": "IAGON v1", "IAI": "inheritance Art", "IAM": "IAME Identity", + "IAOMIN": "Yao Ming", "IB": "Iron Bank", "IBANK": "iBankCoin", "IBAT": "Battle Infinity", + "IBERA": "Infrared Bera", "IBETH": "Interest Bearing ETH", "IBEUR": "Iron Bank EURO", "IBFK": "İstanbul Başakşehir Fan Token", "IBFN": "IBF Net", "IBFR": "iBuffer Token", "IBG": "iBG Token", + "IBGT": "Infrared BGT", "IBIT": "InfinityBit Token", + "IBMX": "International Business Machines xStock", "IBNB": "iBNB", "IBP": "Innovation Blockchain Payment", "IBS": "Irbis Network", @@ -6855,6 +7765,7 @@ "ICE": "Ice Open Network", "ICEC": "IceCream", "ICECR": "Ice Cream Sandwich", + "ICECREAM": "IceCream AI", "ICELAND": "ICE LAND", "ICETH": "Interest Compounding ETH Index", "ICG": "Invest Club Global", @@ -6865,6 +7776,7 @@ "ICL": "ICLighthouse DAO", "ICLICK": "Iclick inu", "ICN": "Iconomi", + "ICNT": "Impossible Cloud Network Token", "ICNX": "Icon.X World", "ICOB": "Icobid", "ICOM": "iCommunity", @@ -6896,8 +7808,11 @@ "IDM": "IDM", "IDNA": "Idena", "IDO": "Idexo", - "IDOL": "IDOLINU", + "IDOL": "MEET48 Token", + "IDOLINU": "IDOLINU", + "IDOODLES": "IDOODLES", "IDORU": "Vip2Fan", + "IDRISS": "IDRISS", "IDRT": "Rupiah Token", "IDRX": "IDRX", "IDT": "InvestDigital", @@ -6942,20 +7857,28 @@ "ILC": "ILCOIN", "ILCT": "ILCoin Token", "ILK": "Inlock", + "ILLUMINAT": "Illuminat", "ILT": "iOlite", "ILV": "Illuvium", + "IMAGE": "Imagen AI", "IMARO": "IMARO", "IMAYC": "IMAYC", + "IMBREX": "Imbrex", "IMBTC": "The Tokenized Bitcoin", "IMC": "i Money Crypto", "IME": "Imperium Empires", "IMG": "ImageCoin", + "IMGN": "IMGN Labs", "IMGNAI": "Image Generation AI", + "IMGX10": "IMGx10", "IMGZ": "Imigize", "IMI": "Influencer", "IML": "IMMLA", + "IMMIGRATION": "Immigration Customs Enforcement", "IMMO": "ImmortalDAO Finance", + "IMMORTAL": "IMMORTAL.COM", "IMO": "IMO", + "IMOV": "IMOV", "IMP": "CoinIMP", "IMPACT": "Impact", "IMPACTXP": "ImpactXP", @@ -6968,7 +7891,7 @@ "IMPULSE": "IMPULSE by FDR", "IMS": "Independent Money System", "IMST": "Imsmart", - "IMT": "IMOV", + "IMT": "Immortal Token", "IMU": "imusify", "IMVR": "ImmVRse", "IMX": "Immutable X", @@ -6980,6 +7903,7 @@ "INCAKE": "InfinityCAKE", "INCEPT": "Incept", "INCNT": "Incent", + "INCO": "InfinitiCoin", "INCORGNITO": "Incorgnito", "INCP": "InceptionCoin", "IND": "Indorse", @@ -6991,6 +7915,8 @@ "INDIAN": "Indian Call Center", "INDICOIN": "IndiCoin", "INDU": "INDU4.0", + "INDUSTRIAL": "Industrial", + "INDX": "CryptoIndex", "INDY": "Indigo Protocol", "INE": "IntelliShare", "INEDIBLE": "INEDIBLE", @@ -7005,11 +7931,14 @@ "INFINI": "Infinity Economics", "INFLR": "Inflr", "INFO": "Infomatix", + "INFOFI": "WAGMI HUB", + "INFR": "infraX", "INFRA": "Bware", "INFT": "Infinito", "INFTT": "iNFT Token", "INFX": "Influxcoin", "ING": "Infinity Games", + "INIT": "Initia", "INJ": "Injective", "INK": "Ink", "INN": "Innova", @@ -7023,14 +7952,14 @@ "INRXV1": "INRx v1", "INS": "Insolar (Old Chain)", "INSANE": "InsaneCoin", + "INSANECOIN": "InsaneCoin", "INSANITY": "Insanity Coin", "INSC": "INSC (Ordinals)", "INSE": "INSECT", - "INSN": "Insane Coin", + "INSN": "Industry Sonic", "INSP": "Inspect", "INSPI": "InspireAI", "INSR": "Insurabler", - "INST": "Instadapp", "INSTAMINE": "Instamine Nuggets", "INSTAR": "Insights Network", "INSUR": "InsurAce", @@ -7038,6 +7967,7 @@ "INSURC": "InsurChain Coin", "INSUREDFIN": "Insured Finance", "INT": "Internet Node token", + "INTCX": "Intel xStock", "INTD": "INTDESTCOIN", "INTE": "InteractWith", "INTELLIQUE": "KARASOU", @@ -7072,8 +8002,10 @@ "IOETH": "ioETH", "IOEX": "ioeX", "IOI": "IOI Token", - "ION": "Ionomy", + "ION": "Ionic", "IONC": "IONChain", + "IONOMY": "Ionomy", + "IONP": "Ion Power Token", "IONX": "Charged Particles", "IONZ": "IONZ", "IOP": "Internet of People", @@ -7087,6 +8019,7 @@ "IOV": "Starname", "IOVT": "IOV", "IOWN": "iOWN Token", + "IP": "Story", "IP3": "Cripco", "IPAD": "Infinity Pad", "IPC": "IPChain", @@ -7101,15 +8034,17 @@ "IPV": "IPVERSE", "IPVOLD": "IPVERSE (Klaytn)", "IPX": "InpulseX", + "IPXV1": "InpulseX v1", "IQ": "IQ", "IQ50": "IQ50", + "IQ6900": "IQ6900", "IQC": "IQ.cash", "IQG": "IQ Global", "IQN": "IQeon", "IQQ": "Iqoniq", "IQT": "IQ Protocol", "IRA": "Diligence", - "IRC": "IRONCOIN", + "IRC": "IRIS", "IRENA": "Irena Coin Apps", "IRIS": "IRIS Network", "IRISTOKEN": "Iris Ecosystem", @@ -7117,6 +8052,7 @@ "IRO": "Iro-Chan", "IRON": "Iron Fish", "IRONBSC": "Iron BSC", + "IRONCOIN": "IRONCOIN", "IRT": "Infinity Rocket", "IRYDE": "iRYDE COIN", "ISA": "Islander", @@ -7131,15 +8067,18 @@ "ISKY": "Infinity Skies", "ISL": "IslaCoin", "ISLAMI": "ISLAMICOIN", + "ISLAND": "ISLAND Token", "ISLM": "Islamic Coin", "ISME": "Root Protocol", "ISP": "Ispolink", "ISR": "Insureum", "ISRG.CUR": "Intuitive Surgical, Inc.", + "ISSOU": "Risitas", "ISSP": "ISSP", "IST": "Inter Stable Token", "ISTEP": "iSTEP", "ITA": "Italian National Football Team Fan Token", + "ITALIANROT": "Italian Brainrot", "ITALOCOIN": "Italocoin", "ITAM": "ITAM Games", "ITAMCUBE": "CUBE", @@ -7148,6 +8087,7 @@ "ITF": "Intelligent Trading", "ITG": "iTrust Governance", "ITGR": "Integral", + "ITHACA": "Ithaca Protocol", "ITHEUM": "Itheum", "ITL": "Italian Lira", "ITLR": "MiTellor", @@ -7192,24 +8132,33 @@ "IZX": "IZX", "IZZY": "Izzy", "InBit": "PrepayWay", - "J": "JoinCoin", + "J": "Jambo", "J8T": "JET8", "J9BC": "J9CASINO", "JACK": "Jack Token", + "JACKPOT": "Solana Jackpot", "JACS": "JACS", "JACY": "JACY", "JADE": "Jade Protocol", "JADEC": "Jade Currency", + "JAE": "JaeCoin", "JAGO": "Jagotrack", + "JAI": "Japanese Akita Inu", "JAIHO": "Jaiho Crypto", + "JAIHOZ": "Jaihoz by Virtuals", + "JAILSTOOL": "Stool Prisondente", "JAKE": "Jake The Dog", "JAM": "Tune.Fm", "JAN": "Storm Warfare", "JANE": "JaneCoin", "JANET": "Janet", "JANI": "JANI", + "JANITOR": "Janitor", + "JANRO": "Janro The Rat", + "JAPAN": "Japan Open Chain", "JAR": "Jarvis+", "JARED": "Jared From Subway", + "JARVIS": "Jarvis AI", "JARY": "JeromeAndGary", "JASMY": "JasmyCoin", "JASON": "Jason Derulo", @@ -7230,37 +8179,46 @@ "JDAI": "Dai (TON Bridge)", "JDC": "JustDatingSite", "JDO": "JINDO", + "JDV": "JD Vance", "JED": "JEDSTAR", "JEDALS": "Yoda Coin Swap", "JEET": "Jeet", "JEETOLAX": "Jeetolax", + "JEETS": "I'm a Jeet", "JEFE": "JEFE TOKEN", "JEFF": "Jeff in Space", "JEFFRY": "jeffry", "JEJUDOGE": "Jejudoge", "JELLI": "JELLI", "JELLY": "Jelly eSports", + "JELLYAI": "jelly ai agent", + "JELLYJELLY": "Jelly-My-Jelly", "JEM": "Jem", "JEN": "JEN COIN", "JENNER": "Caitlyn Jenner", "JENSEN": "Jensen Huang", - "JERRY": "Jerry Inu", + "JERRY": "jerry", "JERRYINU": "JERRYINU", + "JERRYINUCOM": "Jerry Inu", "JES": "Jesus", "JEST": "Jester", "JESUS": "Jesus Coin", "JET": "Jet Protocol", "JETCAT": "Jetcat", "JETCOIN": "Jetcoin", + "JETFUEL": "Jetfuel Finance", "JETTON": "JetTon Game", "JEUR": "Jarvis Synthetic Euro", "JEW": "Shekel", "JEWEL": "DeFi Kingdoms", + "JEWELRY": "Jewelry Token", "JEX": "JEX Token", "JF": "Jswap.Finance", "JFI": "JackPool.finance", "JFIN": "JFIN Coin", "JFIVE": "Jonny Five", + "JFOX": "JuniperFox AI", + "JFP": "JUSTICE FOR PEANUT", "JGLP": "Jones GLP", "JGN": "Juggernaut", "JHH": "Jen-Hsun Huang", @@ -7289,21 +8247,26 @@ "JMT": "JMTIME", "JMZ": "Jimizz", "JNB": "Jinbi Token", + "JNFTC": "Jumbo Blockchain", "JNGL": "Jungle Labz", + "JNJX": "Johnson & Johnson xStock", "JNS": "Janus", "JNT": "Jibrel Network Token", "JNX": "Janex", "JNY": "JNY", "JOB": "Jobchain", "JOBS": "JobsCoin", + "JOBSEEK": "JobSeek AI", "JOC": "Speed Star JOC", "JOE": "JOE", "JOEB": "Joe Biden", "JOEBIDEN2024 ": "JOEBIDEN2024", + "JOECOIN": "Joe Coin", "JOEY": "Joey Inu", "JOGECO": "Jogecodog", "JOHM": "Johm lemmon", "JOHNNY": "Johnny The Bull", + "JOINCOIN": "JoinCoin", "JOINT": "Joint Ventures", "JOJO": "JOJO", "JOK": "JokInTheBox", @@ -7317,6 +8280,7 @@ "JONESUSDC": "Jones USDC", "JOOPS": "JOOPS", "JOPER": "Joker Pepe", + "JOS": "JuliaOS", "JOSE": "Jose", "JOTCHUA": "Perro Dinero", "JOULE": "Joule", @@ -7331,6 +8295,8 @@ "JPD": "JackpotDoge", "JPEG": "JPEG'd", "JPGC": "JPGold Coin", + "JPMORGAN": "JPMorgan", + "JPMX": "JPMorgan Chase xStock", "JPYC": "JPYC", "JPYX": "eToro Japanese Yen", "JRIT": "JERITEX", @@ -7346,12 +8312,14 @@ "JTS": "Jetset", "JTT": "Justus", "JTX": "Project J", + "JU": "JuChain", "JUDGE": "JudgeCoin", "JUGNI": "JUGNI", "JUI": "Juiice", "JUIC": "Juice", "JUICE": "Juice Finance", "JUICEB": "Juice", + "JUICET": "Juice Town", "JUL": "Joule", "JULB": "JustLiquidity Binance", "JULD": "JulSwap", @@ -7383,7 +8351,9 @@ "JWBTC": "Wrapped Bitcoin (TON Bridge)", "JWIF": "Jerrywifhat", "JWL": "Jewels", + "JYAI": "Jerry The Turtle By Matt Furie", "JYC": "Joe-Yo Coin", + "K": "Kinto", "K21": "K21", "K2G": "Kasko2go", "KAAI": "KanzzAI", @@ -7404,7 +8374,10 @@ "KAIK": "KAI KEN", "KAIKEN": "Kaiken Shiba", "KAILY": "Kailith", + "KAIM": "Kai Meme", "KAINET": "KAINET", + "KAIRO": "Kairo", + "KAITO": "KAITO", "KAKA": "KAKA NFT World", "KAKAXA": "KAKAXA", "KAKI": "Doge KaKi", @@ -7422,6 +8395,7 @@ "KAMAL": "Kamala Harris", "KAMALA": "Kamala Harris", "KAMALAHARRIS": "KAMALA HARRIS", + "KAMB": "Kambria", "KAMLA": "KAMALAMA (kamalama.org)", "KAMPAY": "KamPay", "KAN": "Bitkan", @@ -7429,7 +8403,10 @@ "KANG3N": "Kang3n", "KANGAL": "Kangal", "KANGO": "KANGO", + "KAON": "Kaon", "KAP": "KAP Games", + "KAPPA": "Kappa", + "KAPPY": "Kappy", "KAPU": "Kapu", "KAR": "Karura", "KARA": "KarateCat", @@ -7440,6 +8417,7 @@ "KARMAD": "Karma DAO", "KARRAT": "KARRAT", "KART": "Dragon Kart", + "KARUM": "Karum Coin", "KAS": "Kaspa", "KASBOT": "KASBOT THE GUARDIAN OF 𐤊ASPA", "KASHIN": "KASHIN", @@ -7447,7 +8425,7 @@ "KASPY": "KASPY", "KASSIAHOME": "Kassia Home", "KASTA": "Kasta", - "KAT": "Kambria", + "KAT": "Karat", "KATA": "Katana Inu", "KATANA": "Katana Finance", "KATCHU": "Katchu Coin", @@ -7457,8 +8435,9 @@ "KAU": "Kinesis Gold", "KAVA": "Kava", "KAWA": "Kawakami Inu", + "KAWS": "Kaws", "KAYI": "Kayı", - "KB3": "B3Coin", + "KBBB": "KILL BIG BEAUTIFUL BILL", "KBC": "Karatgold coin", "KBD": "Kyberdyne", "KBOND": "Klondike Bond", @@ -7470,7 +8449,8 @@ "KBX": "KuBitX", "KC": "Kernalcoin", "KCAKE": "KittyCake", - "KCAL": "Phantasma Energy", + "KCAL": "KCAL Token", + "KCALV2": "Phantasma Energy", "KCASH": "Kcash", "KCAT": "KING OF CATS", "KCATS": "KASPA CATS", @@ -7486,6 +8466,7 @@ "KDIA": "KDIA COIN", "KDOE": "Kudoe", "KDOGE": "KingDoge", + "KDT": "Kenyan Digital Token", "KDX": "eckoDAO", "KEANU": "Keanu Inu", "KEC": "KEYCO", @@ -7493,10 +8474,14 @@ "KEEMJONG": "KEEM JONG UNN", "KEEP": "Keep Network", "KEES": "Korea Entertainment Education & Shopping", + "KEETARD": "Keetard", "KEI": "Keisuke Inu", + "KEIRA": "Keira", "KEK": "KekCoin", + "KEKARMY": "Kek", "KEKE": "KEK", "KEKEC": "THE BALKAN DWARF", + "KEKIUS": "Kekius Maximus", "KEL": "KelVPN", "KELP": "KELP", "KELPE": "Kelp Earned Points", @@ -7514,9 +8499,14 @@ "KEPT": "KeptChain", "KERMIT": "KermitTheCoin", "KERN": "Kernel", - "KET": "KET", + "KERNEL": "KernelDAO", + "KET": "Ket", "KETAMINE": "Ketamine", "KETAN": "Ketan", + "KETCOIN": "KET", + "KEVIN": "Kevin (kevinonbase.xyz)", + "KEVINTOKENME": "KEVIN (kevintoken.me)", + "KEVINTOKENNET": "Kevin", "KEX": "Kira Network", "KEXCOIN": "KexCoin", "KEY": "SelfKey", @@ -7540,33 +8530,42 @@ "KI": "Genopets KI", "KIAN": "Porta", "KIBA": "Kiba Inu", + "KIBAV1": "Kiba Inu v1", "KIBSHI": "KiboShib", "KICK": "Kick", "KICKS": "GetKicks", "KIDEN": "RoboKiden", "KIF": "KittenFinance", + "KIKI": "KIKICat", + "KIKIF": "Kiki Flaminki", "KIKO": "KIKO", "KILLA": "The Bitcoin Killa", "KILLER": "Fat Cat Killer", "KILLSOLANA": "KillSolana", + "KILO": "KiloEx", "KILT": "KILT Protocol", - "KIM": "King Money", + "KIM": "KIM Token", + "KIMA": "Kima", "KIMBO": "Kimbo", "KIMCHI": "KIMCHI.finance", + "KIMIAI": "Kimi AI Agent", "KIN": "Kin", "KIND": "Kind Ads", "KINE": "Kine Protocol", "KINET": "KinetixFi", - "KING": "KING", + "KING": "LRT Squared", "KING93": "King93", "KINGB": "King Bean", "KINGBONK": "King Bonk", "KINGCAT": "King Cat", + "KINGCOIN": "KING", "KINGD": "Kingdom of Ants", "KINGDOG": "King Dog Inu", + "KINGDOM": "KING", "KINGDOMQUEST": "Kingdom Quest", "KINGF": "King Finance", "KINGGROK": "King Grok", + "KINGMONEY": "King Money", "KINGNEIRO": "King Neiro", "KINGO": "King of memes", "KINGOF": "King Of Memes", @@ -7583,6 +8582,7 @@ "KINK": "Kinka", "KINT": "Kintsugi", "KINU": "Kragger Inu", + "KIP": "KIP", "KIRA": "Kira the Injective Cat", "KIRBY": "Kirby Inu", "KIRBYCEO": "Kirby CEO", @@ -7612,13 +8612,16 @@ "KKT": "Kingdom Karnage", "KLAP": "Klap Finance", "KLAUS": "Klaus", + "KLAYMORE": "Klaymore Stakehouse", "KLC": "KiloCoin", "KLD": "Koduck", "KLEE": "KleeKai", "KLEVA": "KLEVA Protocol", + "KLICKZIE": "Klickzie", "KLIMA": "KlimaDAO", - "KLK": "Klickzie", + "KLK": "Klickl Token", "KLKS": "Kalkulus", + "KLKSYNC": "KLK Sync Protocol", "KLO": "Kalao", "KLON": "Klondike Finance", "KLP": "Kulupu", @@ -7636,6 +8639,7 @@ "KMX": "KiMex", "KNB": "Kronobit Networks Blockchain", "KNC": "Kyber Network Crystal v2", + "KNCH": "Kaanch Network", "KNCL": "Kyber Network Crystal Legacy", "KNDC": "KanadeCoin", "KNDM": "Kingdom", @@ -7655,22 +8659,29 @@ "KNT": "Knekted", "KNTO": "Kento", "KNU": "Keanu", + "KNUT": "Knut From Zoo", "KNW": "Knowledge", "KOAI": "KOI", + "KOBAN": "KOBAN", "KOBE": "Shabu Shabu", "KOBO": "KoboCoin", + "KOBUSHI": "Kobushi", "KODA": "Koda Cryptocurrency", "KODACHI": "Kodachi Token", "KOGE": "BNB48 Club Token", "KOGECOIN": "KogeCoin.io", + "KOGIN": "Kogin by Virtuals", "KOI": "Koi", + "KOII": "Koii", "KOIN": "Koinos", "KOINB": "KoinBülteni Token", "KOINETWORK": "Koi Network", "KOIP": "KoiPond", "KOJI": "Koji", "KOK": "KOK Coin", - "KOKO": "KokoSwap", + "KOKO": "KOALA AI", + "KOKOK": "KoKoK The Roach", + "KOKOSWAP": "KokoSwap", "KOL": "Kollect", "KOLANA": "KOLANA", "KOLION": "Kolion", @@ -7689,10 +8700,13 @@ "KORC": "King of Referral Coin", "KORE": "KORE Vault", "KOREC": "Kore", + "KORI": "Kori The Pom", "KORRA": "KORRA", + "KOS": "KONTOS", "KOSS": "Koss", "KOTARO": "KOTARO", "KOTO": "Koto", + "KOX": "Coca-Cola xStock", "KOY": "Koyo", "KOZ": "Kozjin", "KP3R": "Keep3rV1", @@ -7705,7 +8719,8 @@ "KPK": "ParkCoin", "KPL": "Kepple", "KPN": "KonnektVPN", - "KPOP": "KPOP Coin", + "KPOP": "OFFICIAL K-POP", + "KPOPCOIN": "KPOP Coin", "KPOPFUN": "KPOP (kpop.fun)", "KRAK": "Kraken", "KRATOS": "KRATOS", @@ -7722,7 +8737,7 @@ "KRL": "Kryll", "KRM": "Karma", "KRN": "KRYZA Network", - "KRO": "Betoken", + "KRO": "Kroma", "KROM": "Kromatika", "KROME": "KROME Shares", "KRONE": "Kronecoin", @@ -7749,7 +8764,8 @@ "KSTT": "Kocaelispor Fan Token", "KSWAP": "KyotoSwap", "KSYS": "K-Systems", - "KT": "Kuai Token", + "KT": "KingdomX", + "KTA": "Keeta", "KTC": "KTX.Finance", "KTK": "KryptCoin", "KTN": "Kattana", @@ -7759,13 +8775,16 @@ "KTS": "Klimatas", "KTT": "K-Tune", "KTX": "KwikTrust", + "KUAI": "Kuai Token", "KUB": "Bitkub Coin", "KUBE": "KubeCoin", "KUBO": "KUBO", "KUBOS": "KubosCoin", + "KUDAI": "Kudai", "KUE": "Kuende", "KUJI": "Kujira", "KUKU": "KuKu", + "KULA": "Kula", "KUMA": "Kuma Inu", "KUMU": "Kumu Finance", "KUNAI": "KunaiKash", @@ -7787,6 +8806,7 @@ "KWAI": "KWAI", "KWATT": "4New", "KWD": "KIWI DEFI", + "KWEEN": "KWEEN", "KWENTA": "Kwenta", "KWH": "KWHCoin", "KWIK": "KwikSwap", @@ -7797,21 +8817,25 @@ "KXUSD": "kxUSD", "KYCC": "KYCCOIN", "KYL": "Kylin Network", + "KYO": "Kayyo", "KYOKO": "Kyoko", "KYRA": "KYRA", + "KYSOL": "Kyros Restaked SOL", "KYTE": "Kambria Yield Tuning Engine", "KYUB": "Kyuubi", "KYVE": "KYVE Network", "KZC": "KZCash", "KZEN": "Kaizen", "L": "L inu", + "L1": "Lamina1", + "L1X": "Layer One X", "L2": "Leverj Gluon", "L2DAO": "Layer2DAO", "L3": "Layer3", "L3P": "Lepricon", "L3USD": "L3USD", "L7": "L7", - "LA": "LATOKEN", + "LA": "Lagrange", "LAB": "Labrys", "LABORCRYPTO": "LaborCrypto", "LABRA": "LabraCoin", @@ -7819,6 +8843,7 @@ "LABUBU": "Labubu", "LABX": "Stakinglab", "LABZ": "Insane Labz", + "LABZBASE": "Insane Labz (Base)", "LACCOIN": "LocalAgro", "LACE": "Lovelace World", "LAD": "LADA", @@ -7829,12 +8854,15 @@ "LAELAPS": "Laelaps", "LAFFIN": "Laffin Kamala", "LAI": "LayerAI", - "LAIKA": "Laika Protocol", + "LAIKA": "LAIKA", + "LAIKAPROTOCOL": "Laika Protocol", "LAINESOL": "Laine Staked SOL", + "LAIR": "Lair", "LAKE": "Data Lake", "LALA": "LaLa World", "LAMB": "Lambda", "LAMBO": "LAMBO", + "LAMPIX": "Lampix", "LAN": "Lanify", "LANA": "LanaCoin", "LANC": "Lanceria", @@ -7843,10 +8871,13 @@ "LANDLORD": "LANDLORD RONALD", "LANDS": "Two Lands", "LANDV1": "Landshare v1", + "LANDW": "LandWolf", "LANDWOLF": "LANDWOLF", + "LANDWOLFAVAX": "LANDWOLF (AVAX)", "LANDWOLFETH": "Landwolf", "LANDWU": "LandWu", "LANE": "LaneAxis", + "LANLAN": "LanLan Cat", "LAO": "LC Token", "LAOS": "LAOS Network", "LAPI": "Lapis Inu", @@ -7860,12 +8891,16 @@ "LAS": "LNAsolution Coin", "LASOL": "LamaSol", "LAT": "PlatON Network", + "LATOKEN": "LATOKEN", "LATOM": "Liquid ATOM", "LATTE": "LatteSwap", "LATX": "Latium", "LAUGHCOIN": "Laughcoin", "LAUNCH": "Launchblock.com", - "LAVA": "Lavaswap", + "LAUNCHCOIN": "Launch Coin on Believe", + "LAUNCHMOBY": "Moby", + "LAVA": "Lava Network", + "LAVASWAP": "Lavaswap", "LAVAX": "LavaX Labs", "LAVE": "Lavandos", "LAVITA": "Lavita AI", @@ -7873,12 +8908,13 @@ "LAWO": "Law Of Attraction", "LAX": "LAPO", "LAY3R": "AutoLayer", - "LAYER": "UniLayer", + "LAYER": "Solayer", "LAZ": "Lazarus", "LAZIO": "Lazio Fan Token", "LAZYCAT": "LAZYCAT", "LB": "LoveBit", "LBA": "Cred", + "LBAI": "Lemmy The Bat", "LBC": "LBRY Credits", "LBK": "LBK", "LBL": "LABEL Foundation", @@ -7892,6 +8928,7 @@ "LC": "Lotus Capital", "LC4": "LEOcoin", "LCASH": "LitecoinCash", + "LCAT": "Lion Cat", "LCC": "LitecoinCash", "LCD": "Lucidao", "LCG": "LCG", @@ -7903,6 +8940,7 @@ "LCR": "Lucro", "LCRO": "Liquid CRO", "LCS": "LocalCoinSwap", + "LCSH": "LC SHIB", "LCSN": "Lacostoken", "LCT": "LendConnect", "LCWP": "LiteCoinW Plus", @@ -7928,8 +8966,12 @@ "LEE": "Love Earn Enjoy", "LEET": "LeetSwap", "LEG": "Legia Warsaw Fan Token", + "LEGAL": "LegalX", + "LEGEND": "Legend", "LEGION": "LEGION", + "LEGIT": "LEGIT", "LEGO": "Lego Coin", + "LEI": "Leia Games", "LEIA": "Leia", "LELE": "Lelecoin", "LEMC": "LemonChain", @@ -7955,8 +8997,10 @@ "LEPEN": "LePenCoin", "LEPER": "Leper", "LESBIAN": "Lesbian Inu", + "LESLIE": "Leslie", "LESS": "Less Network", "LESSF": "LessFnGas", + "LESTE": "LESTER by Virtuals", "LESTER": "Litecoin Mascot", "LET": "LinkEye", "LETIT": "Letit", @@ -7974,8 +9018,9 @@ "LEXI": "LEXIT", "LEZ": "Peoplez", "LEZGI": "LEZGI Token", - "LF": "Linkflow", + "LF": "LF", "LFC": "BigLifeCoin", + "LFDOG": "lifedog", "LFG": "Gamerse", "LFGO": "Lets Fuckin Go", "LFI": "LunaFi", @@ -7986,9 +9031,12 @@ "LGBT": "Let's Go Brandon Token", "LGBTQ": "LGBTQoin", "LGC": "LiveGreen Coin", + "LGCT": "Legacy Token", "LGCY": "LGCY Network", "LGD": "Legends Cryptocurrency", + "LGG": "Let's Go Gambling", "LGNDX": "LegendX", + "LGNS": "Longinus", "LGO": "Legolas Exchange", "LGOLD": "LYFE GOLD", "LGOT": "LGO Token", @@ -8003,13 +9051,15 @@ "LIBERA": "Libera Financial", "LIBERO": "Libero Financial", "LIBERTA": "The Libertarian Dog", + "LIBERTY": "Torch of Liberty", "LIBFX": "Libfx", - "LIBRA": "0L Network", + "LIBRA": "Libra", "LIBRAP": "Libra Protocol", "LIBRE": "Libre", "LIC": "Ligercoin", "LICK": "PetLFG", "LICKER": "LICKER", + "LICKO": "LICKO", "LICO": "Liquid Collectibles", "LID": "Liquidity Dividends Protocol", "LIDER": "Lider Token", @@ -8024,15 +9074,19 @@ "LIFT": "Uplift", "LIGER": "Ligercoin", "LIGHT": "LightChain", + "LIGHTSPEED": "LightSpeedCoin", "LIGMA": "Ligma Node", "LIGO": "Ligo", + "LIHUA": "LIHUA", "LIKE": "Only1", "LIKEC": "LikeCoin", "LILA": "LiquidLayer", "LILB": "Lil Brett", "LILFLOKI": "Lil Floki", + "LILO": "Lilo", "LILPUMP": "lilpump", "LILY": "LILY-The Gold Digger", + "LIMBO": "Limbo", "LIME": "iMe Lab", "LIMEX": "Limestone Network", "LIMITEDCOIN": "Limited Coin", @@ -8044,6 +9098,7 @@ "LINDACEO": "LindaYacc Ceo", "LINEA": "Linea", "LING": "Lingose", + "LINGO": "Lingo", "LINK": "Chainlink", "LINKA": "LINKA", "LINKC": "LINKCHAIN", @@ -8051,9 +9106,10 @@ "LINQ": "LINQ", "LINSPIRIT": "linSpirit", "LINU": "Luna Inu", - "LINX": "Linx", + "LINX": "Linde xStock", "LIO": "Lio", - "LION": "Lion Token", + "LION": "Loaded Lions", + "LIONT": "Lion Token", "LIPC": "LIpcoin", "LIPS": "LipChain", "LIQ": "LIQ Protocol", @@ -8064,8 +9120,10 @@ "LIR": "Let it Ride", "LIS": "Realis Network", "LISA": "Lisa Simpson", + "LISAS": "Lisa Simpson", "LIST": "KList Protocol", "LISTA": "Lista DAO", + "LISTEN": "Listen", "LISUSD": "lisUSD", "LIT": "Litentry", "LITE": "Lite USD", @@ -8078,9 +9136,11 @@ "LITT": "LitLab Games", "LIV": "LiviaCoin", "LIVE": "TRONbetLive", + "LIVENCOIN": "LivenPay", "LIVESEY": "Dr. Livesey", "LIVESTARS": "Live Stars", "LIXX": "Libra Incentix", + "LIY": "Lily", "LIZ": "Lizus Payment", "LIZA": "Liza", "LIZARD": "LIZARD", @@ -8097,9 +9157,12 @@ "LKY": "LuckyCoin", "LL": "LightLink", "LLAND": "Lyfe Land", + "LLD": "Liberland dollar", "LLG": "Loligo", "LLION": "Lydian Lion", + "LLM": "Large Language Model Based", "LLT": "LILLIUS", + "LLYX": "Eli Lilly xStock", "LM": "LeisureMeta", "LMAO": "LMAO Finance", "LMC": "LomoCoin", @@ -8109,13 +9172,14 @@ "LMF": "Lamas Finance", "LMQ": "Lightning McQueen", "LMR": "Lumerin", - "LMT": "Lympo Market Token", + "LMT": "LIMITUS", "LMTOKEN": "LM Token", "LMWR": "LimeWire Token", "LMXC": "LimonX", "LMY": "Lunch Money", "LN": "LINK", "LNC": "Blocklancer", + "LNCHM": "Launchium", "LND": "Lendingblock", "LNDRR": "Lendr Network", "LNDRY": "LNDRY", @@ -8124,7 +9188,8 @@ "LNKC": "Linker Coin", "LNL": "LunarLink", "LNQ": "LinqAI", - "LNR": "Lunar", + "LNR": "LNR", + "LNRV2": "Lunar", "LNT": "Lottonation", "LNX": "Lunox Token", "LOA": "League of Ancients", @@ -8147,20 +9212,26 @@ "LOE": "Legends of Elysium", "LOF": "Land of Fantasy", "LOFI": "LOFI", + "LOFIBUZZ": "LOFI", "LOG": "Wood Coin", "LOGO": "LOGOS", + "LOGOS": "LOGOSAI", + "LOGT": "Lord of Dragons Governance Token", "LOGX": "LogX Network", "LOIS": "Lois Token", "LOKA": "League of Kingdoms", "LOKR": "Polkalokr", + "LOKY": "Loky by Virtuals", "LOL": "EMOGI Network", "LOLA": "Lola", "LOLATHECAT": "Lola", "LOLC": "LOL Coin", "LOLLY": "Lollipop", + "LOLLYBOMB": "LollyBomb", "LOLO": "Lolo", "LON": "Tokenlon", "LONG": "Longdrink Finance", + "LONGEVITY": "longevity", "LONGFU": "LONGFU", "LONGM": "Long Mao", "LONGSHINE": "LongShine", @@ -8193,7 +9264,7 @@ "LOUD": "Loud Market", "LOULOU": "LOULOU", "LOV": "LoveChain", - "LOVE": "Deesse", + "LOVE": "Love Monster", "LOVELY": "Lovely finance", "LOVELYV1": "Lovely Inu Finance", "LOVESNOOPY": "I LOVE SNOOPY", @@ -8203,6 +9274,7 @@ "LOYAL": "Loyalty Labs", "LP": "Liquid Protocol", "LPC": "Little Phil", + "LPENGU": "Lil Pudgys", "LPI": "LPI DAO", "LPK": "Kripton", "LPL": "LinkPool", @@ -8210,6 +9282,7 @@ "LPNT": "Luxurious Pro Network Token", "LPOOL": "Launchpool", "LPT": "Livepeer", + "LPTV1": "Livepeer v1", "LPV": "Lego Pepe Vision", "LPY": "LeisurePay", "LQ": "Liqwid Finance", @@ -8219,6 +9292,7 @@ "LQDN": "Liquidity Network", "LQDR": "LiquidDriver", "LQDX": "Liquid Crypto", + "LQNA": "The Queen of Hyperliquid", "LQR": "Laqira Protocol", "LQT": "Lifty", "LQTY": "Liquity", @@ -8227,9 +9301,8 @@ "LRG": "Largo Coin", "LRN": "Loopring [NEO]", "LRT": "LandRocker", - "LRT2": "LRT Squared", "LSC": "LS Coin", - "LSD": "LightSpeedCoin", + "LSD": "Pontem Liquidswap", "LSDOGE": "LSDoge", "LSETH": "Liquid Staked ETH", "LSHARE": "LSHARE", @@ -8246,6 +9319,7 @@ "LSWAP": "LoopSwap", "LT": "Loctite Assets Token", "LTA": "Litra", + "LTAI": "LibertAI", "LTB": "Litebar", "LTBC": "LTBCoin", "LTBTC": "Lightning Bitcoin", @@ -8269,6 +9343,7 @@ "LTO": "LTO Network", "LTOV1": "LTO Network v1", "LTOV2": "LTO Network v2", + "LTP": "Listapie", "LTPC": "Lightpaycoin", "LTR": "LogiTron", "LTRBT": "Little Rabbit", @@ -8285,6 +9360,7 @@ "LUCE": "Luce", "LUCHOW": "LunaChow", "LUCI": "LUCI", + "LUCIC": "Lucidum Coin", "LUCK": "Lucky Cat", "LUCKY": "Lucky Lion", "LUCKYB": "LuckyBlocks", @@ -8292,19 +9368,23 @@ "LUCKYSLP": "LuckysLeprecoin", "LUCRE": "Lucre", "LUCY": "Lucy", + "LUCYAI": "Pitch Lucy AI", "LUDO": "Ludo", + "LUDUS": "Ludus", "LUFC": "Leeds United Fan Token", "LUFFY": "Luffy", "LUFFYG": "Luffy G5", "LUFFYOLD": "Luffy", + "LUFFYV1": "Luffy v1", "LUIGI": "Luigi Inu", "LUIS": "Tongue Cat", "LULU": "LULU", - "LUM": "Illuminates", + "LUM": "Luminous", "LUMA": "LUMA Token", "LUMI": "LUMI Credits", "LUMIA": "Lumia", "LUMIO": "Solana Mascot", + "LUMO": "Lumo-8B-Instruct", "LUMOS": "Lumos", "LUN": "Lunyr", "LUNA": "Terra", @@ -8325,16 +9405,22 @@ "LUSH": "Lush AI", "LUT": "Cinemadrom", "LUTETIUM": "Lutetium Coin", - "LUX": "LUXCoin", + "LUX": "Lux Token", + "LUXAI": "Lux Token", + "LUXCOIN": "LUXCoin", "LUXO": "Luxo", "LUXU": "Luxury Travel Token", "LUXY": "Luxy", "LVG": "Leverage Coin", "LVIP": "Limitless VIP", "LVL": "Level", + "LVLUSD": "Level USD", + "LVLY": "LyvelyToken", "LVM": "LakeViewMeta", - "LVN": "LivenPay", + "LVN": "Levana Protocol", + "LVVA": "Levva Protocol Token", "LVX": "Level01", + "LWA": "LUMIWAVE", "LWC": "Linework Coin", "LWF": "Local World Forwarders", "LX": "Moonlight", @@ -8351,10 +9437,13 @@ "LYK": "Loyakk Vega", "LYL": "LoyalCoin", "LYM": "Lympo", + "LYMPO": "Lympo Market Token", "LYN": "LYNCHPIN Token", "LYNK": "Lynked.World", - "LYNX": "Lynx", + "LYNX": "Lynex", + "LYNXCOIN": "Lynx", "LYO": "LYO Credit", + "LYP": "Lympid Token", "LYQD": "eLYQD", "LYR": "Lyra", "LYRA": "Lyra", @@ -8370,7 +9459,9 @@ "M": "MetaVerse-M", "M1": "SupplyShock", "M2O": "M2O Token", + "M3M3": "M3M3", "M87": "MESSIER", + "MA": "Mind-AI", "MAAL": "Maal Chain", "MABA": "Make America Based Again", "MAC": "MachineCoin", @@ -8379,20 +9470,27 @@ "MADAGASCARTOKEN": "Madagascar Token", "MADANA": "MADANA", "MADC": "MadCoin", + "MADCOIN": "MAD", "MADH": "Madhouse", "MADOG": "MarvelDoge", "MADP": "Mad Penguin", "MADPEPE": "Mad Pepe", + "MAECENAS": "Maecenas", "MAEP": "Maester Protocol", "MAF": "MetaMAFIA", "MAG": "Magnify Cash", - "MAGA": "MAGA Hat", + "MAG7SSI": "MAG7.ssi", + "MAGA": "MAGA", "MAGA2024": "MAGA2024", + "MAGA47": "MAGA 47", "MAGAA": "MAGA AGAIN", + "MAGABRO": "M.A.G.A. Bro", "MAGAC": "MAGA CAT", "MAGACA": "MAGA CAT", "MAGACAT": "MAGACAT", "MAGADOGE": "MAGA DOGE", + "MAGAF": "MAGA FRENS", + "MAGAHAT": "MAGA Hat", "MAGAIBA": "Magaiba", "MAGAN": "Maganomics On Solana", "MAGANOMICS": "Maganomics", @@ -8408,6 +9506,7 @@ "MAGICV": "Magicverse", "MAGIK": "Magik Finance", "MAGN": "Magnate Finance", + "MAGNE": "Magnetix", "MAGNET": "Yield Magnet", "MAGNET6900": "MAGNET6900", "MAGNETWORK": "Magnet", @@ -8415,13 +9514,15 @@ "MAGPAC": "MAGA Meme PAC", "MAH": "Mahabibi Bin Solman", "MAHA": "MahaDAO", - "MAI": "Mindsync", + "MAI": "MAI", "MAIA": "Maia", "MAID": "MaidSafe Coin", "MAIL": "CHAINMAIL", "MAINSTON": "Ston", + "MAIV": "MAIV", + "MAJ": "Major Frog", "MAJO": "Majo", - "MAJOR": "Major Frog", + "MAJOR": "Major", "MAK": "MetaCene", "MAKE": "MAKE", "MAKEA": "Make America Healthy Again", @@ -8430,30 +9531,42 @@ "MALGO": "milkALGO", "MALL": "Metamall", "MALLY": "Malamute Finance", + "MALOU": "MALOU Token", "MAMAI": "MammothAI", "MAMBA": "Mamba", + "MAMBO": "Mambo", + "MAMO": "Mamo", "MAN": "Matrix AI Network", "MANA": "Decentraland", + "MANA3": "MANA3", "MANC": "Mancium", "MAND": "Mandala Exchange Token", "MANDALA": "Mandala Exchange Token", "MANDOX": "MandoX", + "MANDY": "MANDY COIN", "MANE": "MANE", "MANEKI": "MANEKI", + "MANEKINEKO": "MANEKI-NEKO", "MANGA": "Manga Token", "MANIA": "ScapesMania", "MANIFEST": "Manifest", "MANNA": "Manna", "MANORUKA": "ManoRuka", + "MANSONCOIN": "Manson Coin", "MANT": "Mantle USD", "MANTA": "Manta Network", + "MANTI": "Mantis", "MANTLE": "Mantle", + "MANUSAI": "Manus AI Agent", "MANYU": "Little Manyu", - "MAO": "Mao", + "MANYUDOG": "MANYU", + "MAO": "MAO", + "MAOMEME": "Mao", "MAOW": "MAOW", "MAP": "MAP Protocol", "MAPC": "MapCoin", "MAPE": "Mecha Morphing", + "MAPO": "MAP Protocol", "MAPR": "Maya Preferred 223", "MAPS": "MAPS", "MAR3": "Mar3 AI", @@ -8461,24 +9574,29 @@ "MARCUS": "Marcus Cesar Inu", "MARE": "Mare Finance", "MARGA": "Margaritis", + "MARGE": "Marge Simpson", "MARGINLESS": "Marginless", "MARI": "MarijuanaCoin", "MARIC": "Maricoin", + "MARIE": "Marie Rose", "MARIO": "MARIO CEO", "MARK": "Benchmark Protocol", "MARKE": "Market Ledger", + "MARKETMOVE": "MarketMove", "MARLEY": "Marley Token", "MARMAJ": "marmaj", "MARO": "Maro", - "MARS": "MarsCoin", + "MAROV1": "TTC PROTOCOL", + "MARS": "Mars", "MARS4": "MARS4", "MARSC": "MarsCoin", + "MARSCOIN": "MarsCoin", "MARSH": "Unmarshal", "MARSO": "Marso.Tech", "MARSRISE": "MarsRise", "MARSUPILAMI": "MARSUPILAMI INU", "MARSW": "Marswap", - "MART": "Monart", + "MART": "ArtMeta", "MARTIA": "Colonize Mars", "MARTK": "Martkist", "MARTY": "Marty Inu", @@ -8491,6 +9609,7 @@ "MARYJ": "MaryJane Coin", "MAS": "Midas Protocol", "MASA": "Masa", + "MASHA": "Masha", "MASK": "Mask Network", "MASP": "Market.space", "MASQ": "MASQ", @@ -8499,18 +9618,22 @@ "MASTER": "Mastercoin", "MASTERCOIN": "MasterCoin", "MASTERMINT": "MasterMint", + "MASTERMIX": "Master MIX Token", "MASTERTRADER": "MasterTraderCoin", "MASYA": "MASYA", - "MAT": "MiniApps", + "MAT": "My Master Wa", "MATA": "Ninneko", "MATAR": "MATAR AI", "MATCH": "Matching Game", "MATE": "Mate", + "MATES": "MATES", "MATH": "MATH", "MATIC": "Polygon", "MATICX": "Stader MaticX", "MATPAD": "MaticPad", - "MATRIX": "Matrix Labs", + "MATR1X": "Matr1x", + "MATRIX": "Matrix One", + "MATRIXLABS": "Matrix Labs", "MATT": "Matt Furie", "MATTER": "AntiMatter", "MAU": "MAU", @@ -8521,21 +9644,26 @@ "MAW": "Mountain Sea World", "MAWA": "Kumala Herris", "MAWC": "Magawincat", - "MAX": "Matr1x", + "MAX": "Mastercard xStock", + "MAXAIAGENT": "MAX", "MAXCOIN": "MaxCoin", "MAXETH": "Max on ETH", "MAXI": "Maximus", + "MAXIMUSA": "Kekius Maximusa", "MAXL": "Maxi protocol", "MAXR": "Max Revive", "MAXX": "MAXX Finance", - "MAY": "Theresa May Coin", + "MAY": "Mayflower", + "MAYA": "Maya", "MAYACOIN": "MayaCoin", + "MAYILONG": "Yi long ma", "MAYO": "Mr Mayonnaise the Cat", "MAYP": "Maya Preferred", "MAZC": "MyMazzu", "MAZI": "MaziMatic", "MAZZE": "Mazze", "MB": "MineBee", + "MB28": "MBridge28", "MB4": "Matthew Box 404", "MB8": "MB8 Coin", "MBAG": "MoonBag", @@ -8549,6 +9677,7 @@ "MBE": "MxmBoxcEus Token", "MBET": "MoonBet", "MBF": "MoonBear.Finance", + "MBG": "MBG Token", "MBI": "Monster Byte Inc", "MBID": "myBID", "MBILLY": "MAMA BILLY", @@ -8568,6 +9697,7 @@ "MBRS": "Embers", "MBS": "MonkeyBall", "MBT": "Metablackout", + "MBTCS": "MBTCs", "MBTX": "MinedBlock", "MBX": "Marblex", "MC": "Merit Circle", @@ -8581,9 +9711,10 @@ "MCAU": "Meld Gold", "MCB": "MCDEX", "MCC": "Magic Cube Coin", - "MCD": "CDbio", + "MCD": "McDonald's Job Application", "MCDAI": "Dai (Multichain)", "MCDULL": "McDull", + "MCDX": "McDonald’s xStock", "MCELO": "Moola Celo", "MCEN": "Main Character Energy", "MCEUR": "Moola Celo EUR", @@ -8628,15 +9759,17 @@ "MDM": "Medium", "MDN": "Modicoin", "MDOGE": "First Dog In Mars", + "MDOGS": "Money Dogs", "MDR": "Mudra MDR", "MDS": "MediShares", "MDT": "Measurable Data Token", "MDTK": "MDtoken", + "MDTX": "Medtronic xStock", "MDU": "MDUKEY", "MDUS": "MEDIEUS", "MDX": "Mdex (BSC)", "MDXH": "Mdex (HECO)", - "ME": "All.me", + "ME": "Magic Eden", "MEAN": "Meanfi", "MEB": "Meblox Protocol", "MEC": "MegaCoin", @@ -8656,6 +9789,7 @@ "MEER": "Qitmeer Network", "MEET": "CoinMeet", "MEETONE": "MEET.ONE", + "MEETPLE": "Meetple", "MEF": "MEFLEX", "MEFA": "Metaverse Face", "MEGA": "MegaFlash", @@ -8664,15 +9798,19 @@ "MEGAHERO": "MEGAHERO", "MEGALAND": "Metagalaxy Land", "MEGALANDV1": "Metagalaxy Land v1", + "MEGATECH": "Megatech", "MEGAX": "Megahex", "MEGE": "MEGE", "MEH": "meh", "MEI": "Mei Solutions", "MEIZHU": "GUANGZHOU ZOO NEW BABY PANDA", "MEL": "MELX", - "MELANIA": "Melania Trump", + "MELANIA": "Melania Meme", + "MELANIATRUMP": "Melania Trump", "MELB": "Minelab", - "MELD": "MELD", + "MELD": "MetaElfLand Token", + "MELDV1": "MELD v1", + "MELDV2": "MELD", "MELI": "Meli Games", "MELLO": "Mello Token", "MELLOW": "Mellow Man", @@ -8684,23 +9822,32 @@ "MELT": "Defrost Finance", "MEM": "Memecoin", "MEMAGX": "Meta Masters Guild Games", + "MEMBERSHIP": "Membership Placeholders", "MEMD": "MemeDAO", + "MEMDEX": "Memdex100", "MEME": "Memecoin", + "MEMEA": "MEME AI", "MEMEAI": "Meme Ai", + "MEMEBRC": "MEME", + "MEMECOIN": "just memecoin", "MEMECUP": "Meme Cup", "MEMEETF": "Meme ETF", "MEMEFI": "MemeFi", + "MEMEFICASH": "MemeFi", "MEMEINU": "Meme Inu", "MEMEM": "Meme Man", "MEMEME": "MEMEME", "MEMEMINT": "MEME MINT", "MEMEMUSK": "MEME MUSK", + "MEMENTO": "MEMENTO•MORI (Runes)", "MEMERUNE": "MEME•ECONOMICS", "MEMES": "MemeCoinDAO", "MEMESAI": "Memes AI", "MEMESQUAD": "Meme Squad", "MEMET": "MEMETOON", "MEMETIC": "Memetic", + "MEMEX": "Meme Index", + "MEMHASH": "Memhash", "MEMORYCOIN": "MemoryCoin", "MEN": "METAHUB FINANCE", "MENDI": "Mendi Finance", @@ -8708,6 +9855,7 @@ "MENLO": "Menlo One", "MEO": "Meow Of Meme", "MEOW": "Zero Tech", + "MEOWCAT": "MeowCat", "MEOWETH": "Meow", "MEOWG": "MeowGangs", "MEOWIF": "Meowifhat", @@ -8719,6 +9867,7 @@ "MERCU": "Merculet", "MERCURY": "Mercury", "MEREDITH": "Taylor Swift's Cat MEREDITH", + "MERG": "Merge Token", "MERGE": "Merge", "MERI": "Merebel", "MERIDIAN": "Meridian Network LOCK", @@ -8735,6 +9884,7 @@ "META": "MetaDAO", "METAA": "META ARENA", "METABOT": "Robot Warriors", + "METABRAW": "Metabrawl", "METAC": "Metacoin", "METACA": "MetaCash", "METACAT": "MetaCat", @@ -8743,10 +9893,12 @@ "METAD": "MetaDoge", "METADIUM": "Metadium", "METADOGE": "MetaDoge", + "METADOGEV1": "MetaDoge V1", "METADOGEV2": "MetaDoge V2", "METAF": "MetaFastest", "METAG": "MetagamZ", "METAGEAR": "MetaGear", + "METAIVERSE": "MetAIverse", "METAL": "Metal Blockchain", "METALCOIN": "MetalCoin", "METAMEME": "met a meta metameme", @@ -8760,11 +9912,13 @@ "METATI": "Metatime Coin", "METATR": "MetaTrace Utility Token", "METAUFO": "MetaUFO", - "METAV": "MetaVPad", + "METAV": "METAVERSE", "METAVE": "Metaverse Convergence", + "METAVERSEX": "MetaverseX", "METAVIE": "Metavie", + "METAVPAD": "MetaVPad", "METAW": "MetaWorth", - "METAX": "MetaverseX", + "METAX": "Meta xStock", "METEOR": "Meteorite Network", "METFI": "MetFi", "METH": "Mantle Staked Ether", @@ -8772,8 +9926,8 @@ "METIS": "Metis Token", "METM": "MetaMorph", "METO": "Metafluence", - "METOLD": "Metronome", "METRO": "Metropoly", + "METV1": "Metronome", "MEU": "MetaUnit", "MEV": "MEVerse", "MEVETH": "mevETH", @@ -8820,7 +9974,7 @@ "MGOD": "MetaGods", "MGP": "MangoChain", "MGPT": "MotoGP Fan Token", - "MGT": "Megatech", + "MGT": "Moongate", "MGUL": "Mogul Coin", "MGX": "MargiX", "MHAM": "Metahamster", @@ -8831,6 +9985,7 @@ "MHUNT": "MetaShooter", "MI": "XiaoMiCoin", "MIA": "MiamiCoin", + "MIAO": "MIAOCoin", "MIB": "Mobile Integrated Blockchain", "MIBO": "miBoodle", "MIBR": "MIBR Fan Token", @@ -8839,19 +9994,24 @@ "MICHI": "michi", "MICK": "Mickey Meme", "MICKEY": "Steamboat Willie", - "MICRO": "Micromines", + "MICRO": "Micro GPT", "MICRODOGE": "MicroDoge", + "MICROMINES": "Micromines", "MIDAI": "Midway AI", "MIDAS": "Midas", "MIDASDOLLAR": "Midas Dollar Share", + "MIDLE": "Midle", "MIDN": "Midnight", + "MIDNIGHT": "Midnight", "MIE": "MIE Network", "MIF": "monkeywifhat", "MIG": "Migranet", "MIGGLEI": "Migglei", "MIGGLES": "Mr Miggles", "MIGMIG": "MigMig Swap", + "MIH": "MINE COIN", "MIHARU": "Smiling Dolphin", + "MIHV1": "MINE COIN v1", "MIIDAS": "Miidas NFT", "MIININGNFT": "MiningNFT", "MIKE": "Mike", @@ -8860,9 +10020,10 @@ "MILA": "MILADY MEME TOKEN", "MILE": "milestoneBased", "MILEI": "MILEI", - "MILK": "Milkshake Swap", + "MILK": "MilkyWay", "MILK2": "Spaceswap MILK2", "MILKBAG": "MILKBAG", + "MILKSHAKE": "Milkshake Swap", "MILKYWAY": "MilkyWayZone", "MILLI": "Million", "MILLY": "milly", @@ -8880,11 +10041,13 @@ "MINA": "Mina Protocol", "MINC": "MinCoin", "MIND": "Morpheus Labs", + "MINDBODY": "Mind Body Soul", "MINDC": "MindCoin", "MINDCOIN": "MindCoin", "MINDEX": "Mindexcoin", "MINDGENE": "Mind Gene", "MINDS": "Minds", + "MINDSYNC": "Mindsync", "MINE": "SpaceMine", "MINEA": "Mine AI", "MINER": "MINER", @@ -8894,14 +10057,17 @@ "MINEX": "Minex", "MINGO": "Mingo", "MINI": "mini", + "MINIAPPS": "MiniApps", "MINIBNBTIGER": "MiniBNBTiger", "MINID": "Mini Donald", + "MINIDO": "MiniDoge", "MINIDOGE": "MiniDOGE", "MINIFOOTBALL": "Minifootball", "MINIMYRO": "Mini Myro", "MININEIRO": "Mini Neiro", "MININGWATCHDOG": "Miningwatchdog Smartchain", "MINION": "Minions INU", + "MINIONS": "Minions", "MINIP": "MiniPepe Coin", "MINIPEPE": "MiniPepe", "MINIS": "Mini", @@ -8909,10 +10075,12 @@ "MINO": "MINO INU", "MINOCOINCTO": "MINO", "MINS": "Minswap", - "MINT": "Mint Club", + "MINT": "Mintify", + "MINTCHAIN": "Mint", "MINTCOIN": "MintCoin", "MINTE": "Minter HUB", "MINTME": "MintMe.com Coin", + "MINTO": "The AI Mascot", "MINTYS": "MintySwap", "MINU": "Minu", "MINUTE": "MINUTE Vault (NFTX)", @@ -8923,16 +10091,21 @@ "MIR": "Mirror Protocol", "MIRA": "Chains of War", "MIRACLE": "MIRACLE", - "MIRAI": "MIRAI", + "MIRACLETELE": "Miracle Tele", + "MIRAI": "Project MIRAI", + "MIRAIBUILD": "MIRAI", "MIRC": "MIR COIN", "MIRT": "MIR Token", + "MIRX": "Mirada AI", "MIS": "Mithril Share", "MISA": "Sangkara", "MISCOIN": "MIScoin", "MISHA": "Vitalik's Dog", "MISHKA": "Mishka Token", "MISS": "MISS", + "MISSK": "Miss Kaka", "MIST": "Mist", + "MISTCOIN": "MistCoin", "MISTE": "Mister Miggles", "MISTRAL": "Mistral AI", "MIT": "Galaxy Blitz", @@ -8949,6 +10122,7 @@ "MIXAI": "Mixcash AI", "MIXCOIN": "Mixaverse", "MIXER": "TON Mixer", + "MIXIE": "Mixie", "MIY": "Icel Idman Yurdu Token", "MIZ": "Mizar", "MJT": "MojitoSwap", @@ -8996,7 +10170,7 @@ "MMS": "Marsverse", "MMSC": "MMSC PLATFORM", "MMSS": "MMSS (Ordinals)", - "MMT": "Master MIX Token", + "MMT": "MeMusic", "MMTM": "Momentum", "MMUI": "MetaMUI", "MMULTI": "Multichain (via Multichain Cross-Chain Router)", @@ -9009,11 +10183,12 @@ "MNB": "MoneyBag", "MNBR": "MN Bridge", "MNC": "MainCoin", - "MND": "Mound Token", + "MND": "Mind", "MNDCC": "Mondo Community Coin", "MNDE": "Marinade", "MNE": "Minereum", "MNEE": "MNEE USD Stablecoin ", + "MNEMO": "Mnemonics", "MNET": "MINE Network", "MNFT": "Mongol NFT", "MNFTS": "Marvelous NFTs", @@ -9024,7 +10199,9 @@ "MNR": "Mineral", "MNRB": "MoneyRebel", "MNRCH": "Monarch", + "MNRY": "Moonray", "MNS": "Monnos", + "MNSRY": "MANSORY", "MNST": "MoonStarter", "MNTA": "MantaDAO", "MNTC": "Manet Coin", @@ -9052,7 +10229,7 @@ "MOBIU": "Mobius Money", "MOBU": "MOBU", "MOBX": "MOBIX", - "MOBY": "Moby", + "MOBY": "Moby AI", "MOBYONBASE": "Moby", "MOBYONBASEV1": "Moby v1", "MOC": "Mossland", @@ -9067,6 +10244,7 @@ "MODC": "Modclub", "MODE": "Mode", "MODEL": "Model Labs", + "MODERN": "bitcoin-modern", "MODEX": "Modex", "MODU": "Modular Wallet", "MODUM": "Modum", @@ -9086,13 +10264,16 @@ "MOGT": "MOG TRUMP", "MOGU": "Mogu", "MOGUL": "Mogul Productions", + "MOGULV1": "Mogul Productions v1", "MOGUT": "Mogutou", "MOGX": "Mogu", "MOH": "Medal of Honour", "MOI": "MyOwnItem", "MOIN": "MoinCoin", "MOJI": "Moji", - "MOJO": "Mojocoin", + "MOJO": "Planet Mojo", + "MOJOB": "Mojo on Base", + "MOJOCOIN": "Mojocoin", "MOK": "MocktailSwap", "MOL": "Molecule", "MOLA": "MoonLana", @@ -9104,18 +10285,23 @@ "MOMA": "Mochi Market", "MOMIJI": "MAGA Momiji", "MOMO": "MOMO 2.0", + "MOMO2025": "momo", "MON": "MON Protocol", "MONA": "MonaCoin", "MONAIZE": "Monaize", "MONARCH": "TRUEMONARCH", + "MONART": "Monart", "MONAV": "Monavale", "MONB": "MonbaseCoin", "MONDO": "mondo", + "MONEROCHAN": "Monerochan", + "MONET": "Claude Monet Memeory Coin", "MONETA": "Moneta", "MONEY": "MoneyCoin", "MONEYBEE": "MONEYBEE", "MONEYBYTE": "MoneyByte", - "MONEYIMT": "MoneyToken", + "MONEYGOD": "Money God One", + "MONEYTOKEN": "MoneyToken", "MONF": "Monfter", "MONG": "MongCoin", "MONG20": "Mongoose 2.0", @@ -9130,6 +10316,7 @@ "MONKEY": "Monkey", "MONKEYS": "Monkeys Token", "MONKU": "Monku", + "MONKY": "Wise Monkey", "MONO": "MonoX", "MONOLITH": "Monolith", "MONONOKEINU": "Mononoke Inu", @@ -9144,20 +10331,29 @@ "MOOBIFI": "Staked BIFI", "MOOCAT": "MooCat", "MOODENG": "Moo Deng (moodengsol.com)", + "MOODENGBNB": "MOODENG (moodengbnb.com)", + "MOODENGSBS": "Moo Deng (moodeng.sbs)", "MOODENGSPACE": "MOO DENG", + "MOODENGVIP": "MOO DENG (moodeng.vip)", "MOODENGWIF": "MOODENGWIF", "MOOI": "Moonai", "MOOLA": "Degen Forest", + "MOOLAH": "Moolah", "MOOLYA": "moolyacoin", + "MOOMEME": "MOO MOO", + "MOOMOO": "MOOMOO THE BULL", "MOON": "r/CryptoCurrency Moons", "MOONARCH": "Moonarch", "MOONB": "Moon Base", + "MOONBEANS": "Moonbeans", "MOONBI": "Moonbix", "MOONBIX": "MOONBIX MEME", "MOONC": "MoonCoin", + "MOONCOIN": "Mooncoin", "MOOND": "Dark Moon", "MOONDAY": "Moonday Finance", "MOONDO": "MOON DOGE", + "MOONDOGE": "MOONDOGE", "MOONED": "MoonEdge", "MOONER": "CoinMooner", "MOONEY": "Moon DAO", @@ -9165,6 +10361,7 @@ "MOONION": "Moonions", "MOONKIZE": "MoonKize", "MOONLIGHT": "Moonlight Token", + "MOONPIG": "Moonpig", "MOONR": "PulseMoonR", "MOONS": "Sailor Moons", "MOONSHOT": "Moonshot", @@ -9176,27 +10373,33 @@ "MOPS": "Mops", "MOR": "Morpheus", "MORA": "Meliora", - "MORE": "More Coin", + "MORE": "Moonveil", + "MORECOIN": "More Coin", "MOREGEN": "MoreGen FreeMoon", "MORFEY": "Morfey", + "MORI": "MORI COIN", "MOROS": "MOROS NET", "MORPH": "Morpheus Token", + "MORPHIS": "MorphIS", "MORPHO": "Morpho", "MORRA": "Morra", "MORSE": "Morse", + "MORTY": "Morty", "MOS": "MOS Coin", + "MOSS": "MOSS AI", "MOST": "MOST Global", - "MOT": "Olympus Labs", + "MOT": "Mobius Token", "MOTA": "MotaCoin", "MOTG": "MetaOctagon", "MOTH": "MOTH", "MOTHER": "Mother Iggy", "MOTI": "Motion", "MOTO": "Motocoin", + "MOUND": "Mound Token", "MOUTAI": "Moutai", "MOV": "MovieCoin", "MOVD": "MOVE Network", - "MOVE": "MarketMove", + "MOVE": "Movement", "MOVER": "Mover", "MOVEUSD": "MoveMoney USD", "MOVEY": "Movey", @@ -9207,8 +10410,10 @@ "MOWA": "Moniwar", "MOXIE": "Moxie", "MOYA": "MOYA", - "MOZ": "Mozik", - "MP": "Membership Placeholders", + "MOZ": "Lumoz token", + "MOZA": "Mozaic", + "MOZIK": "Mozik", + "MP": "MerlinSwap Token", "MP3": "MP3", "MPAA": "MPAA", "MPAD": "MultiPad", @@ -9225,14 +10430,17 @@ "MPM": "Monopoly Meta", "MPRO": "MediumProject", "MPS": "Mt Pelerin Shares", - "MPT": "Meetple", + "MPT": "Miracleplay Token", + "MPTV1": "Miracleplay Token v1", "MPWR": "Empower", "MPX": "Morphex", "MPXT": "Myplacex", "MQL": "MiraQle", "MQST": "MonsterQuest", "MR": "Meta Ruffy", + "MRB": "MoonRabbits", "MRBASED": "MrBased", + "MRBEAST": "X Super Official CEO", "MRBOB": "MR BOB COIN", "MRCH": "MerchDAO", "MRCR": "Mercor Finance", @@ -9241,6 +10449,7 @@ "MRHB": "MarhabaDeFi", "MRI": "Marshall Inu", "MRK": "MARK.SPACE", + "MRKX": "Merck xStock", "MRM": "Mr Mint", "MRN": "Mercoin", "MRNA": "Moderna", @@ -9249,9 +10458,11 @@ "MRS": "Metars Genesis", "MRSA": "MrsaCoin", "MRSMIGGLES": "Mrs Miggles", + "MRST": "Mars Token", "MRT": "MinersReward", "MRUN": "Metarun", "MRV": "Macroverse", + "MRVLX": "Marvell xStock", "MRX": "Metrix Coin", "MRXB": "Wrapped BNB Metrix", "MRXE": "Wrapped ETH Metrix", @@ -9263,13 +10474,14 @@ "MSCT": "MUSE ENT NFT", "MSD": "MSD", "MSFT": "Microsoft 6900", + "MSFTX": "Microsoft xStock", "MSG": "MsgSender", "MSGO": "MetaSetGO", "MSHD": "MASHIDA", "MSHEESHA": "Sheesha Finance Polygon", "MSHIB": "Magic Shiba Starter", "MSHIP": "MetaShipping", - "MSN": "Manson Coin", + "MSN": "Meson.Network", "MSOL": "Marinade Staked SOL", "MSOT": "BTour Chain", "MSP": "Mothership", @@ -9280,10 +10492,11 @@ "MSTAR": "MerlinStarter", "MSTETH": "Eigenpie mstETH", "MSTO": "Millennium Sapphire", + "MSTRX": "MicroStrategy xStock", "MSU": "MetaSoccer", "MSUSHI": "Sushi (Multichain)", "MSWAP": "MoneySwap", - "MT": "MyToken", + "MT": "Mint Token", "MTA": "Meta", "MTB": "MetaBridge", "MTBC": "Metabolic", @@ -9296,6 +10509,7 @@ "MTGT": "MTG Token", "MTGX": "Montage Token", "MTH": "Monetha", + "MTHB": "MTHAIBAHT", "MTHD": "Method Finance", "MTHN": "MTH Network", "MTIK": "MatikaToken", @@ -9304,11 +10518,14 @@ "MTL": "Metal", "MTLM3": "Metal Music v3", "MTLS": "eMetals", + "MTLV1": "Metal v1", "MTLX": "Mettalex", "MTMS": "MTMS Network", "MTN": "TrackNetToken", "MTO": "Merchant Token", + "MTOS": "MomoAI", "MTP": "Macro Protocol", + "MTPLF": "Metaplanet", "MTR": "Meter Stable", "MTRA": "MetaRare", "MTRC": "ModulTrade", @@ -9322,6 +10539,7 @@ "MTT": "MulTra", "MTTCOIN": "Money of Tommorow, Today", "MTV": "MultiVAC", + "MTV1": "Mint Club", "MTVT": "Metaverser", "MTW": "Meta Space 2045", "MTX": "Matryx", @@ -9330,6 +10548,11 @@ "MTZ": "Monetizr", "MU": "Miracle Universe", "MUA": "MUA DAO", + "MUB": "Mubarak on Base", + "MUBA": "mubarak", + "MUBAR": "mubarak", + "MUBARAK": "mubarak", + "MUBARAKAH": "Mubarakah", "MUBI": "Multibit", "MUC": "Multi Universe Central", "MUDOL2": "Hero Blaze: Three Kingdoms", @@ -9345,6 +10568,7 @@ "MUN": "MUNcoin", "MUNCH": "Munch Token", "MUNCHY": "Boys Club Munchy", + "MUNDI": "Salvator Mundi", "MUNI": "Uniswap Protocol Token (Multichain)", "MUNITY": "Metahorse Unity", "MUNK": "Dramatic Chipmunk", @@ -9360,6 +10584,7 @@ "MUSICAI": "MusicAI", "MUSICOIN": "Musicoin", "MUSK": "Musk", + "MUSKAI": "Musk AI Agent", "MUSKMEME": "MUSK MEME", "MUSKVSZUCK": "Cage Match", "MUST": "MUST Protocol", @@ -9378,6 +10603,7 @@ "MVG": "Mad Viking Games", "MVI": "Metaverse Index", "MVL": "MVL", + "MVOYA": "VOYA (Merlin Bridge)", "MVP": "MAGA VP", "MVPC": "MVP Coin", "MVRS": "Meta MVRS", @@ -9391,12 +10617,16 @@ "MWC": "MimbleWimbleCoin", "MWCC": "Metaworld", "MWD": "MEW WOOF DAO", + "MWETH": "Moonwell Flagship ETH (Morpho Vault)", + "MWH": "Melania Wif Hat", "MX": "MX Token", "MXC": "Machine Xchange Coin", "MXD": "Denarius", "MXGP": "MXGP Fan Token", "MXM": "Maximine", + "MXNA": "Machina", "MXNB": "MXNB", + "MXNBC": "Rekt Burgundy by Virtuals", "MXNT": "Tether MXNt", "MXRP": "Monsta XRP", "MXT": "MixTrust", @@ -9411,6 +10641,7 @@ "MYDFS": "MyDFS", "MYID": "My Identity Coin", "MYL": "MyLottoCoin", + "MYLINX": "Linx", "MYLO": "MYLOCAT", "MYNE": "ITSMYNE", "MYO": "Mycro", @@ -9426,7 +10657,9 @@ "MYT": "Mytrade", "MYTH": "Mythos", "MYTHTOKEN": "Myth Token", + "MYTOKEN": "MyToken", "MYTV": "MyTVchain", + "MYX": "MYX Finance", "MZC": "MazaCoin", "MZERO": "MetaZero", "MZG": "Moozicore", @@ -9437,6 +10670,7 @@ "Medu": "Medusa", "N0031": "nYFI", "N1": "NFTify", + "N3": "Network3", "N3DR": "NeorderDAO ", "N64": "N64", "N7": "Number7", @@ -9446,12 +10680,15 @@ "NACHO": "Nacho the 𐤊at", "NADA": "NADA Protocol Token", "NAFT": "Nafter", + "NAGANO": "nagano", "NAH": "Strayacoin", "NAI": "Nuklai", + "NAIIVE": "Naiive", "NAILONG": "Nailong", + "NAIT": "Node AI Token", "NAKA": "Nakamoto Games", "NAKAV1": "Nakamoto Games v1", - "NALA": "Not a lion, a...", + "NALA": "NALA", "NALS": "NALS (Ordinals)", "NAM": "Namacoin", "NAME": "PolkaDomain", @@ -9494,9 +10731,11 @@ "NAWS": "NAWS.AI", "NAX": "NextDAO", "NAYM": "NAYM", + "NAYUTA": "Nayuta Coin", "NAZ": "NAZDAQ", "NAZA": "NAZA", "NAZAR": "NAZAR PROTOCOL", + "NAZIELON": "NAZI ELON", "NBABSC": "NBA BSC", "NBAI": "Nebula AI", "NBAR": "NOBAR", @@ -9513,7 +10752,7 @@ "NBS": "New BitShares", "NBT": "NanoByte", "NBXC": "Nibble", - "NC": "Nayuta Coin", + "NC": "Nodecoin", "NCA": "NeuroCrypto Ads", "NCASH": "Nucleus Vision", "NCAT": "Neuracat", @@ -9537,6 +10776,7 @@ "NDLC": "NeedleCoin", "NDN": "NDN Link", "NDOGE": "NinjaDoge", + "NDQ": "Nasdaq666", "NDR": "Node Runners", "NDS": "NodeStation AI", "NDX": "Indexed Finance", @@ -9551,8 +10791,9 @@ "NEBU": "Nebuchadnezzar", "NEC": "Nectar", "NEER": "Metaverse.Network Pioneer", - "NEET": "NEET Finance", + "NEET": "Not in Employment, Education, or Training", "NEETCOIN": "Neetcoin", + "NEETFINANCE": "NEET Finance", "NEF": "NefariousCoin", "NEFTIPEDIA": "NEFTiPEDiA", "NEFTY": "NeftyBlocks", @@ -9570,9 +10811,11 @@ "NEIROLOL": "Neiro", "NEIROONB": "Neiro on Base", "NEKI": "Neki Token", - "NEKO": "The Neko", + "NEKO": "NeonNeko", + "NEKOARC": "Neko Arc", "NEKOIN": "Nekoin", "NEKOS": "Nekocoin", + "NEKTAR": "Nektar Token", "NEMO": "NEMO", "NEMS": "The Nemesis", "NEO": "NEO", @@ -9589,13 +10832,15 @@ "NERF": "Neural Radiance Field", "NERO": "Nero Token", "NERVE": "NERVE", + "NES": "Nest AI", "NESS": "Ness LAB", "NEST": "Nest Protocol", "NESTREE": "Nestree", "NESTV1": "Nest Protocol v1", - "NET": "NetCoin", + "NET": "NET", "NETA": "Negative Tax", "NETC": "NetworkCoin", + "NETCOI": "NetCoin", "NETCOIN": "Netcoincapital", "NETCOINV1": "Netcoincapital v1", "NETK": "Netkoin", @@ -9606,9 +10851,11 @@ "NETZ": "MainnetZ", "NETZ1": "NETZERO", "NEU": "Neumark", + "NEUR": "neur.sh", "NEURA": "Neurahub", "NEURAL": "NeuralAI", "NEURALINK": "Neuralink", + "NEURO": "NeuroWeb", "NEURON": "Cerebrum DAO", "NEURONI": "Neuroni AI", "NEUROS": "Shockwaves", @@ -9620,10 +10867,10 @@ "NEVANETWORK": "Neva", "NEVE": "NEVER SURRENDER", "NEVER": "neversol", - "NEW": "Newton", "NEWB": "Newbium", "NEWBV1": "Newbium v1", "NEWC": "New Cat", + "NEWERASOL": "New Era AI", "NEWG": "NewGold", "NEWM": "NEWM", "NEWO": "New Order", @@ -9632,12 +10879,15 @@ "NEWS": "PUBLISH", "NEWSL": "Newsly", "NEWSTOKENS": "NewsTokens", + "NEWT": "Newton Protocol", "NEWTON": "Newtonium", "NEX": "Nash Exchange", "NEXA": "Nexa", "NEXAI": "NexAI", "NEXBOX": "NexBox", "NEXBT": "Native XBTPro Exchange Token", + "NEXD": "Nexade", + "NEXEA": "NEXEA", "NEXG": "NexGami", "NEXM": "Nexum", "NEXMI": "NexMillionaires", @@ -9647,17 +10897,22 @@ "NEXTEX": "Next.exchange Token", "NEXTEXV1": "Next.exchange Token v1", "NEXTV1": "Connext Network", + "NEXUS": "Nexus", "NEXUSAI": "NexusAI", "NEXXO": "Nexxo", - "NEZHA": "NezhaToken", + "NEZHA": "NEZHA", + "NEZHATOKEN": "NezhaToken", "NFAI": "Not Financial Advice", + "NFAIV1": "Not Financial Advice v1", "NFCR": "NFCore", "NFD": "Feisty Doge NFT", "NFE": "Edu3Labs", + "NFLXX": "Netflix xStock", "NFM": "NFMart", "NFN": "Nafen", "NFNT": "NFINITY AI", "NFP": "NFPrompt", + "NFPV1": "Token NFPrompt Token v1", "NFT": "APENFT", "NFT11": "NFT11", "NFTART": "NFT Art Finance", @@ -9671,15 +10926,15 @@ "NFTLOOT": "NFTLootBox", "NFTM": "NFTMart Token", "NFTN": "NFTNetwork", - "NFTP": "NFT", + "NFTPROTOCOL": "NFT", "NFTS": "NFT STARS", "NFTSTYLE": "NFTStyle", - "NFTT": "NFT", "NFTX": "NFTX", "NFTXHI": "NFTX Hashmasks Index", "NFTY": "NFTY Token", "NFTYP": "NFTY DeFi Protocol", "NFUP": "Natural Farm Union Protocol", + "NFX": "Nova Fox", "NFXC": "NFX Coin", "NFY": "Non-Fungible Yearn", "NGA": "NGA Tiger", @@ -9692,7 +10947,9 @@ "NHCT": "Nano Healthcare Token", "NHI": "Non Human Intelligence", "NHT": "Neighbourhoods", + "NIANNIAN": "NianNian", "NIAO": "NIAO", + "NIBBLES": "Nibbles", "NIBI": "Nibiru Chain", "NIC": "NewInvestCoin", "NICE": "Nice", @@ -9711,10 +10968,14 @@ "NIIFI": "NiiFi", "NIK": "NIKPLACE", "NIKO": "NikolAI", + "NIL": "Nillion", + "NILA": "MindWave", "NILE": "Nile", "NIM": "Nimiq", + "NIMBUS": "Nimbus AI", "NIMFA": "Nimfamoney", "NIN": "Next Innovation", + "NINA": "NINA", "NINJ": "Ninja Protocol", "NINJA": "Dog Wif Nunchucks", "NINJACAT": "NinjaCat", @@ -9730,11 +10991,13 @@ "NIPPY": "Cat On Catnip", "NIQAB": "NIQAB WORLD ORDER", "NIRV": "Nirvana NIRV", + "NIRVA": "Nirvana", "NIT": "Nesten", "NITEFEEDER": "Nitefeeder", "NITO": "Nitroken", "NITRO": "Nitro League", "NITROE": "NitroEX", + "NITROFROG": "Nitro", "NITROG": "Nitro", "NIX": "NIX", "NIZA": "Niza Global", @@ -9744,7 +11007,7 @@ "NKN": "NKN", "NKT": "NakomotoDark", "NKYC": "NKYC Token", - "NLC": "NoLimitCoin", + "NLC": "Nelore Coin", "NLC2": "NoLimitCoin", "NLG": "Gulden", "NLINK": "Neuralink", @@ -9772,12 +11035,17 @@ "NOA": "NOA PLAY", "NOAH": "NOAHCOIN", "NOBL": "NobleCoin", + "NOBODY": "Nobody Sausage", "NOBS": "No BS Crypto", + "NOC": "Nono Coin", "NOCHILL": "AVAX HAS NO CHILL", - "NODE": "Whole Network", + "NODE": "NodeOps", + "NODELYAI": "NodelyAI", + "NODESYNAPSE": "NodeSynapse", "NODIDDY": "NODIDDY", "NODIS": "Nodis", "NODL": "Nodle Network", + "NOEL": "AskNoel", "NOGS": "Noggles", "NOHAT": "DogWifNoHat", "NOIA": "Syntropy", @@ -9785,8 +11053,11 @@ "NOIZ": "NOIZ", "NOKA": "Noka Solana AI", "NOKU": "NOKU Master token", + "NOKUV1": "NOKU Master token v1", + "NOL": "NORDO MILE", "NOLA": "Nola", - "NOM": "Finom NOM Token", + "NOM": "Onomy Protocol", + "NOMAI": "nomAI by Virtuals", "NOMNOM": "nomnom", "NOMOX": "NOMOEX Token", "NONE": "None Trading", @@ -9795,9 +11066,11 @@ "NOODS": "Noods", "NOOOO": "NOOOO", "NOOT": "NOOT (Ordinals)", + "NOPAIN": "No Pain No Gain", "NOR": "Noir", "NORA": "SnowCrash Token", "NORD": "Nord Finance", + "NORDO": "Greenland Rare Bear", "NORMIE": "Normie", "NORMUS": "NORMUS", "NOS": "Nosana", @@ -9805,6 +11078,7 @@ "NOSO": "Noso", "NOT": "Notcoin", "NOTAI": "NOTAI", + "NOTALION": "Not a lion, a...", "NOTC": "NOT", "NOTDOG": "NOTDOG", "NOTE": "Notional Finance", @@ -9845,7 +11119,7 @@ "NRV": "Nerve Finance", "NRVE": "Narrative", "NRX": "Neironix", - "NS": "NodeSynapse", + "NS": "SuiNS Token", "NS2DRP": "New Silver Series 2 DROP", "NSBT": "Neutrino Token", "NSD": "Nasdacoin", @@ -9879,6 +11153,7 @@ "NTR": "Nether", "NTRN": "Neutron", "NTS": "Notarised", + "NTV": "NativToken", "NTVRK": "Netvrk", "NTWK": "Network Token", "NTX": "NuNet", @@ -9895,8 +11170,10 @@ "NULS": "Nuls", "NUM": "Numbers Protocol", "NUMBERS": "NumbersCoin", - "NUMI": "Numitor", + "NUMI": "NUMINE Token", + "NUMITOR": "Numitor", "NUR": "Nurcoin", + "NURA": "Nura Labs", "NUSA": "Nusa", "NUSD": "Nomin USD", "NUT": "Native Utility Token", @@ -9907,11 +11184,15 @@ "NUUM": "MNet", "NUX": "Peanut", "NVA": "Neeva Defi", + "NVB": "NovaBank", "NVC": "NovaCoin", + "NVDAX": "NVIDIA xStock", "NVDX": "Nodvix", "NVG": "NightVerse Game", + "NVG8": "Navigate", "NVIR": "NvirWorld", "NVL": "Nevula", + "NVOX": "Novo Nordisk xStock", "NVOY": "Envoy", "NVS": "Navis", "NVST": "NVO", @@ -9931,6 +11212,7 @@ "NXM": "Nexus Mutual", "NXMC": "NextMindCoin", "NXN": "Naxion", + "NXPC": "NXPC", "NXQ": "NexQloud", "NXRA": "AllianceBlock Nexera", "NXS": "Nexus", @@ -9939,7 +11221,8 @@ "NXTT": "Next Earth", "NXTTY": "NXTTY", "NYA": "Nya", - "NYAN": "NyanCoin", + "NYAN": "NYAN", + "NYANCOIN": "NyanCoin", "NYANDOGE": "NyanDOGE International", "NYANTE": "Nyantereum International", "NYBBLE": "Nybble", @@ -9949,6 +11232,7 @@ "NYEX": "Nyerium", "NYM": "Nym Token", "NYN": "NYNJA", + "NYS": "node.sys", "NYX": "NYXCOIN", "NYXC": "Nyxia AI", "NYZO": "Nyzo", @@ -9964,15 +11248,18 @@ "OAK": "Acorn Collective", "OAS": "Oasis City", "OASC": "Oasis City", + "OASI": "Oasis Metaverse", "OASIS": "Oasis", "OAT": "OAT Network", "OATH": "OATH Protocol", "OAX": "Oax", "OB1INCH": "1inch (OmniBridge)", + "OBABYTRUMP": "Official Baby Trump", "OBEMA": "burek obema", "OBI": "Orbofi AI", "OBICOIN": "OBI Real Estate", "OBITS": "Obits Coin", + "OBOL": "Obol Network", "OBOT": "Obortech", "OBROK": "OBRok", "OBS": "One Basis Cash", @@ -9982,12 +11269,13 @@ "OBSUSHI": "Sushi (OmniBridge)", "OBT": "Oobit", "OBTC": "Obitan Chain", + "OBVIOUS": "OBVIOUS COIN", "OBX": "OpenBlox", "OC": "OrangeCoin", "OCADA": "OCADA.AI", "OCAI": "Onchain AI", "OCAVU": "Ocavu Network Token", - "OCB": "BLOCKMAX", + "OCB": "OneCoinBuy", "OCC": "OccamFi", "OCD": "On-Chain Dynamics", "OCE": "OceanEX Token", @@ -9997,6 +11285,7 @@ "OCICAT": "OciCat", "OCL": "Oceanlab", "OCN": "Odyssey", + "OCNEST": "OcNest AI", "OCO": "Owners Casino Online", "OCP": "Omni Consumer Protocols", "OCPR": "OC Protocol", @@ -10007,8 +11296,9 @@ "OCTAVUS": "Octavus Prime", "OCTAX": "OctaX", "OCTI": "Oction", - "OCTO": "OctoFi", - "OCTOC": "OctoCoin", + "OCTO": "OctonetAI", + "OCTOCOIN": "Octocoin", + "OCTOF": "OctoFi", "OCTOIN": "Octoin Coin", "OCW": "Online Cold Wallet", "OCX": "Original Crypto Coin", @@ -10021,6 +11311,7 @@ "ODMC": "ODMCoin", "ODN": "Obsidian", "ODNT": "Old Dogs New Tricks", + "ODOS": "Odos", "ODS": "Odesis", "ODX": "ODX Token", "ODYS": "OdysseyWallet", @@ -10030,8 +11321,15 @@ "OFCR": "CryptoPolice", "OFE": "Ofero", "OFF": "BlastOff", + "OFFI": "Official Elon Coin", + "OFFIC": "OFFICIAL SIMPSON", + "OFFICI": "OFFICIAL BARRON", + "OFFICIA": "Official Elon Coin", + "OFFICIALUSA": "Official USA Token", "OFN": "Openfabric AI", + "OFT": "ONFA", "OG": "OG Fan Token", + "OGC": "OGCommunity", "OGCINU": "The OG Cheems Inu", "OGD": "OLYMPIC GAMES DOGE", "OGGIE": "Oggie", @@ -10056,6 +11354,8 @@ "OHNOGG": "OHNHO (ohno.gg)", "OHO": "OHO", "OICOIN": "Osmium Investment Coin", + "OIIAOIIA": "spinning cat", + "OIK": "Space Nation", "OIL": "Oiler", "OILD": "OilWellCoin", "OILX": "OilX Token", @@ -10075,6 +11375,7 @@ "OKSE": "Okse", "OKT": "OKT Chain", "OL": "Open Loot", + "OLA": "Ola", "OLAF": "Olaf Token", "OLAND": "Oceanland", "OLAS": "Autonolas", @@ -10084,6 +11385,7 @@ "OLEA": "Olea Token", "OLEV1": "OpenLeverage v1", "OLIVE": "Olive", + "OLIVIA": "AIGOV", "OLOID": "OLOID", "OLT": "OneLedger", "OLV": "OldV", @@ -10091,14 +11393,18 @@ "OLY": "Olyseum", "OLYMP": "OlympCoin", "OLYMPE": "OLYMPÉ", + "OLYMPUSLABS": "Olympus Labs", + "OLYN": "Olyn by Virtuals", "OM": "MANTRA", "OMA": "OmegaCoin", + "OMALLEY": "O'Malley", "OMAX": "Omax", "OMAXV1": "Omax v1", "OMC": "Omchain", "OMD": "OneMillionDollars", "OME": "o-mee", "OMEGA": "OMEGA", + "OMEGAX": "Ome‎gaX He‎alth", "OMG": "OMG Network", "OMGC": "OmiseGO Classic", "OMI": "ECOMI", @@ -10126,17 +11432,20 @@ "ONC": "One Cash", "ONCH": "OnchainPoints.xyz", "ONDO": "Ondo", + "ONDOAI": "Ondo DeFAI", "ONE": "Harmony", + "ONEROOT": "OneRoot Network", "ONES": "OneSwap DAO", "ONET": "ONE Token", "ONEX": "ONE TECH", - "ONG": "SoMee.Social", + "ONF": "ONF Token", "ONGAS": "Ontology Gas", "ONI": "ONINO", "ONIG": "Onigiri", "ONIGIRI": "Onigiri The Cat", "ONION": "DeepOnion", "ONIT": "ONBUFF", + "ONIX": "Onix", "ONL": "On.Live", "ONLINE": "Onlinebase", "ONLY": "OnlyCam", @@ -10146,8 +11455,9 @@ "ONS": "One Share", "ONSTON": "Onston", "ONT": "Ontology", + "ONTACT": "OnTact", "ONUS": "ONUS", - "ONX": "Onix", + "ONX": "OnX.finance", "OOE": "OpenOcean", "OOFP": "OOFP", "OOGI": "OOGI", @@ -10160,10 +11470,12 @@ "OOW": "OPP Open WiFi", "OP": "Optimism", "OPA": "Option Panda Platform", + "OPAI": "Optopia AI", "OPAIG": "OvalPixel", "OPC": "OP Coin", "OPCA": "OP_CAT(BIP-420)", "OPCAT": "OPCAT", + "OPCATVIP": "OP_CAT", "OPCT": "Opacity", "OPEN": "Open Custody Protocol", "OPENAI": "OpenAI ERC", @@ -10176,6 +11488,7 @@ "OPENW": "OpenWorld", "OPENX": "OpenSwap Optimism Token", "OPEPE": "Optimism PEPE", + "OPERATOR": "OpenAI Agent", "OPES": "Opes", "OPET": "ÕpetFoundation", "OPEX": "Optherium Token", @@ -10185,10 +11498,12 @@ "OPMND": "Open Mind Network", "OPN": "OPEN Ticketing Ecosystem", "OPNN": "Opennity", + "OPNV1": "GET Protocol", "OPP": "Opporty", "OPS": "Octopus Protocol", "OPSC": "OpenSourceCoin", "OPSEC": "OpSec", + "OPSECV1": "OpSec v1", "OPSV1": "Octopus Protocol v1", "OPSV2": "Octopus Protocol v2", "OPT": "Opus", @@ -10199,14 +11514,19 @@ "OPTIG": "Catgirl Optimus", "OPTIM": "Optimus X", "OPTIMOUSE": "Optimouse", + "OPTIMUS": "Optimus", + "OPTIO": "Optio", "OPTION": "OptionCoin", "OPU": "Opu Coin", "OPUL": "Opulous", + "OPUS": "Opus", "OPV": "OpenLive NFT", "OPXVEVELO": "OpenX Locked Velo", - "ORA": "Oracolxor", + "ORA": "ORA Coin", "ORACLE": "Oracle AI", "ORACLECHAIN": "OracleChain", + "ORACLER": "Oracler", + "ORACOLXOR": "Oracolxor", "ORACUL": "Oracul Ai", "ORAI": "Oraichain Token", "ORAIX": "OraiDEX", @@ -10214,15 +11534,19 @@ "ORAO": "ORAO Network", "ORARE": "OneRare", "ORB": "KlayCity ORB", + "ORBI": "Orbs", "ORBIS": "Orbis", "ORBIT": "Orbit Protocol", "ORBITCOIN": "Orbitcoin", "ORBK": "Ordibank", "ORBR": "Orbler", "ORBS": "Orbs", - "ORBT": "Orbitt Pro", + "ORBT": "Orbitt Token", + "ORBTV1": "Orbitt Pro", "ORC": "Orbit Chain", "ORCA": "Orca", + "ORCAI": "ORCA", + "ORCLX": "Oracle xStock", "ORD": "ordinex", "ORDER": "Orderly Network", "ORDI": "Ordinals ", @@ -10238,6 +11562,7 @@ "ORGT": "Organic Token", "ORI": "Origami", "ORIGIN": "Origin Foundation", + "ORIGINA": "Original Gangsters", "ORION": "Orion Money", "ORKL": "Orakler", "ORLY": "OrlyCoin", @@ -10245,6 +11570,7 @@ "ORME": "Ormeus Coin", "ORMO": "Ormolus", "ORN": "Orion Protocol", + "ORNG": "Juice Town", "ORNJ": "Orange", "ORO": "Operon Origins", "OROC": "Orocrypt", @@ -10270,9 +11596,11 @@ "OSIS": "OSIS", "OSK": "OSK", "OSKDAO": "OSK DAO", + "OSKY": "OpenSky Token", "OSL": "OSL AI", "OSMI": "OSMI", "OSMO": "Osmosis", + "OSOL": "OSOL", "OSQTH": "Opyn Squeeth", "OSS": "OSSChain", "OST": "OST", @@ -10286,6 +11614,7 @@ "OTO": "OTOCASH", "OTSEA": "OTSea", "OTT": "Coost", + "OTTERHOME": "OtterHome", "OTTERSPACE": "Otter Space", "OTX": "Octanox", "OUCHI": "OUCHI", @@ -10296,16 +11625,20 @@ "OUSE": "OUSE Token", "OUSG": "OUSG", "OUT": "Netscouters", + "OUTL": "Outlanders Token", + "OVATO": "Ovato", "OVC": "OVCODE", + "OVER": "OverProtocol", "OVERLORD": "Overlord", "OVN": "Overnight", - "OVO": "Ovato", + "OVO": "OVO", "OVR": "Ovr", "OWC": "Oduwa", "OWD": "Owlstand", "OWL": "OWL Token", - "OWN": "Ownly", + "OWN": "OTHERWORLD", "OWNDATA": "OWNDATA", + "OWNLY": "Ownly", "OWO": "SoMon", "OX": "Open Exchange Token", "OXAI": "OxAI.com", @@ -10330,8 +11663,10 @@ "OZONEC": "Ozonechain", "OZP": "OZAPHYRE", "P": "PUPS•WORLD•PEACE", + "P1": "PEPE ONE", "P202": "Project 202", "P2PS": "P2P Solutions Foundation", + "P33L": "THE P33L", "P3D": "3DPass", "P404": "Potion 404", "PAAL": "PAAL AI", @@ -10346,23 +11681,28 @@ "PACOCA": "Pacoca", "PACP": "PAC Protocol", "PACT": "impactMarket", + "PACTV1": "impactMarket v1", "PAD": "NearPad", "PAF": "Pacific", "PAGE": "Page", - "PAI": "Project Pai", + "PAI": "ParallelAI", "PAID": "PAID Network", "PAIDV1": "PAID Network v1", + "PAIN": "PAIN", "PAINT": "MurAll", "PAIRED": "PairedWorld", "PAJAMAS": "The First Youtube Cat", "PAK": "Pakcoin", "PAL": "PolicyPal Network", "PALAI": "PaladinAI", + "PALCOIN": "Palcoin Ventures", + "PALCOINV1": "PALCOIN Venture Capital v1", "PALE": "Palette", "PALET": "Palette", "PALG": "PalGold", "PALLA": "Pallapay", "PALM": "PaLM AI", + "PALMECO": "Palm Economy", "PALMP": "PalmPay", "PALMV1": "PaLM AI v1", "PALMY": "Palmy", @@ -10391,6 +11731,7 @@ "PAPI": "Papi", "PAPO": "PAPO NINJA", "PAPPAY": "PAPPAY", + "PAPPLE": "Pineapple", "PAPU": "Papu Token", "PAPUSHA": "Papusha", "PAR": "Parachute", @@ -10413,6 +11754,8 @@ "PARQ": "PARQ", "PARRY": "Parry Parrot", "PART": "Particl", + "PARTI": "PARTI Token", + "PARTY": "Party", "PAS": "Passive Coin", "PASC": "Pascal Coin", "PASG": "Passage", @@ -10422,6 +11765,7 @@ "PATEK": "Silly Patek", "PATEX": "Patex", "PATH": "PathDAO", + "PATLU": "Patlu", "PATRIOT": "Patriot", "PATTON": "Patton", "PAUL": "Elephant Penguin", @@ -10429,8 +11773,10 @@ "PAVO": "Pavocoin", "PAW": "PAWSWAP", "PAWPAW": "PawPaw", - "PAWS": "PawStars", + "PAWS": "PAWS", + "PAWSE": "PAWSE", "PAWSTA": "dogeatingpasta", + "PAWSTARS": "PawStars", "PAWTH": "Pawthereum", "PAXE": "Paxe", "PAXEX": "PAXEX", @@ -10439,6 +11785,7 @@ "PAXW": "pax.world", "PAY": "TenX", "PAYB": "Paybswap", + "PAYCENT": "Paycent", "PAYCON": "Paycon", "PAYD": "PAYD", "PAYN": "PayNet Coin", @@ -10460,7 +11807,9 @@ "PBR": "PolkaBridge", "PBRV1": "PolkaBridge v1", "PBT": "Primalbase", + "PBTC": "pTokens BTC", "PBTC35A": "pBTC35A", + "PBTCV1": "pTokens BTC v1", "PBUX": "Playbux", "PBX": "Probinex", "PBXV1": "Probinex v1", @@ -10469,7 +11818,7 @@ "PCCM": "Poseidon Chain", "PCD": " Phecda", "PCE": "PEACE COIN", - "PCH": "POPCHAIN", + "PCH": "Pichi", "PCHS": "Peaches.Finance", "PCI": "PayProtocol Paycoin", "PCKB": "pCKB (via Godwoken Bridge from CKB)", @@ -10503,6 +11852,7 @@ "PEA": "Pea Farm", "PEACH": "Based Peaches", "PEACHY": "Peachy", + "PEAGUY": "The Pea Guy by Virtuals", "PEAK": "PEAKDEFI", "PEAN": "Peanut the Squirrel (peanut-token.xyz)", "PEANIE": "Peanie", @@ -10517,6 +11867,7 @@ "PECL": "PECland", "PED": "PEDRO", "PEDRO": "Pedro The Raccoon", + "PEE": "peecoin", "PEEL": "Meta Apes", "PEENO": "Peeno", "PEEP": "Peepo", @@ -10530,15 +11881,19 @@ "PEG": "PegNet", "PEGA": "PEGA", "PEGAMAGA": "Pepe Maga", + "PEGASCOIN": "Pegascoin", + "PEGAXY": "Pegaxy Stone", "PEGG": "PokPok Golden Egg", "PEGS": "PegShares", - "PEIPEI": "PEIPEI", + "PEIPEI": "PeiPei", + "PEIPEICN": "PEIPEI", "PEKA": "PEKA", "PEKC": "Peacock Coin", "PEKINU": "PEKI INU", "PEKO": "Pepe Neko", "PEL": "Propel Token", "PELF": "PELFORT", + "PELL": "PELL Network Token", "PEM": "Pembrock", "PEME": "PEME", "PENC": "PenCoin", @@ -10546,7 +11901,9 @@ "PENDY": "Pendy", "PENG": "Peng", "PENGCOIN": "PENG", - "PENGU": "Penguiana", + "PENGU": "Pudgy Penguins", + "PENGUI": "Penguiana", + "PENGUIN": "Penguin", "PENGYX": "PengyX", "PENIS": "PenisGrow", "PENJ": "Penjamin Blinkerton", @@ -10555,6 +11912,7 @@ "PENTA": "Penta", "PEON": "Peon", "PEOPLE": "ConstitutionDAO", + "PEOPLEFB": "PEOPLE", "PEOSONE": "pEOS", "PEP": "Pepechain", "PEPA": "Pepa Inu", @@ -10574,7 +11932,8 @@ "PEPEBURN": "Pepeburn", "PEPEC": "Pepe Chain", "PEPECASH": "Pepe Cash", - "PEPECAT": "PEPE CAT", + "PEPECAT": "PEPECAT", + "PEPECATCLUB": "PEPE CAT", "PEPECEO": "REAL PEPE CEO", "PEPECHAIN": "PEPE Chain", "PEPECO": "PEPE COIN BSC", @@ -10582,6 +11941,7 @@ "PEPED": "PepeDAO Coin", "PEPEDAO": "PEPE DAO", "PEPEDERP": "PepeDerp", + "PEPEDNA": "PEPE DNA", "PEPEE": "Pepe the pepe", "PEPEF": "PEPEFLOKI", "PEPEFC": "Pepe FC", @@ -10598,6 +11958,7 @@ "PEPEMAGA": "Trump Pepe", "PEPEMO": "PepeMo", "PEPEMOON": "PEPEMOON", + "PEPEMUSK": "pepemusk", "PEPEOFSOL": "Pepe of Solana", "PEPEPI": "PEPEPi", "PEPER": "Baby Pepe", @@ -10622,12 +11983,15 @@ "PEPPA": "PEPPA", "PEPPER": "Pepper Token", "PEPS": "PEPS Coin", + "PEPU": "Pepe Unchained", "PEPURAI": "PEPURAI", "PEPVERS": "PepVerse", + "PEPX": "Pepsico xStock", "PEPY": "Pepy", "PER": "Perproject", "PERA": "Pera Finance", "PERC": "Perion", + "PERCY": "Percy Verence", "PERI": "PERI Finance", "PERL": "PERL.eco", "PERMIAN": "Permian", @@ -10636,6 +12000,7 @@ "PERU": "PeruCoin", "PERX": "PeerEx Network", "PESA": "Credible", + "PESETACOIN": "PesetaCoin", "PESHI": "PESHI", "PESOBIT": "PesoBit", "PESTO": "Pesto the Baby King Penguin", @@ -10651,18 +12016,21 @@ "PETOSHI": "Petoshi", "PETS": "PolkaPets", "PETT": "Pett Network", + "PETUNIA": "Petunia", "PEUSD": "peg-eUSD", "PEW": "pepe in a memes world", "PEX": "Pexcoin", + "PFEX": "Pfizer xStock", "PFI": "PrimeFinance", "PFID": "Pofid Dao", "PFL": "Professional Fighters League Fan Token", "PFR": "PayFair", - "PFT": "Pitch Finance Token", + "PFT": "PolarFighters", + "PFVS": "Puffverse Token", "PFY": "Portify", "PG": "Pepe Grow", "PGALA": "pGALA", - "PGC": "Pegascoin", + "PGC": "PiggyPiggyCoin", "PGEN": "Polygen", "PGF7T": "PGF500", "PGL": "Prospectors", @@ -10673,15 +12041,15 @@ "PGT": "Polyient Games Governance Token", "PGTS": "Puregold token", "PGU": "Polyient Games Unity", - "PGX": "Pegaxy Stone", + "PGX": "Procter & Gamble xStock", "PHA": "Phala Network", "PHAE": "Phaeton", "PHALA": "Phalanx", "PHAME": "PHAME", + "PHAR": "Pharaoh", "PHAUNTEM": "Phauntem", "PHB": "Phoenix Global [v2]", "PHBD": "Polygon HBD", - "PHC": "Profit Hunters Coin", "PHCR": "PhotoChromic", "PHEN": "Phenx", "PHEX": "HEX (Polygon Portal)", @@ -10703,46 +12071,59 @@ "PHRYG": "PHRYGES", "PHRYGE": "PHRYGES", "PHRYGES": "The Phryges", + "PHRZ": "Pharaohs", "PHS": "PhilosophersStone", "PHT": "Photon Token", "PHTC": "Photochain", "PHTR": "Phuture", "PHUN": "PHUNWARE", "PHV": "PATHHIVE", - "PI": "Plian", + "PHY": "DePHY", + "PI": "Pi Network", "PIA": "Olympia AI", + "PIAI": "Pi Network AI", "PIAS": "PIAS", "PIB": "Pibble", - "PICA": "PicaArtMoney", + "PICA": "Picasso", + "PICAARTMONEY": "PicaArtMoney", "PICKL": "PICKLE", "PICKLE": "Pickle Finance", "PICO": "PicoGo", "PICOLO": "PICOLO", + "PIDOG": "Pi Network Dog", + "PIDOGE": "Pi Network Doge", "PIE": "Persistent Information Exchange", "PIERRE": "sacré bleu", "PIF": "Pepe Wif Hat", "PIG": "Pig Finance", + "PIGC": "Pigcoin", "PIGE": "Pige", "PIGEON": "Pigeon In Yellow Boots", "PIGEONC": "Pigeoncoin", "PIGGY": "Piggy", "PIGGYCOIN": "Piggy Coin", + "PIGLET": "PIGLET", "PIGONK": "PIGONK", "PIGS": "Elon Vitalik Pigs", "PIIN": "piin (Ordinals)", + "PIK": "Pika Protocol", "PIKA": "Pikaboss", "PIKACHU": "Pikachu Inu", "PIKACRYPTO": "Pika", "PIKAM": "Pikamoon", "PIKE": "Pike Token", "PIKO": "Pinnako", + "PILLAR": "PillarFi", "PILOT": "Unipilot", "PIM": "PIM", - "PIN": "Pin", + "PIN": "PinLink", + "PINCHAIN": "Pin", "PINCHI": "Da Pinchi", "PINE": "Pine", "PINETWORKDEFI": "Pi Network DeFi", + "PINEYE": "PinEye", "PING": "CryptoPing", + "PINGO": "PinGo", "PINK": "PINK - The Panther", "PINKCOIN": "PinkCoin", "PINKSALE": "PinkSale", @@ -10758,6 +12139,7 @@ "PIPI": "Pippi Finance", "PIPL": "PiplCoin", "PIPO": "Pipo", + "PIPONHL": "PiP", "PIPPIN": "pippin", "PIPT": "Power Index Pool Token", "PIRATE": "Pirate Nation", @@ -10772,23 +12154,28 @@ "PIST": "Pist Trust", "PIT": "Pitbull", "PITCH": "PITCH", + "PITCHFINANCE": "Pitch Finance Token", + "PITISCOIN": "Pitis Coin", + "PIUU": "PIXIU", "PIVN": "PIVN", "PIVX": "Private Instant Verified Transaction", - "PIX": "Lampix", + "PIX": "PixelSwap", "PIXEL": "Pixels", "PIXELV": "PixelVerse", "PIXFI": "Pixelverse", "PIXL": "PIXL", - "PIZA": "Half Pizza", + "PIZA": "PIZA", "PIZPEPE": "Pepe Pizzeria", - "PIZZA": "PizzaSwap", + "PIZZA": "Pizza", "PIZZACOIN": "PizzaCoin", + "PIZZASWAP": "PizzaSwap", "PJM": "Pajama.Finance", "PKB": "ParkByte", "PKC": "Pikciochain", "PKD": "PetKingdom", "PKF": "PolkaFoundry", "PKG": "PKG Token", + "PKIN": "PUMPKIN", "PKN": "Poken", "PKOIN": "Pocketcoin", "PKT": "PKT", @@ -10802,6 +12189,7 @@ "PLANET": "PLANET", "PLANETCOIN": "PlanetCoin", "PLANETS": "PlanetWatch", + "PLANT": "Plant", "PLASTIK": "Plastiks", "PLAT": "BitGuild PLAT", "PLATC": "PlatinCoin", @@ -10810,6 +12198,7 @@ "PLAY": "Play Token", "PLAYC": "PlayChip", "PLAYCOIN": "PlayCoin", + "PLAYFUN": "PLAYFUN", "PLAYKEY": "Playkey", "PLB": "Paladeum", "PLBT": "Polybius", @@ -10821,6 +12210,7 @@ "PLEA": "Plearn", "PLEB": "PLEBToken", "PLEBONBASE": "PLEB", + "PLENA": "PLENA", "PLENTY": "Plenty DeFi", "PLEO": "Empleos", "PLERF": "Plerf", @@ -10829,9 +12219,11 @@ "PLG": "Pledgecamp", "PLGR": "Pledge Finance", "PLI": "Plugin", + "PLIAN": "Plian", "PLINK": "Chainlink (Polygon Portal)", "PLM": "Plasmonics", "PLMC": "Polimec", + "PLMS": "Polemos", "PLMT": "Pallium", "PLNC": "PLNCoin", "PLNX": "Planumex", @@ -10847,11 +12239,13 @@ "PLSX": "PulseX", "PLT": "Poollotto.finance", "PLTC": "PlatonCoin", + "PLTRX": "Palantir xStock", "PLTX": "PlutusX", "PLTXYZ": "Add.xyz", "PLU": "Pluton", "PLUG": "PL^Gnet", "PLUGCN": "Plug Chain", + "PLUME": "Plume", "PLUP": "PoolUp", "PLURA": "PluraCoin", "PLUS1": "PlusOneCoin", @@ -10876,10 +12270,13 @@ "PMR": "Pomerium Utility Token", "PMT": "POWER MARKET", "PMTN": "Peer Mountain", + "PMX": "Phillip Morris xStock", "PNB": "Pink BNB", "PNC": "PlatiniumCoin", "PND": "PandaCoin", "PNDC": "Pond Coin", + "PNDN": "Pandana", + "PNDO": "Pondo", "PNDR": "Pandora Finance", "PNFT": "Pawn My NFT", "PNG": "Pangolin", @@ -10913,10 +12310,10 @@ "POGAI": "POGAI", "POGS": "POG", "POINT": "SportPoint", - "POINTS": "Cryptsy Points", "POK": "Pokmonsters", "POKEGROK": "PokeGROK", "POKEM": "Pokemonio", + "POKEMO": "Pokemon", "POKEMON": "Pokemon", "POKER": "PokerCoin", "POKERFI": "PokerFi", @@ -10934,8 +12331,10 @@ "POLK": "Polkamarkets", "POLKER": "Polker", "POLL": "Pollchain", + "POLLEN": "Beraborrow", "POLLUK": "Jasse Polluk", "POLLUX": "Pollux Coin", + "POLLY": "Polynetica", "POLNX": "eToro Polish Zloty", "POLO": "NftyPlay", "POLS": "Polkastarter", @@ -10948,6 +12347,7 @@ "POLYX": "Polymesh", "POM": "Proof Of Memes", "PON": "Ponder", + "PONCH": "Ponchiqs", "PONCHO": "Poncho", "POND": "Marlin", "PONGO": "Pongo", @@ -10976,16 +12376,20 @@ "POP": "Popcoin", "POPC": "PopChest", "POPCAT": "Popcat", + "POPCHAIN": "POPCHAIN", "POPCO": "Popcorn", "POPDOG": "PopDog", "POPE": "PopPepe", "POPECOIN": "Popecoin", "POPEPE": "POPEPE", + "POPG": "POPG", "POPGOAT": "Goatseus Poppimus", "POPK": "POPKON", + "POPMART": "POP MART", "POPO": "popo", "POPOETH": "POPO", "POPSICLE": "Popsicle Finance", + "POPU": "Populous", "POPULARCOIN": "PopularCoin", "POR": "Portugal National Team Fan Token", "PORA": "PORA AI", @@ -11012,21 +12416,25 @@ "POTATO": "Potato", "POTS": "Moonpot", "POTTER": "POTTER", + "POTUS": "President Trump", + "POTUS47": "Trump Coin", "POU": "Pou", "POUPE": "Poupe", "POUW": "Pouwifhat", "POW": "PowBlocks", "POWELL": "Jerome Powell", - "POWER": "UniPower", + "POWER": "Powerloom Token", "POWR": "Power Ledger", "POWSCHE": "Powsche", "POX": "Monkey Pox", + "POZO": "Pozo Coin", "PP": "ProducePay Chain", "PPAD": "PlayPad", "PPALPHA": "Phoenix Protocol", "PPAY": "Plasma Finance", "PPBLZ": "Pepemon Pepeballs", "PPC": "PeerCoin", + "PPCOIN": "Project Plutus", "PPFT": "Papparico Finance", "PPI": "Primpy", "PPIZZA": "P Pizza", @@ -11037,10 +12445,11 @@ "PPP": "PayPie", "PPR": "Papyrus", "PPS": "PopulStay", - "PPT": "Populous", + "PPT": "Pop Token", "PPY": "Peerplays", "PQT": "Prediqt", "PRA": "ProChain", + "PRAI": "Privasea AI", "PRARE": "Polkarare", "PRB": "Paribu Net", "PRC": "ProsperCoin", @@ -11061,6 +12470,7 @@ "PRESALE": "Presale.World", "PRESI": "Turbo Trump", "PRESID": "President Ron DeSantis", + "PRESIDEN": "President Elon", "PRFT": "Proof Suite Token", "PRG": "Paragon", "PRI": "PRIVATEUM INITIATIVE", @@ -11072,12 +12482,14 @@ "PRIME": "Echelon Prime", "PRIMECHAIN": "PrimeChain", "PRIMEETH": "Prime Staked ETH", + "PRIMEX": "Primex Finance", "PRIN": "Print The Pepe", "PRINT": "Printer.Finance", "PRINTERIUM": "Printerium", "PRINTS": "FingerprintsDAO", "PRISM": "Prism", "PRISMA": "Prisma Finance", + "PRIVIX": "Privix", "PRIX": "Privatix", "PRL": "Oyster Pearl", "PRM": "PrismChain", @@ -11087,10 +12499,13 @@ "PROB": "ProBit Token", "PROC": "ProCurrency", "PROD": "Productivist", + "PROFITHUNTERS": "Profit Hunters Coin", "PROGE": "Protector Roge", "PROJECT89": "Project89", + "PROJECTPAI": "Project Pai", "PROLIFIC": "Prolific Game Studio", "PROM": "Prometeus", + "PROMPT": "Wayfinder", "PROOF": "PROVER", "PROP": "Propeller", "PROPC": "Propchain", @@ -11132,7 +12547,8 @@ "PSEUD": "PseudoCash", "PSF": "Prime Shipping Foundation", "PSG": "Paris Saint-Germain Fan Token", - "PSI": "PSIcoin", + "PSI": "Trident", + "PSICOIN": "PSIcoin", "PSILOC": "Psilocybin", "PSK": "Pool of Stake", "PSL": "Pastel", @@ -11153,10 +12569,11 @@ "PT": "Phemex", "PTA": "PentaCoin", "PTAS": "La Peseta", - "PTC": "PesetaCoin", + "PTC": "Particle Trade", "PTD": "Pilot", "PTERIA": "Pteria", "PTF": "PowerTrade Fuel", + "PTGC": "The Grays Currency", "PTH": "PlasticHero", "PTI": "Paytomat", "PTM": "Potentiam", @@ -11167,6 +12584,7 @@ "PTP": "Platypus Finance", "PTR": "Petro", "PTRUMP": "Pepe Trump", + "PTS": "Petals", "PTT": "Pink Taxi Token", "PTU": "Pintu Token", "PTX": "PlatinX", @@ -11190,11 +12608,17 @@ "PUMA": "Puma", "PUMBAA": "Pumbaa", "PUMLX": "PUMLx", - "PUMP": "PUMP", + "PUMP": "Pump.fun", + "PUMPAI": "PumpAI", + "PUMPB": "Pump", "PUMPBTC": "pumpBTC", "PUMPFUNBAN": "Pump Fun Ban", + "PUMPIT": "BOGDANOFF", + "PUMPTRUMP": "PUMP TRUMP", + "PUMPY": "WOW MOON LAMBO PUMPPPPPPY", "PUN": "Punkko", "PUNCH": "PUNCHWORD", + "PUNDIAI": "Pundi AI", "PUNDIX": "Pundi X", "PUNDU": "Pundu", "PUNGU": "PUNGU", @@ -11214,7 +12638,10 @@ "PURA": "Pura", "PURE": "Puriever", "PUREALT": "Pure", + "PURGE": "Forgive Me Father", + "PURP": "Purple Platform io", "PURPE": "Purple Pepe", + "PURPLEBTC": "Purple Bitcoin", "PURR": "Purr", "PURRC": "Purrcoin", "PURSE": "Pundi X PURSE", @@ -11227,17 +12654,21 @@ "PUSSY": "Pussy Financial", "PUSSYINBIO": "Pussy In Bio", "PUT": "PutinCoin", + "PUTIN": "Putin Meme", "PUUSH": "puush da button", "PUX": "pukkamex", "PVC": "PVC Meta", "PVFYBO": "JRVGCUPVSC", - "PVP": "PVPChain", + "PVP": "PvP", + "PVPCHAIN": "PVPChain", "PVT": "Pivot Token", "PVU": "Plant vs Undead Token", "PWAR": "PolkaWar", "PWC": "PixelWorldCoin", + "PWEASE": "Pwease", "PWH": "pepewifhat", "PWINGS": "JetSwap pWings", + "PWOG": "Purple Fwog", "PWON": "Personal Wager", "PWR": "MaxxChain", "PWRC": "PWR Coin", @@ -11257,7 +12688,7 @@ "PYLON": "Pylon Finance", "PYM": "Playermon", "PYME": "PymeDAO", - "PYN": "Paycent", + "PYN": "Paynetic", "PYP": "PayPro", "PYQ": "PolyQuity", "PYR": "Vulcan Forged", @@ -11268,6 +12699,7 @@ "PYRV1": "Vulcan Forged v1", "PYT": "Payther", "PYTH": "Pyth Network", + "PYTHIA": "Pythia", "PYUSD": "PayPal USD", "PZETH": "pzETH", "PZM": "Prizm", @@ -11307,12 +12739,15 @@ "QIE": "QI Blockchain", "QINGWA": "ShangXin QingWa", "QISWAP": "QiSwap", + "QKA": "Qkacoin", "QKC": "QuarkChain", + "QKITTY": "QueenKitty", "QKNTL": "Quick Intel", "QLC": "Kepple [OLD]", "QLINDO": "QLINDO", "QLIX": "QLix", "QMALL": "QMALL TOKEN", + "QMV": "Qumva Network", "QNT": "Quant", "QNTR": "Quantor", "QNTU": "Quanta", @@ -11325,6 +12760,7 @@ "QQBC": "QQBC IPFS BLOCKCHAIN", "QQQ": "Poseidon Network", "QQQF": "Standard Crypto Fund", + "QQQX": "Nasdaq xStock", "QR": "Qrolli", "QRK": "QuarkCoin", "QRL": "Quantum Resistant Ledger", @@ -11332,6 +12768,7 @@ "QRP": "Cryptics", "QRT": "Qrkita Token", "QRX": "QuiverX", + "QSHX": "Queen Sherex", "QSLV": "Quicksilver coin", "QSP": "Quantstamp", "QSR": "Quasar", @@ -11347,21 +12784,25 @@ "QTO": "QToken", "QTUM": "QTUM", "QTZ": "Quartz", + "QU3": "QU3ai", + "QU3V1": "QU3ai v1", "QUA": "Quantum Tech", "QUAC": "QUACK", "QUACK": "Rich Quack", + "QUAI": "Quai Network", "QUAM": "Quam Network", "QUAN": "Quant AI", "QUANT": "Quant Finance", "QUARASHI": "Quarashi Network", - "QUARK": "Quark", "QUARTZ": "Sandclock", "QUASA": "Quasacoin", + "QUASAR": "Quasar", "QUB": "Qubism", "QUBE": "Qube", "QUBIC": "Qubic", "QUBITICA": "Qubitica", "QUBY": "Quby", + "QUDEFI": "Qudefi", "QUE": "Queen Of Memes", "QUEEN": "Queen of Engrand", "QUICK": "Quickswap", @@ -11374,12 +12815,15 @@ "QUIZ": "Quizando", "QUNT": "Quants", "QUO": "Quoll Finance", + "QUQ": "quq", "QUROZ": "Qfora", "QUSD": "QUSD", + "QUSDT": "Tether (Qom Bridge)", "QVT": "Qvolta", "QWAN": "The QWAN", "QWARK": "Qwark", "QWC": "Qwertycoin", + "QWEN": "Qwen AI", "QWLA": "Qawalla", "QWT": "QoWatt", "QXC": "QuantumXC", @@ -11393,6 +12837,8 @@ "RABB": "Rabbit INU", "RABBI": "Len \"rabbi\" Sassaman", "RABBIT": "Rabbit Finance", + "RABBITC": "RabBitcoin", + "RABET": "Rabet", "RABI": "Rabi", "RAC": "RAcoin", "RACA": "Radio Caca", @@ -11410,7 +12856,8 @@ "RAFT": "Raft", "RAGDOLL": "Ragdoll", "RAGE": "Rage Fan", - "RAI": "Rai Reflex Index", + "RAGET": "RAGE", + "RAI": "Reploy", "RAID": "Raid Token", "RAIDER": "Crypto Raiders", "RAIF": "RAI Finance", @@ -11420,6 +12867,7 @@ "RAINC": "RainCheck", "RAINCO": "Rain Coin", "RAINI": "Rainicorn", + "RAIREFLEX": "Rai Reflex Index", "RAISE": "Raise Token", "RAIT": "Rabbitgame", "RAIZER": "RAIZER", @@ -11429,7 +12877,9 @@ "RALLY": "Trump Rally", "RAM": "Ramifi Protocol", "RAMA": "Ramestta", + "RAME": "Ramen", "RAMEN": "RamenSwap", + "RAMON": "Ramon", "RAMP": "RAMP", "RANKER": "RankerDao", "RAP": "Philosoraptor", @@ -11442,13 +12892,16 @@ "RAT": "RatCoin", "RATECOIN": "Ratecoin", "RATING": "DPRating", - "RATIO": "Ratio", + "RATIO": "Ratio Governance Token", + "RATO": "Rato The Rat", + "RATOTHERAT": "Rato The Rat", "RATS": "Rats", "RATWIF": "RatWifHat", "RAVE": "Ravendex", "RAVELOUS": "Ravelous", "RAVEN": "Raven Protocol", "RAVENCOINC": "Ravencoin Classic", + "RAWDOG": "RawDog", "RAWG": "RAWG", "RAY": "Raydium", "RAYS": "Rays Network", @@ -11467,10 +12920,11 @@ "RBLZ": "RebelSatoshi", "RBN": "Ribbon Finance", "RBNB": "StaFi Staked BNB", + "RBNT": "Redbelly Network", "RBP": "Rare Ball Potion", "RBR": "Ribbit Rewards", "RBRETT": "ROARING BRETT", - "RBT": "Rabet", + "RBT": "RebootWorld", "RBTC": "Smart Bitcoin", "RBUNNY": "Rocket Bunny", "RBW": "Crypto Unicorns Rainbow", @@ -11480,9 +12934,11 @@ "RBY": "RubyCoin", "RC": "Russiacoin", "RC20": "RoboCalls", + "RCADE": "RCADE", "RCC": "Reality Clash", "RCCC": "RCCC", "RCG": "Recharge", + "RCGE": "RCGE", "RCH": "Rich", "RCKT": "RocketSwap", "RCM": "READ2N", @@ -11498,10 +12954,11 @@ "RDEX": "Orders.Exchange", "RDF": "ReadFi", "RDGX": "R-DEE Protocol", + "RDMP": "Roadmap Coin", "RDN": "Raiden Network Token", "RDNT": "Radiant Capital", "RDNTV1": "Radiant Capital v1", - "RDO": "Rodeo Finance", + "RDO": "RDO Token", "RDOG": "Repost Dog", "RDPX": "Dopex Rebate Token", "RDR": "Rise of Defenders", @@ -11510,12 +12967,21 @@ "RDX": "Redux Protocol", "REA": "Realisto", "REACH": "/Reach", + "REACT": "Reactive Network", + "READY": "READY!", "REAL": "RealLink", + "REALESTATE": "RealEstate", + "REALIS": "Realis Worlds", "REALM": "Realm", "REALMS": "Realms of Ethernity", "REALP": "Real Pepe", "REALPLATFORM": "REAL", + "REALPUMPITCOIN": "PUMP", + "REALR": "Real Realm", "REALTRACT": "RealTract", + "REALUSD": "Real USD", + "REALUSDV1": "Real USD v1", + "REALUSDV2": "Real USD v2", "REALY": "Realy Metaverse", "REAP": "ReapChain", "REAPER": "Grim Finance", @@ -11529,7 +12995,7 @@ "RECOM": "Recom", "RECORD": "Music Protocol", "RECT": "ReflectionAI", - "RED": "RED TOKEN", + "RED": "RedStone", "REDC": "RedCab", "REDCO": "Redcoin", "REDDIT": "Reddit", @@ -11540,10 +13006,13 @@ "REDLC": "Redlight Chain", "REDLUNA": "Redluna", "REDN": "Reden", + "REDNOTE": "RedNote Xiaohongshu", "REDO": "Resistance Dog", "REDP": "Red Ponzi Gud", "REDPEPE": "Red Pepe", "REDTH": "Red The Mal", + "REDTOKEN": "RED TOKEN", + "REDX": "REDX", "REDZILLA": "REDZILLA COIN", "REE": "ReeCoin", "REEE": "REEE", @@ -11555,7 +13024,9 @@ "REFLECTO": "Reflecto", "REFTOKEN": "RefToken", "REFUND": "Refund", + "REG": "RealToken Ecosystem Governance", "REGALCOIN": "Regalcoin", + "REGE": "Regent of the North Winds", "REGEN": "Regen Network", "REGENT": "REGENT COIN", "REGI": "Resistance Girl", @@ -11564,11 +13035,15 @@ "REI": "REI Network", "REIGN": "Reign of Terror", "REINDEER": "Reindeer", - "REKT": "REKT", - "REKT2": "REKT 2.0", + "REK": "Rekt", + "REKT": "Rekt", + "REKTV1": "REKT", + "REKTV2": "REKT 2.0", + "REKTV3": "REKT v3 (rekt.game)", "REL": "Reliance", "RELAY": "Relay Token", "RELI": "Relite Finance", + "RELIGN": "RELIGN", "RELOADED": "Doge Reloaded", "RELVT": "Relevant", "REM": "REMME", @@ -11576,6 +13051,8 @@ "REME": "REME-Coin", "REMILIA": " Remilia", "REMIT": "BlockRemit", + "REMMETA": "Real Estate Metaverse", + "REMUS": "REMUS", "REN": "REN", "RENA": "Warena", "RENBTC": "renBTC", @@ -11586,6 +13063,7 @@ "RENQ": "Renq Finance", "RENS": "Rens", "RENT": "Rent AI", + "RENTA": "Renta Network", "RENTBE": "Rentberry", "REP": "Augur", "REPE": "Resistance Pepe", @@ -11597,10 +13075,13 @@ "REQ": "Request Network", "RES": "Resistance", "RESCUE": "Rescue", + "RESOLV": "Resolv", "REST": "Restore", "RET": "Renewable Energy", "RETA": "Realital Metaverse", "RETAIL": "Retail.Global", + "RETAR": "Retard Finder Coin", + "RETARD": "retardcoin", "RETARDIA": "RETARDIA", "RETARDIO": "RETARDIO", "RETH": "Rocket Pool ETH", @@ -11609,6 +13090,7 @@ "RETIRE": "Retire Token", "REU": "REUCOIN", "REUNI": "Reunit Wallet", + "REUSDC": "Relend USDC", "REV": "Revain", "REV3L": "REV3AL", "REVA": "Revault Network", @@ -11623,7 +13105,9 @@ "REVV": "REVV", "REW": "Review.Network", "REWARD": "Rewardable", - "REX": "Imbrex", + "REWARDS": "Solana Rewards", + "REX": "REVOX", + "REXBT": "rexbt by VIRTUALS", "REXHAT": "rexwifhat", "REZ": "Renzo", "RF": "Raido Financial", @@ -11658,18 +13142,25 @@ "RIBB": "Ribbit", "RIBBIT": "Ribbit", "RIC": "Riecoin", - "RICE": "RiceFarm", + "RICE": "DAOSquare Governance Token", "RICECOIN": "RiceCoin", - "RICH": "Richie", + "RICEFARM": "RiceFarm", + "RICH": "GET RICH QUICK", + "RICHCOIN": "RICHCOIN", + "RICHIE": "Richie2.0", + "RICHIEV1": "Richie", "RICHOFME": "Rich Of Memes", "RICHR": "RichRabbit", "RICK": "Infinite Ricks", "RICKMORTY": "Rick And Morty", "RIDE": "Holoride", + "RIDECHAIN": "Ride Chain Coin", "RIDEMY": "Ride My Car", "RIF": "RIF Token", "RIF3": "MetaTariffv3", + "RIFA": "Rifampicin", "RIFI": "Rikkei Finance", + "RIFT": "RIFT AI", "RIGEL": "Rigel Finance", "RIK": "RIKEZA", "RIL": "Rilcoin", @@ -11698,17 +13189,21 @@ "RISEP": "Rise Protocol", "RISEVISION": "Rise", "RISITA": "Risitas", + "RITA": "Rita Elite Order", "RITE": "ritestream", "RITO": "Ritocoin", "RITZ": "Ritz.Game", "RIVUS": "RivusDAO", "RIYA": "Etheriya", + "RIZ": "Rivalz Network", "RIZE": "Rizespor Token", "RIZO": "HahaYes", "RIZOLOL": "Rizo", "RIZZ": "Rizz", + "RIZZMAS": "Rizzmas", "RJV": "Rejuve.AI", "RKC": "Royal Kingdom Coin", + "RKEY": "RKEY", "RKI": "RAKHI", "RKN": "RAKON", "RKR": "REAKTOR", @@ -11717,6 +13212,7 @@ "RLC": "iExec", "RLM": "MarbleVerse", "RLOOP": "rLoop", + "RLP": "Resolv RLP", "RLT": "Runner Land", "RLUSD": "Ripple USD", "RLX": "Relex", @@ -11732,6 +13228,7 @@ "RMS": "Resumeo Shares", "RMT": "SureRemit", "RMV": "Reality Metaverse", + "RNAPEPE": "RNA PEPE", "RNB": "Rentible", "RNBW": "Rainbow Token", "RNC": "ReturnCoin", @@ -11740,22 +13237,25 @@ "RNDX": "Round X", "RNEAR": "Near (Rainbow Bridge)", "RNS": "RenosCoin", - "RNT": "OneRoot Network", + "RNT": "REAL NIGGER TATE", "RNTB": "BitRent", "RNX": "ROONEX", "ROAD": "ROAD", + "ROAM": "Roam Token", "ROAR": "Alpha DEX", "ROARINGCAT": "Roaring Kitty", "ROB": "ROB", "ROBET": "RoBet", + "ROBI": "Robin Rug", "ROBIN": "Robin of Da Hood", "ROBINH": "ROBIN HOOD", "ROBO": "RoboHero", + "ROBOCOIN": "First Bitcoin ATM", "ROBOTA": "TAXI", "ROBOTAXI": "ROBOTAXI", "ROC": "Rasputin Online Coin", "ROCCO": "Just A Rock", - "ROCK": "Bedrock", + "ROCK": "Zenrock", "ROCK2": "Ice Rock Mining", "ROCKET": "Team Rocket", "ROCKETCOIN": "RocketCoin", @@ -11765,6 +13265,7 @@ "ROCKYCOIN": "ROCKY", "ROCO": "ROCO FINANCE", "RODAI": "ROD.AI", + "RODEO": "Rodeo Finance", "ROE": "Rover Coin", "ROG": "ROGin AI", "ROGER": "ROGER", @@ -11772,6 +13273,7 @@ "ROK": "Rockchain", "ROKM": "Rocket Ma", "ROKO": "Roko", + "ROLLSROYCE": "RollsRoyce", "ROLS": "RollerSwap", "ROM": "ROMCOIN", "ROME": "Rome", @@ -11779,6 +13281,7 @@ "RONCOIN": "RON", "ROND": "ROND", "RONIN": "Ronin", + "RONNIE": "Ronnie", "ROO": "Lucky Roo", "ROOBEE": "ROOBEE", "ROOK": "KeeperDAO", @@ -11789,8 +13292,13 @@ "ROOT": "The Root Network", "ROOTCOIN": "RootCoin", "ROOTS": "RootProject", + "ROP": "Redemption Of Pets", + "ROPE": "Rope Token", + "ROPELOL": "Rope", + "ROPIRITO": "Ropirito", "ROS": "ROS Coin", "ROSA": "Rosa Inu", + "ROSCOE": "Roscoe", "ROSE": "Oasis Labs", "ROSEC": "Rosecoin", "ROSEW": "RoseWifHat", @@ -11799,12 +13307,15 @@ "ROSX": "Roseon", "ROT": "Rotten", "ROTTY": "ROTTYCOIN", + "ROUGE": "Rouge Studio", "ROUND": "RoundCoin", "ROUP": "Roup (Ordinals)", "ROUSH": "Roush Fenway Racing Fan Token", "ROUTE": "Router Protocol", "ROUTEV1": "Router Protocol v1", + "ROUTINE": "Morning Routine", "ROVI": "ROVI", + "ROVR": "ROVR Network", "ROW": "Rage On Wheels", "ROWAN": "Sifchain", "ROX": "Robotina", @@ -11841,6 +13352,7 @@ "RSG": "RSG TOKEN", "RSIC": "RSIC•GENESIS•RUNE", "RSIN": "Roketsin", + "RSO": "Real Sociedad Fan Token", "RSPN": "Respan", "RSR": "Reserve Rights", "RSRV": "Reserve", @@ -11851,9 +13363,11 @@ "RSUN": "RisingSun", "RSUSHI": "Sushi (Rainbow Bridge)", "RSV": "Reserve", + "RSVV1": "Reserve v1", "RSWETH": "Restaked Swell Ethereum", "RT2": "RotoCoin", "RTB": "AB-CHAIN", + "RTBL": "Rolling T-bill", "RTC": "Reltime", "RTD": "Retard", "RTE": "Rate3", @@ -11867,8 +13381,10 @@ "RUBB": "Rubber Ducky Cult", "RUBCASH": "RUBCASH", "RUBIT": "Rublebit", + "RUBIUS": "Rubius", + "RUBIX": "Rubix", "RUBX": "eToro Russian Ruble", - "RUBY": "Rubius", + "RUBY": "RubyToken", "RUBYEX": "Ruby.Exchange", "RUC": "Rush", "RUFF": "Ruff", @@ -11880,11 +13396,14 @@ "RUM": "RUM Pirates of The Arrland Token", "RUN": "Run", "RUNE": "Thorchain", + "RUNESX": "RUNES·X·BITCOIN", "RUNEVM": "RUNEVM", + "RUNI": "Runesterminal", "RUNNER": "Runner", "RUNY": "Runy", "RUP": "Rupee", "RUPX": "Rupaya", + "RURI": "Ruri - Truth Terminal's Crush", "RUSD": "Reflecto USD", "RUSH": "RUSH COIN", "RUSHCMC": "RUSHCMC", @@ -11896,9 +13415,12 @@ "RUX": "Gacrux NFT", "RVC": "Revenue Coin", "RVF": "RocketX exchange", + "RVFV1": "RocketX exchange v1", + "RVFV2": "RocketX exchange v2", "RVL": "Revolotto", "RVLNG": "RevolutionGames", "RVLT": "Revolt 2 Earn", + "RVLTV1": "Revolt 2 Earn v1", "RVM": "Realvirm", "RVN": "Ravencoin", "RVO": "AhrvoDEEX", @@ -11907,7 +13429,8 @@ "RVST": "Revest Finance", "RVT": "Rivetz", "RVX": "Rivex", - "RWA": "Xend Finance", + "RWA": "RWA Inc.", + "RWAECO": "RWA Ecosystem", "RWAS": "RWA Finance", "RWB": "RawBlock", "RWD": "Reward Vision", @@ -11915,10 +13438,13 @@ "RWN": "Rowan Token", "RWS": "Robonomics Web Services", "RWT": "RWT TOKEN", + "RX": "RealtyX", "RXCG": "RXCGames", "RXD": "Radiant", "RXO": "RocketXRP Official", + "RXR": "RXR Coin", "RXT": "RIMAUNANGIS", + "RYAN": "OFFICIAL RYAN", "RYC": "RoyalCoin", "RYCN": "RoyalCoin 2.0", "RYD": "RYderOSHI", @@ -11927,9 +13453,11 @@ "RYOCURRENCY": "Ryo", "RYOMA": "Ryoma", "RYOSHI": "Ryoshis Vision", + "RYS": "RefundYourSOL", "RYU": "The Blue Dragon", "RYZ": "Anryze", "RZR": "RazorCoin", + "RZUSD": "RZUSD", "RedFlokiCEO": "Red Floki CEO", "S": "Sonic Labs", "S2K": "Sports 2K75", @@ -11937,7 +13465,10 @@ "S4F": "S4FE", "S8C": "S88 Coin", "SA": "Superalgos", + "SAAD": "Saad Boi", + "SAAS": "SaaSGo", "SABAI": "Sabai Protocol", + "SABER": "Saber", "SABLE": "Sable Finance", "SABR": "SABR Coin", "SAC1": "Sable Coin", @@ -11968,7 +13499,9 @@ "SAGA": "Saga", "SAGACOIN": "SagaCoin", "SAGE": "Ceremonies AI", - "SAI": "SAI", + "SAHA": "Sahara AI Coin", + "SAHARA": "Sahara AI", + "SAI": "Sharpe AI", "SAIL": "SAIL", "SAITA": "SaitaChain", "SAITABIT": "SaitaBit", @@ -11976,6 +13509,7 @@ "SAITAMAV1": "Saitama v1", "SAITANOBI": "Saitanobi", "SAITO": "Saito", + "SAIV1": "SAI", "SAIY": "Saiyan PEPE", "SAK": "SharkCoin", "SAKAI": "Sakai Vault", @@ -11993,7 +13527,8 @@ "SAMA": "Moonsama", "SAMMY": "Samoyed", "SAMO": "Samoyedcoin", - "SAN": "Santiment", + "SAMS": "Samsara.Build", + "SAN": "San Chan", "SANA": "Storage Area Network Anywhere", "SANCHO": "Sancho", "SAND": "The Sandbox", @@ -12006,6 +13541,8 @@ "SANSHU": "Sanshu Inu", "SANTA": "SANTA CHRISTMAS INU", "SANTAGROK": "Santa Grok", + "SANTAHAT": "SANTA HAT", + "SANTI": "Santiment", "SANTOS": "Santos FC Fan Token", "SAO": "Sator", "SAP": "SwapAll", @@ -12014,6 +13551,7 @@ "SAPPC": "SappChat", "SAR": "Saren", "SARCO": "Sarcophagus", + "SARM": "Stella Armada", "SAROS": "Saros", "SAS": "Stand Share", "SASHA": "SASHA CAT", @@ -12023,14 +13561,17 @@ "SATA": "Signata", "SATAN": "MrBeast's Cat", "SATO": "Atsuko Sato", + "SATOEXCHANGE": "SatoExchange Token", + "SATOPAY": "SatoPay", "SATORI": "Satori Network", "SATOSHINAKAMOTO": "Satoshi Nakamoto", + "SATOTHEDOG": "Sato The Dog", "SATOX": "Satoxcoin", "SATOZ": "Satozhi", "SATS": "SATS (Ordinals)", "SATSALL": "ALL BEST ICO SATOSHI", "SATT": "SaTT", - "SATX": "SatoExchange Token", + "SATX": "SATX", "SAUBER": "Alfa Romeo Racing ORLEN Fan Token", "SAUCE": "SaucerSwap", "SAUCEINU": "SAUCEINU", @@ -12040,13 +13581,17 @@ "SAUNA": "SaunaFinance Token", "SAV": "Save America", "SAV3": "SAV3", + "SAVAX": "BENQI Liquid Staked AVAX", + "SAVEOCEAN": "Save The Ocean", "SAVG": "SAVAGE", "SAVM": "SatoshiVM", + "SAVVA": "SAVVA", "SAY": "SAY Coin", "SB": "DragonSB", "SBA": "simplyBrand", "SBABE": "SNOOPYBABE", "SBAE": "Salt Bae For The People", + "SBB": "Slim Beautiful Bill", "SBC": "StableCoin", "SBCC": "Smart Block Chain City", "SBCH": "Smart Bitcoin Cash", @@ -12058,14 +13603,14 @@ "SBIO": "Vector Space Biosciences, Inc.", "SBNB": "Binance Coin (SpookySwap)", "SBOX": "SUIBOXER", - "SBR": "Saber", + "SBR": "STRATEGIC BITCOIN RESERVE", "SBRT": "SaveBritney", "SBSC": "Subscriptio", "SBT": "SOLBIT", "SBTC": "Super Bitcoin", "SC": "Siacoin", "SC20": "Shine Chain", - "SCA": "SiaClassic", + "SCA": "Scallop", "SCALE": "Scalia Infrastructure", "SCAM": "Scam Coin", "SCAMP": "ScamPump", @@ -12139,8 +13684,10 @@ "SDAO": "SingularityDAO", "SDC": "ShadowCash", "SDCRV": "Stake DAO CRV", + "SDEUSD": "Staked deUSD", "SDEX": "SmarDex", "SDL": "Saddle Finance", + "SDM": "Shieldeum", "SDME": "SDME", "SDN": "Shiden Network", "SDO": "TheSolanDAO", @@ -12156,12 +13703,14 @@ "SDX": "SwapDEX", "SEAGULL": "SEAGULL SAM", "SEAIO": "Second Exchange Alliance", - "SEAL": "Seal Finance", + "SEAL": "Seal", + "SEALFINANCE": "Seal Finance", "SEALN": "Seal Network", "SEAM": "Seamless Protocol", "SEAMLESS": "SeamlessSwap", "SEAN": "Starfish Finance", - "SEAT": "SeatlabNFT", + "SEAT": "Seamans Token", + "SEATLABNFT": "SeatlabNFT", "SEBA": "Seba", "SEC": "SecureCryptoPayments", "SECO": "Serum Ecosystem Token", @@ -12195,7 +13744,8 @@ "SEN": "Sentaro", "SENATE": "SENATE", "SENC": "Sentinel Chain", - "SEND": "Social Send", + "SEND": "Suilend", + "SENDCOIN": "Sendcoin", "SENDOR": "Sendor", "SENK": "Senk", "SENNO": "SENNO", @@ -12206,6 +13756,7 @@ "SENSOV1": "SENSO v1", "SENSUS": "Sensus", "SENT": "Sentinel", + "SENTAI": "SentAI", "SENTI": "Sentinel Bot Ai", "SENTR": "Sentre Protocol", "SEON": "Seedon", @@ -12215,6 +13766,7 @@ "SEPA": "Secure Pad", "SEQ": "Sequence", "SER": "Secretum", + "SERAPH": "Seraph", "SERG": "Seiren Games Network", "SERO": "Super Zero", "SERP": "Shibarium Perpetuals", @@ -12222,6 +13774,7 @@ "SERV": "Serve", "SERVE": "Metavice", "SESE": "Simpson Pepe", + "SESH": "Session Token", "SESSIA": "SESSIA", "SETH": "sETH", "SETH2": "sETH2", @@ -12231,6 +13784,7 @@ "SEX": "SEX Odyssey", "SEXY": "EthXY", "SEXYP": "SEXY PEPE", + "SFAGRO": "SFAGRO", "SFARM": "SolFarm", "SFC": "Solarflarecoin", "SFCP": "SF Capital", @@ -12245,12 +13799,14 @@ "SFLOKI": "SuiFloki-Inu", "SFLR": "Sceptre Staked FLR", "SFM": "SafeMoon V2", + "SFMV2": "SafeMoon v2", "SFP": "SafePal", "SFR": "SaffronCoin", "SFRAX": "Staked FRAX", "SFRC": "Safari Crush", "SFRXETH": "Frax Staked Ether", - "SFT": "SportsFix", + "SFRXUSD": "Staked Frax USD", + "SFT": "Fightly", "SFTMX": "Stader sFTMX", "SFTY": "Stella Fantasy", "SFU": "Saifu", @@ -12259,6 +13815,7 @@ "SFV2": "ShibaFameV2", "SFX": "SUBX FINANCE LAB", "SG": "SocialGood", + "SGA": "Saga", "SGB": "Songbird", "SGDX": "eToro Singapore Dollar", "SGE": "Society of Galactic Exploration", @@ -12268,7 +13825,7 @@ "SGOLD": "SpaceGold", "SGP": "SGPay", "SGPT": "ShitGPT", - "SGR": "Sogur Currency", + "SGR": "Schrodinger", "SGROK": "Super Grok", "SGT": "SharedStake Governance Token", "SHA": "Safe Haven", @@ -12288,9 +13845,10 @@ "SHARE": "Seigniorage Shares", "SHARECHAIN": "ShareChain", "SHARES": "shares.finance", + "SHAREV1": "Seigniorage Shares v1", "SHARK": "Sharky", - "SHARKC": "Shark Cat", "SHARKI": "Sharki", + "SHARKYSH": "Sharky Sharkx", "SHARP": "Sharp", "SHARPE": "Sharpe Capital", "SHAUN": "SHAUN INU", @@ -12298,6 +13856,7 @@ "SHC": "School Hack Coin", "SHD": "ShardingDAO", "SHDW": "Shadow Token", + "SHDX": "Shido DEX", "SHE": "Shine Chain", "SHEB": "SHEBOSHIS", "SHEEESH": "Secret Gem", @@ -12305,7 +13864,8 @@ "SHEESHA": "Sheesha Finance", "SHEGEN": "Aiwithdaddyissues", "SHEI": "SheikhSolana", - "SHELL": "Shell Token", + "SHELL": "MyShell", + "SHELLTOKEN": "Shell Token", "SHEN": "Shen", "SHEPE": "Shiba V Pepe", "SHERA": "Shera Tokens", @@ -12319,6 +13879,7 @@ "SHIB05": "Half Shiba Inu", "SHIB1": "Shib1", "SHIB2": "SHIB2", + "SHIB20": "Shib2.0", "SHIBA": "Shibaqua", "SHIBAAI": "SHIBAAI", "SHIBAC": "SHIBA CLASSIC", @@ -12327,8 +13888,10 @@ "SHIBAI": "AiShiba", "SHIBAKEN": "Shibaken Finance", "SHIBAMOM": "Shiba Mom", + "SHIBANCE": "Shibance Token", "SHIBAR": "Shibarium Name Service", "SHIBARMY": "Shib Army", + "SHIBAW": "Shiba $Wing", "SHIBAY": "Shiba Inu Pay", "SHIBAZILLA": "ShibaZilla2.0", "SHIBCAT": "SHIBCAT", @@ -12370,6 +13933,8 @@ "SHINT": "Shiba Interstellar", "SHIP": "ShipChain", "SHIR": "SHIRO", + "SHIRO": "Shiro Neko", + "SHIROSOL": "Shiro Neko (shirosol.online)", "SHIRYOINU": "Shiryo-Inu", "SHISHA": "Shisha Coin", "SHIT": "I will poop it NFT", @@ -12378,20 +13943,24 @@ "SHK": "Shrike", "SHL": "Oyster Shell", "SHLD": "ShieldCoin", + "SHM": "Shardeum", "SHND": "StrongHands", "SHNT": "Sats Hunters", "SHO": "Showcase Token", "SHOE": "ShoeFy", "SHOG": "SHOG", - "SHOGGOTH": "Shoggoth", + "SHOGGOTH": "Shoggoth (shoggoth.monster)", + "SHOGGOTHAI": "Shoggoth", "SHOKI": "Shoki", "SHON": "ShonToken", + "SHONG": "Shong Inu", "SHOOT": "Mars Battle", "SHOOTER": "Top Down Survival Shooter", "SHOP": "Shoppi Coin", "SHOPN": "ShopNEXT", "SHOPX": "Splyt", "SHORK": "shork", + "SHORT": "Bermuda Shorts", "SHORTY": "ShortyCoin", "SHOW": "ShowCoin", "SHPING": "Shping Coin", @@ -12399,35 +13968,44 @@ "SHRA": "Shrapnel", "SHRAP": "Shrapnel", "SHRED": "ShredN", - "SHREK": "ShrekCoin", + "SHREK": "Shrek", + "SHRI": "Shrimp Paste", "SHRIMP": "SHRIMP", "SHROO": "Shroomates", "SHROOM": "Shroom.Finance", "SHROOMFOX": "Magic Shroom", "SHRUB": "Shrub", + "SHRUBIUS": "Shrubius Maximus", + "SHRX": "Sherex", "SHS": "SHEESH", "SHU": "Shutter", "SHUB": "SimpleHub", "SHUFFLE": "SHUFFLE!", "SHVR": "Shivers", "SHX": "Stronghold Token", + "SHY": "Shytoshi Kusama", "SHYTCOIN": "ShytCoin", "SI": "Siren", + "SIACLASSIC": "SiaClassic", "SIB": "SibCoin", "SIBA": "SibaInu", "SIC": "Swisscoin", "SID": "Sid", "SIDE": "Side.xyz", + "SIDELINED": "Sidelined?", + "SIDELINER": "Sideliner Coin", "SIDESHIFT": "SideShift Token", "SIDUS": "Sidus", "SIERRA": "Sierracoin", + "SIF": "Solana Index Fund", "SIFT": "Smart Investment Fund Token", "SIFU": "SIFU", "SIG": "Signal", "SIGMA": "SIGMA", - "SIGN": "Sign Token", + "SIGN": "Sign", "SIGNA": "Signa", "SIGNAT": "SignatureChain", + "SIGNMETA": "Sign Token", "SIGT": "Signatum", "SIGU": "Singular", "SIKA": "SikaSwap", @@ -12443,15 +14021,18 @@ "SILVA": "Silva Token", "SILVER": "SILVER", "SILVERKRC": "Silver KRC-20", + "SILVERNOV": "Silvernova Token", "SILVERSTAND": "Silver Standard", "SILVERWAY": "Silverway", "SIM": "Simpson", + "SIMBA": "SIMBA The Sloth", "SIMP": "SO-COL", "SIMPLE": "SimpleChain", "SIMPS": "Simpson MAGA", "SIMPSO": "Simpson Neiro", "SIMPSON": "Homer", "SIMPSON6900": "Simpson6900 ", + "SIMPSONAI": "Simpson AI Agent", "SIMPSONF": "Simpson FUKU", "SIMPSONP": "Simpson Predictions", "SIMPSONSINU": "The Simpsons Inu", @@ -12471,6 +14052,7 @@ "SIPHER": "Sipher", "SIPHON": "Siphon Life Spell", "SIR": "Sir", + "SIREN": "siren", "SIRIUS": "first reply", "SIS": "Symbiosis Finance", "SISA": "Strategic Investments in Significant Areas", @@ -12481,11 +14063,15 @@ "SIUUU": "Crustieno Renaldo", "SIV": "Sivasspor Token", "SIX": "SIX Network", + "SIXP": "Sixpack Miner", "SIXPACK": "SIXPACK", + "SIXSI": "SIX SIGMA", "SIZ": "Sizlux", "SIZE": "SIZE", "SJCX": "StorjCoin", "SKAI": "Skillful AI", + "SKAIN": "SKAINET", + "SKATE": "Skate", "SKB": "SkullBuzz", "SKBDI": "Skibidi Toilet", "SKC": "Skeincoin", @@ -12494,14 +14080,18 @@ "SKET": "Sketch coin", "SKEY": "SmartKey", "SKG888": "Safu & Kek Gigafundz 888", - "SKI": "Skillchain", + "SKI": "Ski Mask Dog", "SKIBIDI": "Skibidi Toilet", + "SKICAT": "SKI MASK CAT", "SKID": "Success Kid", "SKILL": "CryptoBlades", + "SKILLC": "Skillchain", "SKIN": "Skincoin", "SKING": "Solo King", "SKINS": "Coins & Skins", + "SKINUT": "Skimask Pnut", "SKIPUP": "SKI MASK PUP", + "SKITTEN": "Ski Mask Kitten", "SKL": "SKALE Network", "SKLAY": "sKLAY", "SKM": "Skrumble Network", @@ -12520,17 +14110,20 @@ "SKX": "SKPANAX", "SKY": "Sky", "SKYA": "Sekuya Multiverse", + "SKYAI": "SKYAI", "SKYCOIN": "Skycoin", "SKYFT": "SKYFchain", "SKYM": "SkyMap", + "SKYOPS": "Skyops", "SKYRIM": "Skyrim Finance", "SKYX": "SKUYX", "SLA": "SUPERLAUNCH", "SLAM": "Slam Token", "SLAP": "CatSlap", "SLAVI": "Slavi Coin", + "SLAYER": "ThreatSlayerAI by Virtuals", "SLB": "Solberg", - "SLC": "Solice", + "SLC": "Silencio", "SLCL": "Solcial", "SLEEP": "Sleep Ecosystem", "SLEEPEE": "SleepFuture", @@ -12547,7 +14140,9 @@ "SLIME": "Snail Trail", "SLING": "Sling Coin", "SLINK": "Soft Link", + "SLIPPY": "SLIPPY", "SLISBNB": "Lista Staked BNB", + "SLK": "SLK", "SLM": "SlimCoin", "SLN": "Smart Layer Network", "SLND": "Solend", @@ -12564,17 +14159,19 @@ "SLRS": "Solrise Finance", "SLS": "SaluS", "SLST": "SmartLands", - "SLT": "Social Lending Network", + "SLT": "Salute", "SLUGDENG": "SLUG DENG", "SLUMBO": "SLUMBO", + "SLVLUSD": "Staked Level USD", "SLVX": "eToro Silver", "SLX": "Slate", "SMA": "Soma Network", "SMAC": "Social Media Coin", "SMAK": "Smartlink", "SMARS": "SafeMars", - "SMART": "SmartCash", + "SMART": "Smart game", "SMARTB": "Smart Coin", + "SMARTCASH": "SmartCash", "SMARTCREDIT": "SmartCredit Token", "SMARTH": "SmartHub", "SMARTLOX": "SmartLOX", @@ -12585,6 +14182,7 @@ "SMARTSHARE": "Smartshare", "SMARTUP": "Smartup", "SMAT": "Smathium", + "SMB": "SMB Token", "SMBR": "Sombra", "SMBSWAP": "SimbCoin Swap", "SMC": "SmartCoin", @@ -12598,7 +14196,9 @@ "SMI": "SafeMoon Inu", "SMIDGE": "Smidge", "SMIDGEETH": "Smidge", - "SMILE": "Smile Token", + "SMIL": "Smile Token", + "SMILE": "bitSmiley", + "SMILEAI": "Smile AI", "SMILEK": "Smilek to the Bank", "SMILEY": "SMILEY", "SMILY": "Smily Trump", @@ -12607,6 +14207,7 @@ "SMLY": "SmileyCoin", "SMM": "TrendingTool.io", "SMOG": "Smog", + "SMOK": "Smoking Chicken Fish", "SMOKE": "Smoke", "SMOL": "Smolcoin", "SMOLE": "smolecoin", @@ -12633,11 +14234,17 @@ "SNA": "SUKUYANA", "SNAC": "SnackboxAI", "SNACK": "Crypto Snack", + "SNAI": "SwarmNode.ai", "SNAIL": "SnailBrook", "SNAKE": "snake", + "SNAKEAI": "Snake-ai", + "SNAKEMOON": "Snakemoon", "SNAKES": "Snakes Game", + "SNAKETOKEN": "Snake Token", + "SNAKT": "Sna-King Trump", "SNAP": "SnapEx", "SNAPCAT": "Snapcat", + "SNAPKERO": "SNAP", "SNB": "SynchroBitcoin", "SNC": "SunContract", "SNCT": "SnakeCity", @@ -12652,20 +14259,23 @@ "SNG": "SINERGIA", "SNGLS": "SingularDTV", "SNGT": "SNG Token", - "SNIBBU": "Snibbu The Crab", + "SNIBBU": "Snibbu", + "SNIBBUTHEC": "Snibbu The Crab", "SNIFT": "StarryNift", "SNIP": "LyrnAI", "SNIPPEPE": "SNIPING PEPE", "SNITCH": "Randall", - "SNK": "Snake Token", + "SNK": "Snook", "SNL": "Sport and Leisure", "SNM": "SONM", "SNMT": "Satoshi Nakamoto Token", "SNN": "SeChain", + "SNO": "Snow Leopard", "SNOB": "Snowball", "SNOLEX": "Snolex", "SNOOP": "SnoopDAO", "SNOOPY": "Snoopy", + "SNOR": "SNOR", "SNORK": "Snork", "SNORT": "SNORT", "SNOV": "Snovio", @@ -12675,6 +14285,7 @@ "SNPAD": "SNP adverse", "SNPC": "SnapCoin", "SNPS": "Snaps", + "SNPT": "SNPIT TOKEN", "SNRG": "Synergy", "SNRK": "Snark Launch", "SNS": "Synesis One", @@ -12699,6 +14310,8 @@ "SOCC": "SocialCoin", "SOCCER": "SoccerInu", "SOCIAL": "Phavercoin", + "SOCIALLT": "Social Lending Network", + "SOCIALSEND": "Social Send", "SOCKS": "Unisocks", "SOCOLA": "SOCOLA INU", "SODA": "SODA Coin", @@ -12707,9 +14320,11 @@ "SOFAC": "SofaCat", "SOFI": "RAI Finance", "SOFTCO": "SOFT COQ INU", + "SOGUR": "Sogur Currency", "SOH": "Stohn Coin", "SOHOT": "SOHOTRN", - "SOIL": "SoilCoin", + "SOIL": "Soil", + "SOILCOIN": "SoilCoin", "SOJ": "Sojourn Coin", "SOK": "shoki", "SOKU": "Soku Swap", @@ -12723,6 +14338,7 @@ "SOLAN": "Solana Beach", "SOLANAP": "Solana Poker", "SOLANAS": "Solana Swap", + "SOLANATREASURY": "Solana Treasury Machine", "SOLAPE": "SolAPE Token", "SOLAR": "Solar", "SOLARA": "Solara", @@ -12734,6 +14350,7 @@ "SOLAV": "SOLAV TOKEN", "SOLBET": "SOL STREET BETS", "SOLBO": "SolBoss", + "SOLBOX": "SolBox", "SOLBULL": "SOLBULL", "SOLC": "SolCard", "SOLCASH": "SOLCash", @@ -12743,9 +14360,12 @@ "SOLER": "Solerium", "SOLETF": "SOL ETF", "SOLEX": "Solex Launchpad", + "SOLEY": "Soley", "SOLFI": "SoliDefi", + "SOLFUN": "SolFun", "SOLGOAT": "SOLGOAT", "SOLGUN": "Solgun", + "SOLIC": "Solice", "SOLID": "Solidified", "SOLIDSEX": "SOLIDsex: Tokenized veSOLID", "SOLITO": "SOLITO", @@ -12769,10 +14389,14 @@ "SOLSPONGE": "Solsponge", "SOLT": "Soltalk AI", "SOLTR": "SolTrump", + "SOLV": "Solv Protocol", "SOLVBTC": "Solv Protocol SolvBTC", "SOLVBTCBBN": "Solv Protocol SolvBTC.BBN", "SOLVBTCCORE": "Solv Protocol SolvBTC.CORE", + "SOLVBTCENA": "SolvBTC Ethena", + "SOLVBTCJUP": "SolvBTC Jupiter", "SOLVE": "SOLVE", + "SOLVEX": "SOLVEX", "SOLWIF": "Solwif", "SOLX": "SolarX", "SOLXD": "Solxdex", @@ -12781,22 +14405,29 @@ "SOLZILLA": "Solzilla", "SOM": "Souls of Meta", "SOMA": "Soma", + "SOMEE": "SoMee.Social", + "SOMEEV1": "SoMee.Social", "SOMM": "Sommelier", - "SOMNIUM": "Somnium Space CUBEs", "SOMPS": "SompsOnKas", "SON": "Simone", "SONAR": "SonarWatch", "SONG": "Song Coin", "SONGOKU": "SONGOKU", - "SONIC": "Sonic", + "SONIC": "Sonic SVM", "SONICO": "Sonic", + "SONICSONIC": "Sonic", "SONICWIF": "SonicWifHat", "SONNE": "Sonne Finance", "SONOF": "Son of Solana", - "SOON": "Soonaverse", + "SONOR": "SonorusToken", + "SOON": "SOON Token", + "SOONAVERSE": "Soonaverse", "SOONCOIN": "SoonCoin", + "SOONTOKEN": "SOON", "SOOTCASE": "I like my sootcase", "SOP": "SoPay", + "SOPH": "Sophon", + "SOPHIA": "SophiaVerse", "SOPHON": "Sophon (Atomicals)", "SOR": "Sorcery", "SORA": "Sora Validator Token", @@ -12805,18 +14436,20 @@ "SORAETH": "SORA", "SORAI": "Sora AI", "SORAPORN": "Sora Porn", - "SOSNOVKINO": "Sosnovkino", + "SOSO": "SoSoValue", "SOT": "Soccer Crypto", "SOTA": "SOTA Finance", "SOUL": "Phantasma", "SOULO": "SouloCoin", - "SOULS": "Soulsaver", + "SOULS": "Unfettered Ecosystem", + "SOULSA": "Soulsaver", "SOUND": "Sound Coin", "SOURCE": "ReSource Protocol", "SOUTH": "DeepSouth AI", "SOV": "Sovryn", "SOVE": "Soverain", "SOVI": "Sovi Finance", + "SOVRN": "Sovrun", "SOWA": "Sowa AI", "SOX": "Nobby Game", "SOY": "Soy Finance", @@ -12824,9 +14457,12 @@ "SP8DE": "Sp8de", "SPA": "Sperax", "SPAC": "SPACE DOGE", - "SPACE": "Spacelens", + "SPACE": "MicroVisionChain", "SPACECOIN": "SpaceCoin", "SPACED": "SPACE DRAGON", + "SPACEHAMSTER": "Space Hamster", + "SPACELENS": "Spacelens", + "SPACEM": "Spacem Token", "SPACEPI": "SpacePi", "SPAD": "SolPad", "SPAI": "Starship AI", @@ -12835,6 +14471,7 @@ "SPARK": "Sparklife", "SPARKLET": "Upland", "SPARKO": "Sparko", + "SPARKSPAY": "SparksPay", "SPARTA": "Spartan Protocol Token", "SPARTACATS": "SpartaCats", "SPARTAD": "SpartaDex", @@ -12845,6 +14482,7 @@ "SPC.QRC": "SpaceChain (QRC-20)", "SPCIE": "Specie", "SPCT": "Spectra Chain", + "SPCX": "Paimon SpaceX SPV Token", "SPD": "Stipend", "SPDR": "SpiderDAO", "SPDX": "Speedex", @@ -12853,6 +14491,8 @@ "SPECT": "Spectral", "SPECTRE": "SPECTRE AI", "SPEE": "SpeedCash", + "SPEED": "IShowSpeed", + "SPEEDCOIN": "Speed Coin", "SPEEDY": "Speedy", "SPELL": "Spell Token", "SPELLFIRE": "Spellfire", @@ -12860,6 +14500,7 @@ "SPENDC": "SpendCoin", "SPENT": "Espento", "SPEPE": "SolanaPepe", + "SPERG": "Bloomsperg Terminal", "SPEX": "StepEx", "SPF": "SportyCo", "SPFC": "São Paulo FC Fan Token", @@ -12876,7 +14517,8 @@ "SPHYNXV3": "Sphynx Token v3", "SPHYNXV4": "Sphynx Token v4", "SPI": "Shopping.io", - "SPICE": "Spice", + "SPICE": "SPICE", + "SPICETOKEN": "Spice", "SPIDER": "Spider Man", "SPIDERMAN": "SPIDERMAN BITCOIN", "SPIDEY": "Spidey", @@ -12887,7 +14529,6 @@ "SPIRIT": "SpiritSwap", "SPITT": "Hawk Ttuuaahh", "SPIZ": "SPACE-iZ", - "SPK": "SparksPay", "SPKL": "SpokLottery", "SPKTR": "Ghost Coin", "SPL": "SocialPal", @@ -12898,6 +14539,7 @@ "SPO": "Spores Network", "SPOK": "Spock", "SPOL": "Starterpool", + "SPONG": "Spongebob", "SPONGE": "Sponge", "SPONGEBOB": "Spongebob Squarepants", "SPOODY": "Spoody Man", @@ -12906,12 +14548,16 @@ "SPORE": "Spore", "SPORT": "SportsCoin", "SPORTS": "ZenSports", + "SPORTSFIX": "SportsFix", "SPORTSP": "SportsPie", + "SPOT": "Defispot", + "SPOTCOIN": "Spotcoin", "SPOTS": "Spots", "SPOX": "Sports Future Exchange Token", "SPRING": "Spring", "SPRITZMOON": "SpritzMoon Crypto Token", "SPRKL": "Sparkle Loyalty", + "SPROUT": "Sprout", "SPRT": "Sportium", "SPRTS": "Sprouts", "SPRTZ": "SpritzCoin", @@ -12928,7 +14574,10 @@ "SPXC": "SpaceXCoin", "SPY": "Smarty Pay", "SPYRO": "SPYRO", + "SPYX": "SP500 xStock", + "SQ3": "Squad3", "SQAT": "Syndiqate", + "SQD": "SQD", "SQG": "Squid Token", "SQGROW": "SquidGrow", "SQL": "Squall Coin", @@ -12948,6 +14597,7 @@ "SQUIDGROWV1": "SquidGrow v1", "SQUIDV1": "Squid Game v1", "SQUIDW": "Squidward Coin", + "SQUIRT": "SQUIRTLE", "SQUOGE": "DogeSquatch", "SR30": "SatsRush", "SRBP": "Super Rare Ball Potion", @@ -12957,6 +14607,7 @@ "SRCX": "Source Token", "SREUR": "SocialRemit", "SRG": "Street Runner NFT", + "SRGD": "Studio Releasing Gold", "SRK": "SparkPoint", "SRLTY": "SaitaRealty", "SRLY": "Rally (Solana)", @@ -12968,10 +14619,14 @@ "SRWD": "ShibRWD", "SRX": "StorX", "SS": "Sharder", + "SS20": "Shell Trade", "SSB": "SatoshiStreetBets", "SSC": "SelfSell", "SSD": "Sonic Screw Driver Coin", - "SSE": "Soroosh Smart Ecosystem", + "SSDX": "SpunkySDX", + "SSE": "Solana Social Explorer", + "SSEV1": "Soroosh Smart Ecosystem v1", + "SSEV2": "Soroosh Smart Ecosystem", "SSG": "Surviving Soldiers", "SSGT": "Safeswap", "SSH": "StreamSpace", @@ -12980,10 +14635,12 @@ "SSLX": "StarSlax", "SSNC": "SatoshiSync", "SSOL": "Solayer SOL", + "SSR": "SOL Strategic Reserve", "SSS": "StarSharks", "SSSSS": "Snake wif Hat", "SST": "SIMBA Storage Token", "SSTC": "SunShotCoin", + "SSTZ": "SSTZ", "SSU": "Sunny Side up", "SSUI": "Spring Staked SUI", "SSV": "ssv.network", @@ -12997,8 +14654,9 @@ "STABLZ": "Stablz", "STAC": "STAC", "STACK": "StackOS", - "STACKS": "STACKS", + "STACKS": " STACKS PAY", "STACS": "STACS Token", + "STAGE": "Stage", "STAK": "Jigstack", "STAKE": "xDai Chain", "STAKEDETH": "StakeHound Staked Ether", @@ -13007,10 +14665,13 @@ "STAN": "Stank Memes", "STANDARD": "Stakeborg DAO", "STAPT": "Ditto Staked Aptos", - "STAR": "FileStar", + "STAR": "StarHeroes", + "STAR10": "Ronaldinho Coin", "STARAMBA": "Staramba", "STARBASE": "Starbase", "STARC": "StarChain", + "STARDOGE": "StarDOGE", + "STARGATEAI": "Stargate AI Agent", "STARL": "StarLink", "STARLAUNCH": "StarLaunch", "STARLY": "Starly", @@ -13024,9 +14685,12 @@ "STARSHIPONSOL": "Starship", "START": "StartCoin", "STARTA": "Starta", + "STARTER": "Starter.xyz", + "STARTUP": "Startup", "STARWARS": "Star Wars", "STARX": "STARX TOKEN", - "STASH": "BitStash", + "STASH": "STASH INU", + "STASHV1": "BitStash", "STAT": "STAT", "STATE": "New World Order", "STATER": "Stater", @@ -13035,18 +14699,23 @@ "STATOKEN": "STA", "STATOM": "Stride Staked ATOM", "STATS": "Stats", + "STAU": "STAU", "STAX": "Staxcoin", "STAY": "NFsTay", + "STB": "stabble", "STBOT": "SolTradingBot", + "STBTC": "Lorenzo stBTC", "STBU": "Stobox Token", "STC": "Satoshi Island", "STCN": "Stakecoin", "STD": "STEED", "STDYDX": "Stride Staked DYDX", "STEAK": "SteakHut Finance", + "STEAKUSDC": "Steakhouse USDC Morpho Vault", "STEALTH": "StealthPad", "STEAMPUNK": "SteamPunk", "STEAMX": "Steam Exchange", + "STEEL": "SteelCoin", "STEEM": "Steem", "STEEMD": "Steem Dollars", "STEEP": "SteepCoin", @@ -13068,12 +14737,15 @@ "STFX": "STFX", "STG": "Stargate Finance", "STHR": "Stakerush", + "STHYPE": "Staked HYPE", "STI": "Seek Tiger", "STIC": "StickMan", + "STICKMAN": "stickman", "STIK": "Staika", "STIMA": "STIMA", "STING": "Sting", "STINJ": "Stride Staked INJ", + "STITCH": "Stitch", "STIX": "STIX", "STJUNO": "Stride Staked JUNO", "STK": "STK Token", @@ -13090,10 +14762,14 @@ "STMAN": "Stickman Battleground", "STMATIC": "Lido Staked Matic", "STMX": "StormX", + "STMXV1": "Storm", + "STMXV2": "StormX v1", "STND": "Standard Protocol", "STNEAR": "Staked NEAR", - "STO": "Save The Ocean", + "STNK": "Stonks", + "STO": "StakeStone", "STOC": "STO Cash", + "STOCK": "Digital Asset Stockpile", "STOG": "Stooges", "STOGE": "Stoner Doge Finance", "STOIC": "stoicDAO", @@ -13101,13 +14777,13 @@ "STONE": "Stone Token", "STONEDE": "Stone DeFi", "STONK": "STONK", - "STONKS": "HarryPotterObamaWallStreetBets10Inu", - "STOP": "SatoPay", + "STONKS": "STONKS", + "STOP": "LETSTOP", "STOR": "Self Storage Coin", "STORE": "Bit Store", "STOREP": "Storepay", "STORJ": "Storj", - "STORM": "Storm", + "STORM": "STORM", "STORY": "Story", "STOS": "Stratos", "STOSMO": "Stride Staked OSMO", @@ -13124,7 +14800,8 @@ "STRAY": "Stray Dog", "STRD": "Stride", "STRDY": "Sturdy", - "STREAM": "STREAMIT COIN", + "STREAM": "Streamflow", + "STREAMIT": "STREAMIT COIN", "STREETH": "STREETH", "STRI": "Strite", "STRIKE": "Strike", @@ -13140,6 +14817,7 @@ "STRUMP": "Super Trump", "STRX": "StrikeX", "STS": "SBank", + "STSHIP": "StarShip", "STSOL": "Lido Staked SOL", "STSOMM": "Stride Staked SOMM", "STSR": "SatelStar", @@ -13156,6 +14834,7 @@ "STUDENTC": "Student Coin", "STUFF": "STUFF.io", "STUMEE": "Stride Staked UMEE", + "STUPID": "StupidCoin", "STUSDT": "Staked USDT", "STV": "Sativa Coin", "STWEMIX": "Staked WEMIX", @@ -13167,21 +14846,31 @@ "STZETA": "ZetaEarn", "STZU": "Shihtzu Exchange Token", "SU": "Smol Su", + "SUAI": "SuiAI", "SUB": "Subsocial", + "SUBA": "Yotsuba", "SUBAWU": "Subawu Token", "SUBF": "Super Best Friends", "SUBS": "Substratum Network", "SUCR": "Sucre", + "SUD": "Sudo Labs", "SUDO": "sudoswap", + "SUEDE": "Johnny Suede", "SUGAR": "Sugar Exchange", + "SUGARB": "SugarBlock", "SUI": "Sui", "SUIA": "SUIA", + "SUIAGENT": "aiSUI", + "SUIAI": "SUI Agents", "SUIB": "Suiba Inu", + "SUIDEPIN": "Sui DePIN", "SUIJAK": "Suijak", "SUILAMA": "Suilama", "SUIMAN": "Suiman", "SUIMON": "Sui Monster", "SUIP": "SuiPad", + "SUIRWA": "Sui RWA", + "SUIRWAPIN": "SUIRWAPIN", "SUISHIB": "SuiShiba", "SUITE": "Suite", "SUKI": "SUKI", @@ -13222,10 +14911,14 @@ "SUPERC": "SuperCoin", "SUPERCAT": "SUPERCAT", "SUPERF": "SUPER FLOKI", + "SUPERGROK": "SuperGrok", "SUPEROETHB": "Super OETH", "SUPERT": "Super Trump", "SUPERTX": "SuperTX", + "SUPFRIEND": "SuperFriend", "SUPR": "SuperDapp", + "SUPRA": "Supra", + "SUPREMEFINANCE": "Hype", "SUR": "Suretly", "SURE": "inSure", "SURF": "Surf.Finance", @@ -13233,9 +14926,11 @@ "SUSD": "sUSD", "SUSDA": "sUSDa", "SUSDE": "Ethena Staked USDe", + "SUSDS": "Savings USDS", "SUSDX": "Staked USDX", "SUSHI": "Sushi", "SUSX": "Savings USX", + "SUT": "SuperTrust", "SUTEKU": "Suteku", "SUTER": "Suterusu", "SUWI": "suwi", @@ -13258,11 +14953,13 @@ "SWAGT": "Swag Token", "SWAI": "Safe Water AI", "SWAMP": "Swampy", - "SWAN": "Black Swan", + "SWAN": "Swan Chain", + "SWANSOL": "Black Swan", "SWAP": "Trustswap", "SWAPP": "SWAPP Protocol", "SWAPZ": "SWAPZ.app", "SWARM": "SwarmCoin", + "SWARMS": "Swarms", "SWASH": "Swash", "SWAY": "Sway Social", "SWBTC": "Swell Restaked BTC", @@ -13294,6 +14991,7 @@ "SWISE": "StakeWise", "SWITCH": "Switch", "SWM": "Swarm Fund", + "SWO": "SwordMagicToken", "SWOLE": "Swole Doge", "SWOP": "Swop", "SWORD": "eZKalibur", @@ -13302,7 +15000,9 @@ "SWP": "Kava Swap", "SWPR": "Swapr", "SWPRS": "Maid Sweepers", + "SWPX": "SwapX", "SWRV": "Swerve", + "SWRX": "SwissRx Coin", "SWT": "Swarm City Token", "SWTH": "Carbon", "SWTS": "SWEETS", @@ -13316,6 +15016,7 @@ "SXM": "saxumdao", "SXP": "SXP", "SXS": "Sphere", + "SXT": "Space and Time", "SXUT": "SPECTRE Utility Token", "SYA": "SaveYourAssets", "SYBC": "SYB Coin", @@ -13327,36 +15028,47 @@ "SYLO": "Sylo", "SYLV": "Sylvester", "SYM": "SymVerse", + "SYMM": "Symmio", + "SYMP": "Sympson AI", "SYN": "Synapse", "SYNC": "Syncus", "SYNCC": "SyncCoin", "SYNCG": "SyncGPT", "SYNCN": "Sync Network", "SYNCO": "Synco", + "SYNDOG": "Synthesizer Dog", + "SYNK": "Synk", "SYNLEV": "SynLev", "SYNO": "Synonym Finance", "SYNR": "MOBLAND", "SYNT": "Synthetix Network", "SYNTE": "Synternet", - "SYNTH": "Synthswap", + "SYNTH": "SYNTHR", + "SYNTHSWAP": "Synthswap", "SYNX": "Syndicate", "SYPOOL": "Sypool", + "SYRAX": "Syrax AI", "SYRUP": "Syrup", + "SYRUPUSDC": "SyrupUSDC", "SYS": "Syscoin", "SZCB": "Zugacoin", "T": "Threshold Network Token", + "T1": "Trump Mobile", "T23": "T23", "T99": "Tethereum", + "TA": "Trusta.AI", "TAAS": "Token as a Service", "TAB": "MollyCoin", "TABOO": "Taboo Token", "TAC": "Traceability Chain", + "TACC": "TACC", "TACHYON": "Tachyon Protocol", "TAD": "Tadpole", "TADA": "Ta-da", "TADDY": "DADDY TRUMP", "TADPOLEF": "Tadpole Finance", "TAF": "TAF", + "TAG": "Tagger", "TAGR": "Think And Get Rich Coin", "TAI": "TARS Protocol", "TAIKO": "Taiko", @@ -13366,10 +15078,13 @@ "TAJ": "TajCoin", "TAK": "TakCoin", "TAKE": "Take America Back", + "TAKER": "Taker", "TAKI": "Taki", + "TAKO": "Tako", "TALA": "Baby Tala", "TALAHON": "Talahon", "TALAO": "Talao", + "TALE": "PrompTale AI", "TALENT": "Talent Protocol", "TALES": "Tales of Pepe", "TALIS": "Talis Protocol", @@ -13379,33 +15094,42 @@ "TANG": "Tangent", "TANGO": "keyTango", "TANGYUAN": "TangYuan", - "TANK": "CryptoTanks", + "TANK": "AgentTank", "TANPIN": "Tanpin", + "TANSSI": "TANSSI", "TANUKI": "Tanuki", "TANUPAD": "Tanuki Launchpad", "TAO": "Bittensor", + "TAOBOT": "tao.bot", + "TAOCAT": "TAOCat by Virtuals", "TAONU": "TAO INU", "TAOP": "TaoPad", "TAOTOOLS": "TAOTools", "TAP": "TAP FANTASY", "TAPC": "Tap Coin", + "TAPCOIN": "TAP FANTASY", "TAPPINGCOIN": "TappingCoin", "TAPROOT": "Taproot Exchange", + "TAPS": "TapSwap", "TAPT": "Tortuga Staked Aptos", "TARA": "Taraxa", "TARAL": "TARALITY", "TARD": "Tard", + "TARDI": "Tardi", + "TARGETCOIN": "TargetCoin", "TARI": "Tari World", "TAROT": "Tarot", "TAROTV1": "Tarot v1", "TARP": "Totally A Rug Pull", "TAS": "TARUSH", "TASH": "Smart Trip Platform", + "TASSHUB": "TASS HUB", "TASTE": "TasteNFT", "TAT": "Tatcoin", "TATA": "TATA Coin", - "TATE": "Tate", + "TATE": "Tate Terminal", "TATES": "Tate Stop", + "TATETOKENETH": "Tate", "TATSU": "Taτsu", "TAU": "Lamden Tau", "TAUC": "Taurus Coin", @@ -13413,7 +15137,10 @@ "TAUR": "Marnotaur", "TAVA": "ALTAVA", "TAX": "MetaToll", + "TAXAD": "TAXAD", "TAXI": "Robotaxi", + "TAXLESSTRUMP": "MAGA TAXLESS", + "TAXP": "Taxpad", "TBAC": "BlockAura", "TBANK": "TaoBank", "TBAR": "Titanium BAR", @@ -13428,6 +15155,7 @@ "TBFT": "Türkiye Basketbol Federasyon Token", "TBIS": "TBIS token", "TBL": "Tombola", + "TBR": "Tuebor", "TBRIDGE": "tBridge Token", "TBT": "T-BOT", "TBTC": "tBTC", @@ -13457,6 +15185,7 @@ "TCY": "The Crypto You", "TD": "The Big Red", "TDAN": "TDAN", + "TDC": "Tidecoin", "TDE": "Trade Ecology Token", "TDEFI": "Token Teknoloji A.S. Token DeFi", "TDFB": "TDFB", @@ -13471,6 +15200,7 @@ "TEC": "TeCoin", "TECAR": "Tesla Cars", "TECH": "TechCoin", + "TECK": "Technet", "TECRA": "TecraCoin", "TED": "TED", "TEDDY": "Teddy Doge v2", @@ -13480,14 +15210,17 @@ "TEITEI": "TeiTei", "TEK": "TekCoin", "TEL": "Telcoin", - "TELE": "Miracle Tele", + "TELE": "Tele", "TELEBTC": "teleBTC", + "TELEPORT": "Teleport System Token", "TELL": "Tellurion", "TELLER": "Teller", "TELO": "Telo Meme Coin", "TELOS": "Teloscoin", "TEM": "Temtum", + "TEMA": "Tema", "TEMCO": "TEMCO", + "TEMM": "TEM MARKET", "TEMP": "Tempus", "TEMPLE": "TempleDAO", "TEN": "Tokenomy", @@ -13515,6 +15248,7 @@ "TERR": "Terrier", "TERRA": "Terraport", "TERRAB": "TERRABYTE AI", + "TERRACOIN": "TerraCoin", "TERRY": "Terry The Disgruntled Turtle", "TERZ": "SHELTERZ", "TES": "TeslaCoin", @@ -13523,17 +15257,21 @@ "TEST": "Test", "TESTA": "Testa", "TET": "Tectum", - "TETHER": "Hermione", + "TETH": "Treehouse ETH", "TETHYS": "Tethys", "TETRA": "Tetra", + "TETSUO": "Tetsuo Coin", "TETU": "TETU", + "TEVA": "Tevaera", "TEW": "Trump in a memes world", + "TEX": "Terrax", "TF47": "Trump Force 47", "TFBX": "Truefeedback Token", "TFC": "The Freedom Coin", "TFI": "TrustFi Network Token", "TFL": "True Flip Lottery", "TFLOW": "TradeFlow", + "TFNY": "TFNY", "TFS": "TFS Token", "TFT": "The Famous Token", "TFUEL": "Theta Fuel", @@ -13543,7 +15281,7 @@ "TGPT": "Trading GPT", "TGRAM": "TG20 TGram", "TGRASS": "Top Grass Club", - "TGT": "TargetCoin", + "TGT": "Tokyo Games Token", "TGW": "The Green World", "TH": "Team Heretics Fan Token", "THALES": "Thales", @@ -13551,7 +15289,7 @@ "THAVAGE": "Mike Tython", "THC": "The Hempcoin", "THD": "Trump Harris Debate", - "THE": "The Protocol", + "THE369": "The 369 code", "THE9": "THE9", "THEAICOIN": "AI", "THEB": "The Boys Club", @@ -13561,7 +15299,10 @@ "THECAT": "THECAT", "THECITADEL": "The Citadel", "THEDAO": "The DAO", + "THEDOGE": "The Dogefather", "THEF": "The Flash Currency", + "THEFACE": "FACE", + "THEFARM": "FARM", "THEG": "The GameHub", "THEHARAMBE": "Harambe", "THEM": "The Meta DAO", @@ -13569,14 +15310,20 @@ "THEN": "THENA", "THEO": "Theopetra", "THEOS": "Theos", + "THEP": "The Protocol", + "THERESAMAY": "Theresa May Coin", "THES": "The Standard Protocol (USDS)", + "THESTANDARD": "Standard Token", "THETA": "Theta Network", "THETAN": "Thetan Coin", + "THETRANSFERTOKEN": "The Transfer Token", "THETRIBE": "The Tribe", "THEX": "Thore Exchange", "THG": "Thetan Arena", "THIK": "ThikDik", "THING": "Nothing", + "THINGSOP": "ThingsOperatingSystem", + "THINK": "THINK Token", "THINKWAREAI": "ThinkwareAI", "THISISF": "This is Fine", "THL": "Thala", @@ -13591,6 +15338,7 @@ "THR": "Thorecoin", "THREE": "Three Protocol Token ", "THRT": "ThriveToken", + "THRUST": "Thruster", "THRY": "THEORY", "THS": "TechShares", "THT": "Thought", @@ -13601,7 +15349,9 @@ "TI": "Titanium22", "TIA": "Celestia", "TIANHE": "Tianhe", + "TIBBIR": "Ribbita", "TIC": "TrueInvestmentCoin", + "TICO": "Tico", "TIDAL": "Tidal Finance", "TIDDIES": "TIDDIES", "TIDE": "Tidalflats", @@ -13612,34 +15362,43 @@ "TIG": "Tigereum", "TIGER": "TIGER", "TIGERC": "TigerCash", + "TIGERCV1": "TigerCash v1", "TIGERMOON": "TigerMoon", + "TIGERSHARK": "Tiger Shark", "TIGRA": "Tigra", "TIGRES": "Tigres Fan Token", "TIIM": "TriipMiles", "TIK": "ChronoBase", "TIKI": "Tiki Token", + "TIKTOK": "Tiktok", "TIKTOKEN": "TikToken", "TIM": "TIMTIM GAMES", "TIME": "Chrono.tech", + "TIMEFUN": "timefun", "TIMES": "DARKTIMES", - "TIMI": "Timicoin", + "TIMESW": "Timeswap", + "TIMI": "This Is My Iguana", + "TIMICOIN": "Timicoin", "TIN": "Token IN", "TINC": "Tiny Coin", + "TIND": "Tinder Swindler", "TINKU": "TinkuCoin", "TINU": "Telegram Inu", "TINY": "TinyBits", "TIOX": "TIOx", - "TIP": "Tip Blockchain", + "TIP": "Tip", "TIPC": "Tipcoin", "TIPINU": "Tip Inu", "TIPS": "FedoraCoin", "TIPSY": "TipsyCoin", "TIT": "TittieCoin", "TITA": "Titan Hunters", - "TITAN": "TitanSwap", + "TITAN": "SATOSHI•RUNE•TITAN (Runes)", "TITANO": "Titano", + "TITANSWAP": "TitanSwap", "TITANX": "TitanX", "TITC": "TitCoin", + "TITCOIN": "titcoin", "TITI": "TiTi Protocol", "TITS": "We Love Tits", "TITTY": "TamaKitty", @@ -13669,6 +15428,7 @@ "TLP": "TulipCoin", "TLW": "TILWIKI", "TMAGA": "THE MAGA MOVEMENT", + "TMAI": "Token Metrics AI", "TMANIA": "Trump Mania", "TME": "Timereum", "TMED": "MDsquare", @@ -13677,6 +15437,7 @@ "TMNG": "TMN Global", "TMNT": "TMNT", "TMON": "Two Monkey Juice Bar", + "TMOX": "Thermo Fisher xStock", "TMPL": "TMPL", "TMRW": "TMRW Coin", "TMSH": "Bursaspor Fan Token", @@ -13693,19 +15454,21 @@ "TNT": "Tierion", "TOA": "TOA Coin", "TOAD": "TOAD", + "TOADCOIN": "TOAD", "TOB": "Tom On Base", "TOBI": "MOTO DOG", "TOBY": "toby", "TOC": "TouchCon", "TODAY": "TodayCoin", "TODD": "TURBO TODD", - "TOK": "Tokenplace", + "TOK": "Tokai", "TOKA": "Tonka Finance", "TOKAMAK": "Tokamak Network", "TOKAU": "Tokyo AU", "TOKC": "Tokyo Coin", "TOKE": "Tokemak", "TOKEN": "TokenFi", + "TOKENPLACE": "Tokenplace", "TOKENSTARS": "TokenStars", "TOKERO": "TOKERO LevelUP Token", "TOKKI": "CRYPTOKKI", @@ -13716,11 +15479,14 @@ "TOLO": "Tolo Yacoloco", "TOLYCAT": "Toly's Cat", "TOM": "TOM Finance", + "TOMA": "Tomarket", "TOMAHAWKCOIN": "Tomahawkcoin", + "TOMAINFO": "TomaInfo", "TOMAN": "IRR", "TOMB": "Tomb", "TOMC": "TOM CAT", "TOMI": "tomiNet", + "TOMO": "Tomo Cat", "TOMOE": "TomoChain ERC20", "TOMS": "TomTomCoin", "TON": "Toncoin", @@ -13742,6 +15508,8 @@ "TOOLS": "TOOLS", "TOON": "Pontoon", "TOONF": "Toon Finance", + "TOOTHLESS": "Toothless", + "TOPBIDDER": "TopBidder", "TOPC": "Topchain", "TOPCA": "TOP CAT", "TOPCAT": "Topcat", @@ -13759,8 +15527,9 @@ "TORII": "Torii Finance", "TORN": "Tornado Cash", "TORO": "Toro Inoue", + "TOROSOL": "Toro", "TORSY": "TORSY", - "TOS": "ThingsOperatingSystem", + "TOS": "Cryptos", "TOSA": "TosaInu BSC", "TOSC": "T.OS", "TOSDIS": "TosDis", @@ -13768,7 +15537,9 @@ "TOSHI": "Toshi", "TOSHKIN": "Toshkin Coin", "TOT": "TotCoin", + "TOTAKEKE": "Dark Cheems", "TOTEM": "DragonMaster", + "TOTHEMOON": "To The Moon", "TOTM": "Totem", "TOTO": "TOTO", "TOUCHFAN": "TouchFan", @@ -13794,17 +15565,21 @@ "TPU": "TensorSpace", "TPV": "TravGoPV", "TPY": "Thrupenny", + "TQ": "TonQuestion", + "TQQQX": "TQQQ xStock", "TQRT": "TokoQrt", "TR3": "Tr3zor", "TRA": "Trabzonspor Fan Token", "TRAC": "OriginTrail", "TRACE": "Trace Network Labs", "TRACEA": "Trace AI", + "TRACKEDBIO": "TrackedBio", "TRACN": "trac (Ordinals)", "TRADE": "Polytrade", "TRADEBOT": "TradeBot", "TRADECHAIN": "Trade Chain", "TRADEX": "TradeX AI", + "TRAI": "Trackgood AI", "TRAID": "Traid", "TRAIMP": "TRUMP AI", "TRAIN": "Trump Train", @@ -13820,7 +15595,7 @@ "TRB": "Tellor", "TRBT": "Tribute", "TRBV1": "Tellor Tributes v1", - "TRC": "TerraCoin", + "TRC": "Terrace", "TRCB": "TRCB Chain", "TRCL": "Treecle", "TRCT": "Tracto", @@ -13828,11 +15603,15 @@ "TRDL": "Strudel Finance", "TRDS": "Traders Token", "TRDT": "Trident", - "TREAT": "Treat", + "TRDX": "Trendix", + "TREA": "Treat", + "TREAT": "Shiba Inu Treat", + "TREB": "Treble", "TRECENTO": "Trecento Blockchain Capital", - "TREE": "HyperionX", + "TREE": "Tree", "TREEB": "Retreeb", "TREMP": "Doland Tremp", + "TRENCHER": "Trencher", "TRESTLE": "TRESTLE", "TRET": "Tourist Review", "TRG": "The Rug Game", @@ -13848,9 +15627,13 @@ "TRICKLE": "Trickle", "TRIG": "Trigger", "TRINI": "Trinity Network Credit", - "TRIO": "Tripio", + "TRIO": "TRIO", "TRIPAD": "TripAdvisor, Inc.", + "TRIPIO": "Tripio", + "TRIPPKI": "Trippki", + "TRISIG": "TRI SIGMA", "TRITON": "Triton", + "TRIVI": "TriviAgent by Virtuals", "TRIVIA": "Trivians", "TRIX": "TriumphX", "TRK": "TruckCoin", @@ -13861,10 +15644,12 @@ "TRNGUY": "Tron Guy Project", "TROG": "Trog", "TROGE": "Troge", - "TROLL": "Trollcoin", + "TROLL": "TROLL", + "TROLLC": "Trollcoin", "TROLLHEIM": "Trollheim", "TROLLICTO": "TROLLI CTO", "TROLLMODE": "TROLL MODE", + "TROLLRUN": "TROLL", "TROLLS": "trolls in a memes world", "TRONDOG": "TronDog", "TRONI": "Tron Inu", @@ -13891,12 +15676,13 @@ "TRUM": "TrumpBucks", "TRUMAGA": "TrumpMAGA", "TRUMATIC": "TruFin Staked MATIC", - "TRUMP": "MAGA", + "TRUMP": "OFFICIAL TRUMP", "TRUMP2": "Trump2024", "TRUMP2024": "Donald Trump", "TRUMP3": "Trump MP3", "TRUMP47": "47th President of the United States", "TRUMPA": "TRUMP AI", + "TRUMPAI": "Trump Maga AI", "TRUMPAMANIA": "TRUMPAMANIA", "TRUMPARMY": "Trump Army", "TRUMPBASE": "MAGA (magatrumponbase.tech)", @@ -13904,28 +15690,36 @@ "TRUMPC": "TrumpCat", "TRUMPCA": "Trump Card", "TRUMPCAT": "TRUMPCAT", + "TRUMPCATF": "Trump Cat Family", "TRUMPCATS": "Trump Golden Cat", - "TRUMPCOIN": "TrumpCoin", + "TRUMPCOIN": "MAGA: Fight for Trump", + "TRUMPCOINROCKS": "TrumpCoin", "TRUMPDAO": "TRUMP DAO", "TRUMPDO": "TRUMP", "TRUMPDOGE": "Trump Doge", + "TRUMPDOGECOIN": "DOGE", "TRUMPE": "Trump Pepe", "TRUMPEPE": "Trump Pepe", "TRUMPER": "Trump Era", "TRUMPF": "Trump Fight", + "TRUMPG": "TRUMP GROK", "TRUMPHAT": "Trump Hat", + "TRUMPI": "TRUMP IP", "TRUMPINU": "Trump Inu", "TRUMPJ": "TRUMPJR", - "TRUMPJR": "TrumpJr", + "TRUMPJR": "OFFICIAL TRUMP JR", + "TRUMPJRVIP": "TrumpJr", "TRUMPM": "TRUMP MAGA PRESIDENT", "TRUMPMA": "TRUMP MAGA SUPER", "TRUMPMAGA": "President Trump MAGA", "TRUMPONBASE": "TRUMP ON BASE", + "TRUMPPROJECT": "Trump Project 2025", "TRUMPS": "Trump SOL", "TRUMPSB": "TrumpsBags", "TRUMPSFIGHT": "TrumpsFight", "TRUMPSHIBA": "Trump Shiba", "TRUMPTECH": "Trump Tech", + "TRUMPTESLA": "Trump Tesla", "TRUMPTITANS": "TrumpTitans", "TRUMPVANCE": "Trump Vance 2024", "TRUMPX": "Trump X-Maga", @@ -13933,11 +15727,13 @@ "TRUNK": "Elephant Money", "TRUST": "TrustDAO", "TRUSTNFT": "TrustNFT", + "TRUT": "Truth", "TRUTH": "TruthGPT", "TRUTHFI": "Truthfi", "TRV": "TrustVerse", "TRVC": "Trivechain", "TRVL": "TRVL", + "TRWA": "TRWA", "TRWP": "Danol Tremp", "TRX": "TRON", "TRXC": "TRONCLASSIC", @@ -13959,21 +15755,28 @@ "TSHARE": "Tomb Shares", "TSHP": "12Ships", "TSL": "Energo", + "TSLAX": "Tesla xStock", "TSLT": "Tamkin", "TSN": "Tsunami Exchange Token", + "TSO": "Thesirion", + "TSOTCHKE": "tsotchke", "TSR": "Tesra", + "TST": "Test", + "TSTAI": "Test AI", + "TSTS": "Test", "TSUBASAUT": "TSUBASA Utility Token", "TSUGT": "Captain Tsubasa", "TSUJI": "Tsutsuji", "TSUKA": "Dejitaru Tsuka", "TSX": "TradeStars", "TT": "ThunderCore", - "TTC": "TTC PROTOCOL", + "TTC": "TonTycoon", "TTF": "TurboTrix Finance", "TTK": "The Three Kingdoms", - "TTM": "To The Moon", + "TTM": "Tradetomato", "TTN": "Titan Coin", - "TTT": "The Transfer Token", + "TTNT": "TITA Project", + "TTT": "TRUMPETTOKEN", "TTTU": "T-Project", "TTU": "TaTaTu", "TTV": "TV-TWO", @@ -13983,11 +15786,16 @@ "TUCKER": "TUCKER CARLSON", "TUDA": "Tutor's Diary", "TUF": "TUF Token", + "TUGGIN": "Tuggin", "TUGOU": "TuGou", + "TUKI": "Tuki", + "TUKIV1": "Tuki v1", "TULIP": "Tulip Protocol", "TUNA": "TUNACOIN", "TUNE": "Bitune", + "TUNETRADEX": "TuneTrade", "TUP": "Tenup", + "TUPE": "Turtle Pepe", "TUR": "Turron", "TURB": "TurboX", "TURBO": "Turbo", @@ -13998,7 +15806,8 @@ "TUS": "Treasure Under Sea", "TUSD": "True USD", "TUSDV1": "True USD v1", - "TUT": "Tutellus", + "TUT": "Tutorial", + "TUTELLUS": "Tutellus", "TUTTER": "Tutter", "TUX": "Tux The Penguin", "TUZKI": "Tuzki", @@ -14029,12 +15838,14 @@ "TX20": "Trex20", "TXA": "TXA", "TXAG": "tSILVER", + "TXAGV1": "AurusSILVER", + "TXAI": "TrumpX Ai", "TXAU": "tGOLD", "TXBIT": "Txbit Token", "TXC": "TEXITcoin", "TXG": "TRUSTxGAMING", "TXL": "Autobahn Network", - "TXT": "TuneTrade", + "TXT": "Taxa Token", "TYBENG": "TYBENG", "TYBG": "Base God", "TYBGSc": "Base Goddess", @@ -14044,6 +15855,7 @@ "TYLER": "Tyler", "TYOGHOUL": "TYO GHOUL", "TYPE": "TypeAI", + "TYPEL": "TypeIt", "TYPERIUM": "Typerium", "TYPUS": "Typus", "TYRANT": "Fable Of The Dragon", @@ -14052,15 +15864,19 @@ "TYT": "Tianya Token", "TZC": "TrezarCoin", "TZKI": "Tsuzuki Inu", + "TZPEPE": "Tezos Pepe", "TZU": "Sun Tzu", "U": "Unidef", + "U2U": "U2U Network", "U8D": "Universal Dollar", + "UA1": "UA1", "UAEC": "United Arab Emirates Coin", "UAHG": "UAHg", "UAT": "UltrAlpha", "UB": "UBit Token", "UBA": "Unbox.Art", - "UBC": "Ubcoin", + "UBC": "Universal Basic Compute", + "UBCOIN": "Ubcoin", "UBDN": "UBD Network", "UBEX": "Ubex", "UBI": "Universal Basic Income", @@ -14102,6 +15918,7 @@ "UETL": "Useless Eth Token Lite", "UFARM": "UniFarm", "UFC": "Union Fair Coin", + "UFD": "Unicorn Fart Dust", "UFFYI": "Unlimited FiscusFYI", "UFI": "PureFi", "UFO": "UFO Gaming", @@ -14150,6 +15967,7 @@ "UMT": "UnityMeta", "UMX": "UniMex Network", "UMY": "KaraStar UMY", + "UNA": "Unagi Token", "UNAT": "Unattanium", "UNB": "Unbound Finance", "UNBNK": "Unbanked", @@ -14157,6 +15975,7 @@ "UNC": "UnCoin", "UNCL": "UNCL", "UNCN": "Unseen", + "UNCOMMONGOODS": "UNCOMMON•GOODS", "UNCX": "UniCrypt", "UND": "United Network Distribution", "UNDB": "unibot.cash", @@ -14167,26 +15986,40 @@ "UNF": "Unfed Coin", "UNFI": "Unifi Protocol DAO", "UNFK": "UNFK", + "UNHX": "UnitedHealth xStock", "UNI": "Uniswap Protocol Token", + "UNIART": "UNIART", "UNIBOT": "Unibot", + "UNIBOTV1": "Unibot v1", + "UNIBTC": "uniBTC", "UNIC": "Unicly", "UNICE": "UNICE", "UNICORN": "UNICORN Token", "UNIDEXAI": "UniDexAI", "UNIDX": "UniDex", + "UNIDXV1": "UniDex v1", "UNIE": "Uniswap Protocol Token (Avalanche Bridge)", "UNIETH": "Universal ETH", + "UNIFI": "Unifi", "UNIFY": "Unify", + "UNIL": "UniLayer", "UNIM": "Unicorn Milk", "UNIO": "Unio Coin", + "UNIPOWER": "UniPower", + "UNIPT": "Universal Protocol Token", "UNIQ": "Uniqredit", "UNIQUE": "Unique One", + "UNIR": "UniRouter", + "UNISD": "unified Stable Dollar", + "UNISDV1": "uniswap State Dollar", "UNISTAKE": "Unistake", "UNIT": "Universal Currency", "UNIT0": "UNIT0", "UNITARYSTATUS": "UnitaryStatus Dollar", "UNITED": "UnitedCoins", "UNITRADE": "UniTrade", + "UNITREEAI": "Unitree G1 AI", + "UNITREEDOG": "Unitree AI Robot Dog", "UNITS": "GameUnits", "UNITY": "SuperNET", "UNIVRS": "Universe", @@ -14222,6 +16055,8 @@ "UPR": "Upfire", "UPRO": "ULTRAPRO", "UPS": "UPFI Network", + "UPT": "UPROCK", + "UPTOP": "UPTOP", "UPTOS": "UPTOS", "UPUNK": "Unicly CryptoPunks Collection", "UPUSD": "Universal US Dollar", @@ -14231,7 +16066,9 @@ "URAC": "Uranus", "URALS": "Urals Coin", "URFA": "Urfaspor Token", - "URO": "UroCoin", + "URMOM": "urmom", + "URO": "Urolithin A", + "UROCOIN": "UroCoin", "URQA": "UREEQA", "URS": "URUS", "URUS": "Urus Token", @@ -14244,8 +16081,10 @@ "USCC": "USC", "USCOIN": "USCoin", "USD0": "Usual", + "USD1": "World Liberty Financial USD", "USD3": "Web 3 Dollar", - "USDA": "USDA", + "USDA": "USDa", + "USDACC": "USDA", "USDAP": "Bond Appetite USD", "USDB": "USD Bancor", "USDBC": "Bridged USDC", @@ -14261,38 +16100,52 @@ "USDCPO": "USD Coin (PoS) (Portal from Polygon)", "USDCSO": "USD Coin (Portal from Solana)", "USDD": "USDD", + "USDDV1": "USDD v1", "USDE": "Ethena USDe", "USDEBT": "USDEBT", "USDEX": "eToro US Dollar", + "USDF": "Falcon USD", "USDFL": "USDFreeLiquidity", - "USDG": "USDG", + "USDG": "Global Dollar", + "USDGLOBI": "Globiance USD Stablecoin", + "USDGV1": "USDG v1", + "USDGV2": "USDG", "USDH": "HonestCoin", + "USDHL": "Hyper USD", "USDI": "Interest Protocol USDi", "USDJ": "USDJ", "USDK": "USDK", "USDL": "Lift Dollar", "USDM": "Mountain Protocol", "USDMA": "USD mars", - "USDN": "Neutrino USD", + "USDN": "Neutral AI", "USDO": "USD Open Dollar", + "USDONE": "Currency One USD", "USDP": "Pax Dollar", "USDPLUS": "Overnight.fi USD+", - "USDQ": "USDQ", - "USDR": "Real USD", + "USDQ": "Quantoz USDQ", + "USDQSTABLE": "USDQ", + "USDR": "StablR USD", "USDS": "Sky Dollar", "USDSB": "USDSB", "USDSTABLY": "StableUSD", "USDT": "Tether", + "USDT0": "USDT0", + "USDTB": "USDtb", "USDTBASE": "USDT (Base)", "USDTV": "TetherTV", "USDTZ": "USDtez", "USDU": "Upper Dollar", + "USDUC": "Unstable Coin", "USDV": "Verified USD", + "USDW": "USD DWIN", "USDX": "USDX Stablecoin", + "USDXL": "Last USD", "USDY": "Ondo US Dollar Yield", "USDZ": "Zedxion USDZ", "USE": "Usechain Token", "USEDCAR": "A Gently Used 2001 Honda", + "USELESS": "USELESS COIN", "USETH": "USETH", "USG": "USGold", "USH": "unshETHing_Token", @@ -14313,8 +16166,11 @@ "USTBL": "Spiko US T-Bills Money Market Fund", "USTC": "TerraClassicUSD", "USTCW": "TerraClassicUSD Wormhole", + "USTREAM": "Ustream Coin", "USTX": "UpStableToken", "USUAL": "Usual", + "USUALX": "USUALx", + "USUD": "USUD", "USV": "Universal Store of Value", "USX": "USX Quantum", "USYC": "Hashnote USYC", @@ -14323,6 +16179,7 @@ "UTC": "UltraCoin", "UTG": "UltronGlow", "UTH": "Uther", + "UTHR": "Utherverse Xaeon", "UTHX": "Utherverse", "UTI": "Unicorn Technology International", "UTIL": "Utility Coin", @@ -14330,10 +16187,13 @@ "UTKV1": "Utrust", "UTMDOGE": "UltramanDoge", "UTNP": "Universa", + "UTON": "uTON", "UTT": "United Traders Token", "UTU": "UTU Protocol", "UTX": "UTIX", + "UTYA": "Utya", "UTYAB": "Utya Black", + "UUC": "USA Unity Coin", "UUSD": "Utopia USD", "UUU": "U Network", "UVT": "UvToken", @@ -14349,12 +16209,16 @@ "VAAVE": "Venus AAVE", "VAB": "Vabble", "VADA": "Venus Cardano", - "VADER": "Vader Protocol", + "VADER": "VaderAI", + "VADERPROTOCOL": "Vader Protocol", "VAI": "Vai", + "VAIN": "Vainguard by Virtuals", "VAIOT": "VAIOT", "VAIOTV1": "VAIOT v1", + "VAIX": "Vectorspace AI X", "VAL": "Validity", "VALAS": "Valas Finance", + "VALENTINE": "Valentine", "VALI": "VALIMARKET", "VALID": "Validator Token", "VALOR": "Valor Token", @@ -14363,10 +16227,12 @@ "VALUE": "Value Liquidity", "VAMPIRE": "Vampire Inu", "VAN": "Vanspor Token", - "VANA": "Nirvana", + "VANA": "Vana", "VANCAT": "Vancat", "VANCE": "JD Vance", + "VANCEMEME": "Vance Meme", "VANF": "Van Fwogh", + "VANKEDISI": "vankedisi", "VANRY": "Vanar Chain", "VANT": "Vanta Network", "VANY": "Vanywhere", @@ -14375,6 +16241,7 @@ "VARA": "Vara Network", "VARIUS": "Varius", "VARK": "Aardvark", + "VATAN": "Vatan Token", "VATO": "vanitis", "VATR": "Vatra INU", "VATRENI": "Croatian FF Fan Token", @@ -14397,6 +16264,7 @@ "VCF": "Valencia CF Fan Token", "VCG": "VCGamers", "VCHF": "VNX Swiss Franc", + "VCI": "VinciToken", "VCK": "28VCK", "VCNT": "ViciCoin", "VCORE": "VCORE", @@ -14415,6 +16283,7 @@ "VEC": "VECTOR", "VEC2": "VectorCoin 2.0", "VECT": "Vectorium", + "VECTOR": "VectorChat.ai", "VEE": "BLOCKv", "VEED": "VEED", "VEEN": "LIVEEN", @@ -14426,11 +16295,14 @@ "VEIL": "VEIL", "VEKTOR": "VEKTOR", "VELA": "Vela Token", + "VELAAI": "velaai", "VELAR": "Velar", "VELO": "Velo", "VELOD": "Velodrome Finance", + "VELODV1": "Velodrome v1", "VELOX": "Velox", "VELOXPROJECT": "Velox", + "VELVET": "Velvet", "VEMP": "vEmpire DDAO", "VEN": "VeChain Old", "VENA": "Vena Network", @@ -14450,7 +16322,9 @@ "VERO": "VEROPAD", "VERSA": "Versa Token", "VERSACE": "VERSACE", - "VERSE": "Verse", + "VERSE": "Verse World", + "VERSEBIT": "Verse", + "VERT": "VERT", "VERTAI": "Vertical AI", "VERTEX": "Vertex", "VERUM": "Verum Coin", @@ -14473,13 +16347,15 @@ "VGX": "Voyager Token", "VHC": "Vault Hill City", "VI": "Vid", - "VIA": "ViaCoin", + "VIA": "Octavia AI", + "VIAC": "ViaCoin", "VIB": "Viberate", "VIBE": "VIBEHub", "VIBEA": "Vibe AI", "VIBLO": "VIBLO", "VIC": "Viction", "VICA": "ViCA Token", + "VICE": "VICE Token", "VICEX": "ViceToken", "VICS": "RoboF", "VICT": "Victory Impact Coin", @@ -14488,6 +16364,7 @@ "VIDA": "Vidiachange", "VIDEO": "Videocoin by Drakula", "VIDT": "VIDT Datalink", + "VIDTV1": "VIDT Datalink", "VIDY": "Vidy", "VIDYA": "Vidya", "VIDYX": "VidyX", @@ -14497,9 +16374,11 @@ "VIK": "VIKTAMA", "VIKITA": "VIKITA", "VIKKY": "VikkyToken", + "VILADY": "Vitalik Milady", "VIM": "VicMove", "VIN": "VinChain", "VINCI": "VINCI", + "VINE": "Vine Coin", "VINU": "Vita Inu", "VIOR": "ViorCoin", "VIP": "VIP Tokens", @@ -14513,6 +16392,7 @@ "VIS": "Vigorus", "VISIO": "Visio", "VISION": "VisionGame", + "VISIONCITY": "Vision City", "VISR": "Visor", "VIST": "VISTA", "VISTA": "Ethervista", @@ -14523,21 +16403,27 @@ "VITAFAST": "Molecules of Korolchuk IP-NFT", "VITAL": "Vital Network", "VITALI": "Vitalik's Casper", + "VITALIK": "OFFICIAL VITALIK", + "VITAMINS": "Vitamins", + "VITARNA": "VitaRNA", "VITE": "VITE", + "VITEX": "ViteX Coin", "VITRA": "Vitra Studios", "VITY": "Vitteey", "VIU": "Viuly", "VIVEK": "Head of D.O.G.E", + "VIVI": "LH VIVI", "VIVID": "Vivid Coin", "VIVO": "VIVO Coin", "VIX": "VIXCO", "VIX7": "VIX777", "VIXV1": "VIXCO v1", - "VIZ": "Vision City", + "VIZ": "VIZ Token", "VIZION": "ViZion Protocol", "VIZSLASWAP": "VizslaSwap", "VKNF": "VKENAF", "VLC": "Volcano Uni", + "VLDY": "Validity", "VLK": "Vulkania", "VLS": "Veles", "VLT": "Veltor", @@ -14547,6 +16433,7 @@ "VLUNA": "Venus Luna", "VLX": "Velas", "VLXPAD": "VelasPad", + "VMANTA": "Bifrost Voucher MANTA", "VMATIC": "Venus MATIC", "VMC": "VirtualMining Coin", "VME": "TrueVett", @@ -14572,6 +16459,7 @@ "VOCO": "Provoco", "VODCAT": "VODKA CAT", "VODKA": "Vodka Token", + "VOID": "Nothing", "VOIP": "Voip Finance", "VOISE": "Voise", "VOL": "Volume Network", @@ -14583,18 +16471,21 @@ "VOLTOLD": "Volt Inu (Old)", "VOLTV1": "Volt Inu v1", "VOLTV2": "Volt Inu v2", + "VOLTX": "VolatilityX", "VOLTZ": "Voltz", "VOLX": "VolumeX", + "VON": "Vameon", "VONE": "Vone", "VONSPEED": "Andrea Von Speed", "VOOT": "VootCoin", + "VOOZ": "Vooz Coin", "VOPO": "VOPO", "VOT": "Votecoin", "VOW": "Vow", "VOX": "Vox.Finance", "VOXEL": "Voxies", "VOY": "enVoy DeFi", - "VOYA": "Voyacoin", + "VOYACOIN": "Voyacoin", "VP": "Torah Network", "VPAD": "VLaunch", "VPK": "Vulture Peak", @@ -14603,7 +16494,9 @@ "VPR": "VaporWallet", "VPRC": "VapersCoin", "VPS": "VPS AI", + "VPT": "Veritas Protocol", "VR": "Victoria", + "VR1": "VR1", "VRA": "Verasity", "VRC": "Virtual Coin", "VRGW": "Virtual Reality Game World", @@ -14632,13 +16525,16 @@ "VSOL": "VSolidus", "VSP": "Vesper Finance", "VSTA": "Vesta Finance", + "VSTR": "Vestra DAO", "VSUI": "Volo Staked SUI", - "VSX": "Vsync", + "VSX": "Versus-X", + "VSYNC": "Vsync", "VSYS": "V Systems", "VT": "Virtual Tourist", "VTC": "Vertcoin", "VTG": "Victory Gem", "VTHO": "VeChainThor", + "VTIX": "Vanguard xStock", "VTL": "Vertical", "VTM": "Victorieum", "VTN": "Voltroon", @@ -14647,6 +16543,7 @@ "VTRAD": "VTRADING", "VTRO": "Vitruveo DEX", "VTRUMP": "Vote Trump", + "VTRV": "VitraVerse", "VTRX": "Venus TRX", "VTS": "Veritise", "VTU": "Virtu", @@ -14655,6 +16552,7 @@ "VTY": "Victoriouscoin", "VUC": "Virta Unique Coin", "VULC": "Vulcano", + "VULPEFI": "Vulpe Finance", "VUNI": "Venus UNI", "VUSD": "Virtual USD", "VUZZ": "Vuzz AI", @@ -14662,26 +16560,32 @@ "VVAIFU": "Dasha", "VVI": "VV Coin", "VVS": "VVS Finance", - "VX": "ViteX Coin", + "VVV": "Venice Token", + "VX": "Visa xStock", "VXL": "Voxel X Network", "VXR": "Vox Royale", "VXRP": "Venus XRP", "VXT": "Voxto Amplify", "VXV": "Vectorspace AI", + "VY": "Valinity", "VYBE": "Vybe", "VYFI": "VyFinance", "VYNC": "VYNK Chain", "VYPER": "VYPER.WIN", + "VYVO": "Vyvo AI", + "VZ": "Vault Zero", "VZT": "Vezt", "W": "Wormhole", "W1": "W1", "W12": "W12 Protocol", "W2E": "Walk To Earn", "W3C": "W3Coin", + "W3GG": "W3GG Token", "W3M": "Web3Met", "W3S": "Web3Shot", "W3W": "Web3 Whales", "W8BIT": "8Bit Chain", + "WA7A5": "Wrapped A7A5", "WAAC": "Wrapped AyeAyeCoin", "WAB": "WABnetwork", "WABI": "WABI", @@ -14697,6 +16601,7 @@ "WAGG": "Waggle Network", "WAGIE": "Wagie", "WAGIEBOT": "Wagie Bot", + "WAGM": "WAGMI", "WAGMI": "Wagmi Coin", "WAGMIGAMES": "WAGMI Game", "WAGMIT": "Wagmi", @@ -14705,7 +16610,7 @@ "WAIF": "Waifu Token", "WAIFU": "Waifu", "WAIT": "Hourglass", - "WAL": "The Wasted Lands", + "WAL": "WAL Token", "WALE": "Waletoken", "WALK": "Walk Token", "WALL": "Du Rove's Wall", @@ -14730,18 +16635,24 @@ "WARPED": "Warped Games", "WARPIE": "Warpie", "WARS": "MetaWars", + "WART": "Warthog", "WAS": "Wasder", "WASABI": "WasabiX", "WASD": "WASD Studios", "WASH": "WashingtonCoin", "WASSIE": "WASSIE", + "WASTED": "WastedLands", "WASTR": "Wrapped Astar", - "WAT": "Wat", + "WAT": "WATCoin", + "WAT0X63": "Wat", "WATC": "WATCoin", "WATCH": "Yieldwatch", - "WATER": "doginwotah", + "WATER": "Waterfall", + "WATERCOIN": "WATER", + "WATT": "WATTTON", "WAVAX": "Wrapped AVAX", "WAVES": "Waves", + "WAVESCOMM": "Waves Community Token", "WAVL": "Wrapped Aston Villa", "WAWA": "Wawa Cat", "WAXE": "WAXE", @@ -14749,11 +16660,15 @@ "WAXP": "Worldwide Asset eXchange", "WAXS": "Axie Infinity Shards (Wormhole)", "WAY": "WayCoin", + "WAYGU": "WAYGU CASH", "WAZ": "MikeAI", + "WBAI": "Wrapped Balance AI", + "WBAN": "Wrapped Banano", "WBB": "Wild Beast Coin", "WBBC": "Wibcoin", "WBC": "WorldBrain Coin", "WBCH": "Wrapped Bitcoin Cash", + "WBERA": "Wrapped Bera", "WBESC": "Wrapped BESC", "WBET": "Wavesbet", "WBETH": "Wrapped Beacon ETH", @@ -14787,8 +16702,9 @@ "WCRO": "Wrapped CRO", "WCS": "Weecoins", "WCSOV": "Wrapped CrownSterling", - "WCT": "Waves Community Token", + "WCT": "WalletConnect", "WCT1WCT1": "Wrapped Car Token 1", + "WCTH": "Wrapped CTH Token", "WCUSD": "Wrapped Celo Dollar", "WDAI": "Dai (Wormhole)", "WDC": "WorldCoin", @@ -14801,6 +16717,7 @@ "WEALTH": "WealthCoin", "WEAPON": "MEGAWEAPON", "WEAR": "MetaWear", + "WEAVE6": "Weave6", "WEB": "Webcoin", "WEB3": "WEB3 Inu", "WEB4": "WEB4 AI", @@ -14808,6 +16725,7 @@ "WEBAI": "Web Ai", "WEBC": "Webchain", "WEBD": "WebDollar", + "WEBSIM": "The Css God by Virtuals", "WEBSS": "Websser", "WEC": "Whole Earth Coin", "WECO": "WECOIN", @@ -14821,13 +16739,16 @@ "WEGI": "Wegie", "WEGLD": "Wrapped EGLD", "WEHMND": "Wrapped eHMND", + "WEHODL": "HODL", "WEIRDO": "Weirdo", "WEL": "Welsh Corgi", "WELA": "Wrapped Elastos", "WELD": "Weld", "WELL": "Moonwell", + "WELL3": "WELL3", "WELLTOKEN": "Well", "WELLV1": "Moonwell v1", + "WELON": "WrappedElon", "WELSH": "Welshcorgicoin", "WELT": "Fabwelt", "WELUPS": "Welups Blockchain", @@ -14839,6 +16760,8 @@ "WENLAMBO": "Wenlambo", "WEOS": "Wrapped EOS", "WEPC": "World Earn & Play Community", + "WEPE": "Wall Street Pepe", + "WERK": "Werk Family", "WEST": "Waves Enterprise", "WET": "WeShow Token", "WETH": "WETH", @@ -14859,6 +16782,7 @@ "WFLAMA": "WIFLAMA", "WFLOW": "Wrapped Flow", "WFO": "WoofOracle", + "WFRAGSOL": "Wrapped fragSOL", "WFT": "Windfall Token", "WFTM": "Wrapped Fantom", "WFTN": "Wrapped FTN", @@ -14878,6 +16802,7 @@ "WHALE": "WHALE", "WHALES": "Whales Market", "WHAT": "What the Duck", + "WHATSONPIC": "WhatsOnPic", "WHBAR": "Wrapped HBAR", "WHC": "Whales Club", "WHEAT": "Wheat Token", @@ -14890,9 +16815,11 @@ "WHIRL": "Whirl Finance", "WHISK": "Whiskers", "WHISKEY": "WHISKEY", - "WHITE": "Whiteheart", + "WHITE": "WhiteRock", + "WHITEHEART": "Whiteheart", "WHL": "WhaleCoin", "WHO": "Truwho", + "WHOLE": "Whole Network", "WHOREN": "elizabath whoren", "WHT": "Wrapped Huobi Token", "WHTETGRMOON": "WHITE TIGER MOON", @@ -14900,6 +16827,8 @@ "WHX": "WHITEX", "WHY": "WHY", "WHYCAT": "WhyCat", + "WHYPAD": "Unamano", + "WHYPADV1": "Unamano v1", "WIB": "Wibson", "WIBE": "Wibegram", "WIC": "Wi Coin", @@ -14940,7 +16869,10 @@ "WINT": "WinToken", "WINTER": "Winter", "WINU": "Walter Inu", + "WINX": "WinX.io", + "WIOTA": "wIOTA", "WIOTX": "Wrapped IoTeX", + "WIRE": "717ai by Virtuals", "WIRTUAL": "Wirtual", "WIS": "Experty Wisdom Token", "WISC": "WisdomCoin", @@ -14954,6 +16886,7 @@ "WIWI": "Wiggly Willy", "WIX": "Wixlar", "WIZA": "Wizardia", + "WIZZ": "Wizzwoods Token", "WJD": "WJD", "WJEWEL": "WJEWEL", "WJXN": "Jax.Network", @@ -14962,6 +16895,8 @@ "WKAVA": "Wrapped Kava", "WKC": "Wiki Cat", "WKD": "Wakanda Inu", + "WKEYDAO": "WebKey DAO", + "WLAI": "Weblume AI", "WLD": "Worldcoin", "WLF": "Wolfs Group", "WLFI": "World Liberty Financial", @@ -14969,13 +16904,16 @@ "WLK": "Wolk", "WLKN": "Walken", "WLO": "WOLLO", + "WLSC": "WESTLAND SMART CITY", "WLTH": "Common Wealth", "WLUNA": "Wrapped LUNA Token", "WLUNC": "Wrapped LUNA Classic", "WLXT": "Wallex Token", "WMATIC": "Wrapped Matic", "WMB": "WatermelonBlock", - "WMC": "WMCoin", + "WMC": "Wrapped MistCoin", + "WMCOIN": "WMCoin", + "WMDR": "WaterMinder", "WMEMO": "Wonderful Memories", "WMETIS": "Wrapped Metis", "WMF": "Whale Maker Fund", @@ -14985,17 +16923,20 @@ "WMN": "WebMind Network", "WMNT": "Wrapped Mantle", "WMOXY": "Moxy", - "WMT": "World Mobile Token", + "WMT": "World Mobile Token v1", + "WMTX": "World Mobile Token", "WMW": "WoopMoney", "WMX": "Wombex Finance", "WMXWOM": "Wombex WOM", "WNCG": "Wrapped NCG", "WND": "WonderHero", "WNDR": "Wonderman Nation", + "WNE": "Winee3", "WNEAR": "Wrapped Near", "WNEON": "Wrapped Neon EVM", "WNET": "Wavesnode.net", "WNK": "The Winkyverse", + "WNKV1": "The Winkyverse v1", "WNOW": "WalletNow", "WNRG": "Wrapped-Energi", "WNRZ": "WinPlay", @@ -15004,7 +16945,7 @@ "WNYC": "Wrapped NewYorkCoin", "WNZ": "Winerz", "WOA": "Wrapped Origin Axie", - "WOD": "World of Defish", + "WOD": "World of Dypians", "WOETH": "Wrapped Origin Ether", "WOFM": "World of Masters", "WOID": "WORLD ID", @@ -15013,9 +16954,10 @@ "WOJAK2": "Wojak 2.0 Coin", "WOJAKC": "Wojak Coin", "WOKB": "Wrapped OKB", + "WOKIE": "Wokie Plumpkin by Virtuals", "WOKT": "Wrapped OKT", "WOL": "World of Legends", - "WOLF": "LANDWOLF (AVAX)", + "WOLF": "Landwolf 0x67", "WOLFILAND": "Wolfiland", "WOLFOF": "Wolf of Wall Street", "WOLFP": "Wolfpack Coin", @@ -15033,9 +16975,10 @@ "WONE": "Wrapped Harmony", "WOO": "WOO Network", "WOOD": "Mindfolk Wood", - "WOOF": "Shibance Token", + "WOOF": "WoofWork.io", "WOOFY": "Woofy", "WOOL": "Wolf Game Wool", + "WOOLLY": "Miniature Woolly Mammoth", "WOONK": "Woonkly", "WOOO": "wooonen", "WOOOOO": "Wooooo! Coin", @@ -15044,13 +16987,17 @@ "WOP": "WorldPay", "WOR": "Hollywood Capital Group WARRIOR", "WORK": "Work X", + "WORKCHAIN": "WorkChain.io", "WORKE": "Worken", + "WORKIE": "Workie", "WORL": "World Record Banana", "WORLD": "World Token", + "WORLDOFD": "World of Defish", "WORM": "HealthyWorm", "WORX": "Worx", "WOS": "Wolf Of Solana", "WOT": "World Of Trump", + "WOULD": "would", "WOW": "WOWswap", "WOWS": "Wolves of Wall Street", "WOZX": "Efforce", @@ -15067,6 +17014,7 @@ "WPR": "WePower", "WQT": "Work Quest", "WRC": "Worldcore", + "WREACT": "Wrapped REACT", "WRK": "BlockWRK", "WRKX": "NFT Workx", "WRLD": "NFT Worlds", @@ -15076,6 +17024,7 @@ "WRTCOIN": "WRTcoin", "WRX": "WazirX", "WRZ": "Weriz", + "WS": "Wrapped Sonic", "WSB": "WallStreetBets DApp", "WSBABY": "Wall Street Baby", "WSBC": "WSB Coin", @@ -15098,16 +17047,19 @@ "WSTORV1": "StorageChain v1", "WSTR": "Wrapped Star", "WSTUSDT": "wstUSDT", + "WSTUSR": "Resolv wstUSR", "WSX": "WeAreSatoshi", "WT": "WeToken", "WTAO": "Wrapped TAO", "WTC": "Waltonchain", "WTE": "Wonder Energy Technology", "WTF": "Waterfall Governance", + "WTFO": "WTF Opossum", "WTFT": "WTF Token", "WTFUEL": "Wrapped TFUEL", "WTG": "Watergate", "WTK": "WadzPay Token", + "WTKV1": "WadzPay Token v1", "WTL": "Welltrado", "WTN": "Wateenswap", "WTON": "Wrapped TON Crystal", @@ -15117,6 +17069,7 @@ "WUF": "WUFFI", "WUK": "WUKONG", "WUKONG": "Sun Wukong", + "WULFY": "Wulfy", "WUSD": "Worldwide USD", "WUST": "Wrapped UST Token", "WVG0": "Wrapped Virgin Gen-0 CryptoKittties", @@ -15139,6 +17092,7 @@ "WXRP": "Wrapped XRP", "WXT": "WXT", "WXTZ": "Wrapped Tezos", + "WYAC": "Woman Yelling At Cat", "WYN": "Wynn", "WYNN": "Anita Max Wynn", "WYS": "Wysker", @@ -15154,6 +17108,9 @@ "X": "X Empire", "X2": "X2Coin", "X2Y2": "X2Y2", + "X314": "X314", + "X314V1": "X314 v1", + "X33": "Shadow Liquid Staking Token", "X42": "X42 Protocol", "X7": "X7", "X7C": "X7 Coin", @@ -15165,9 +17122,11 @@ "XAGX": "Silver Token", "XAH": "Xahau", "XAI": "Xai", + "XAIGAME": "xAI Game Studio", "XALGO": "Wrapped ALGO", "XALPHA": "XAlpha AI", "XAMP": "Antiample", + "XAND": "Xandeum", "XANK": "Xank", "XAP": "Apollon", "XAR": "Arcana Network", @@ -15177,7 +17136,9 @@ "XAUM": "Matrixdock Gold", "XAUR": "Xaurum", "XAUT": "Tether Gold", + "XAUT0": "XAUt0", "XAVA": "Avalaunch", + "XAVIER": "Xavier: Renegade Angel", "XAYA": "XAYA", "XB": "XBANKING", "XBASE": "ETERBASE", @@ -15214,6 +17175,7 @@ "XCFX": "Nucleon", "XCG": "Xchange", "XCH": "Chia", + "XCHAT": "XChat", "XCHF": "CryptoFranc", "XCHNG": "Chainge Finance", "XCI": "Cannabis Industry Coin", @@ -15257,7 +17219,8 @@ "XELS": "XELS Coin", "XEM": "NEM", "XEN": "XEN Crypto", - "XEND": "Xend Finance", + "XENDV1": "Xend Finance", + "XENDV2": "Xend Finance", "XENIX": "XenixCoin", "XENO": "Xeno", "XENOVERSE": "Xenoverse", @@ -15272,8 +17235,8 @@ "XFINANCE": "Xfinance", "XFIT": "Xfit", "XFLOKI": "XFLOKI", - "XFT": "Fantasy Cash", - "XFTC": "Offshift", + "XFT": "Offshift", + "XFTV1": "Offshift v1", "XFUEL": "XFUEL", "XFUND": "xFund", "XFYI": "XCredit", @@ -15283,6 +17246,7 @@ "XGD": "X Gold", "XGEM": "Exchange Genesis Ethlas Medium", "XGLI": "Glitter Finance", + "XGN": "0xGen", "XGOLD": "XGOLD COIN", "XGOX": "Go!", "XGP": "XGP", @@ -15294,6 +17258,7 @@ "XHP": "XHYPE", "XHPV1": "XHYPE v1", "XHT": "HollaEx", + "XHUNT": "CryptoHunter World", "XHV": "Haven Protocol", "XI": "Xi", "XIASI": "Xiasi Inu", @@ -15305,6 +17270,7 @@ "XING": "Xing Xing", "XINU": "XINU", "XIO": "Blockzero Labs", + "XION": "XION", "XIOS": "Xios", "XIOT": "Xiotri", "XIV": "Project Inverse", @@ -15334,6 +17300,7 @@ "XMN": "Motion", "XMO": "Monero Original", "XMON": "XMON", + "XMOON": "r/CryptoCurrency Moons v1", "XMP": "Mapt.Coin", "XMR": "Monero", "XMRG": "Monero Gold", @@ -15355,28 +17322,35 @@ "XNO": "Xeno Token", "XNODE": "XNODE", "XNP": "ExenPay Token", + "XNPCS": "NPCS AI", "XNS": "Insolar", "XNT": "Exenium", "XNV": "Nerva", "XNX": "XanaxCoin", + "XO": "XOCIETY", "XODEX": "Xodex", "XOLO": "Xoloitzcuintli", + "XOMX": "Exxon Mobil xStock", "XOR": "Sora", "XOT": "Okuru", "XOV": "XOVBank", "XOX": "XOX Labs", "XOXNO": "XOXNO", - "XP": "Experience Points", + "XOXO": "XO Protocol", + "XP": "Xphere", "XPA": "XPA", + "XPARTY": "X Party", "XPAT": "Bitnation Pangea", "XPAY": "Wallet Pay", "XPB": "Pebble Coin", "XPC": "eXPerience Chain", "XPD": "PetroDollar", "XPE": "Xpense", + "XPED": "Xpedition", "XPET": "XPET token", "XPH": "PharmaCoin", "XPHX": "PhoenixCo Token", + "XPI": "XPi", "XPL": "Exclusive Platform", "XPLA": "XPLA", "XPLL": "ParallelChain", @@ -15402,6 +17376,7 @@ "XQN": "Quotient", "XQR": "Qredit", "XQUOK": "XQUOK", + "XR": "Xraders", "XRA": "Xriba", "XRAI": "X-Ratio A", "XRAY": "Ray Network", @@ -15409,6 +17384,7 @@ "XRD": "Radix", "XRDOGE": "XRdoge", "XRE": "RevolverCoin", + "XREA": "XREATORS", "XRGB": "XRGB", "XRISE": "Xrise", "XRL": "Rialto.AI", @@ -15418,10 +17394,10 @@ "XRP": "XRP", "XRP2": "XRP2.0", "XRP20": "XRP20", - "XRP8": "HarryPotterObamaPacMan8Inu", "XRPAYNET": "XRPayNet", "XRPC": "Xrp Classic", "XRPCHAIN": "Ripple Chain", + "XRPCV1": "XRP Classic v1", "XRPEPE": "XRPEPE", "XRPH": "XRP Healthcare", "XRS": "Xrius", @@ -15431,7 +17407,7 @@ "XSAUCE": "xSAUCE", "XSC": "Hyperspace", "XSD": "SounDAC", - "XSEED": "BitSeeds", + "XSEED": "XSEED", "XSGD": "XSGD", "XSH": "SHIELD", "XSHIB": "XSHIB", @@ -15439,6 +17415,7 @@ "XSLR": "NovaXSolar", "XSN": "StakeNet", "XSP": "XSwap", + "XSPA": "XSPA", "XSPC": "SpectreSecurityCoin", "XSPEC": "Spectre", "XSPECTAR": "xSPECTAR", @@ -15456,8 +17433,11 @@ "XTAL": "XTAL", "XTC": "TileCoin", "XTECH": "X-TECH", + "XTER": "Xterio", "XTK": "xToken", "XTM": "TORUM", + "XTMV1": "TORUM v1", + "XTN": "Neutrino Index Token", "XTO": "Tao", "XTP": "Tap", "XTR": "Xtreme", @@ -15468,6 +17448,7 @@ "XTRM": "XTRM COIN", "XTRUMP": "X TRUMP", "XTT": "XSwap Treasure", + "XTTA": "XTTA", "XTTB20": "XTblock", "XTUSD": "XT Stablecoin XTUSD", "XTV": "XTV", @@ -15497,6 +17478,7 @@ "XY": "XY Finance", "XYM": "Symbol", "XYO": "XY Oracle", + "XYRO": "XYRO", "XYZ": "Universe.XYZ", "XZK": "Mystiko Network", "Y24": "Yield 24", @@ -15517,6 +17499,7 @@ "YAMV2": "YAM v2", "YAOYAO": "Yaoyao's Cat", "YAP": "Yap Stone", + "YAPSTER": "YAPSTER", "YARL": "Yarloo", "YAW": "Yawww", "YAWN": "YAWN", @@ -15524,7 +17507,9 @@ "YAY": "YAY Games", "YAYCOIN": "YAYcoin", "YBC": "YbCoin", + "YBDBD": "YBDBD", "YBO": "Young Boys Fan Token", + "YBR": "YieldBricks", "YCC": "Yuan Chain Coin", "YCE": "MYCE", "YCO": "Y Coin", @@ -15533,13 +17518,18 @@ "YDF": "Yieldification", "YDOGE": "Yorkie Doge", "YDR": "YDragon", + "YE": "Kanye West", + "YEAI": "YE AI Agent", "YEARN": "YearnTogether", "YEC": "Ycash", "YEE": "Yeeco", "YEED": "Yggdrash", "YEEHAW": "YEEHAW", + "YEET": "Yeet", + "YEETI": "YEETI 液体", "YEFI": "YeFi", "YEL": "Yel.Finance", + "YELP": "Yelpro", "YEON": "Yeon", "YEPE": "Yellow Pepe", "YES": "YES Money", @@ -15547,6 +17537,7 @@ "YESP": "Yesports", "YESW": "Yes World", "YETI": "Yeti Finance", + "YETIUSD": "YUSD Stablecoin", "YETU": "Yetucoin", "YFARM": "YFARM Token", "YFBETA": "yfBeta", @@ -15573,6 +17564,8 @@ "YIELD": "Yield Protocol", "YIELDX": "Yield Finance", "YIKES": "Yikes Dog", + "YILONG": "Yi Long Ma", + "YILONGMA": "Chinese Elon Musk", "YIN": "YIN Finance", "YINBI": "Yinbi", "YLAY": "Yelay", @@ -15581,13 +17574,16 @@ "YLDY": "Yieldly", "YMC": "YamahaCoin", "YMS": "Yeni Malatyaspor Token", + "YNE": "yesnoerror", "YNETH": "YieldNest Restaked ETH", "YO": "Yobit Token", "YOBASE": "All Your Base", "YOC": "YoCoin", "YOCO": "YocoinYOCO", "YOD": "Year of the Dragon", + "YODA": "YODA", "YODE": "YodeSwap", + "YOEX": "YO EXCHANGE", "YOLO": "YoloNolo", "YOM": "YOM", "YONNY": "YONNY", @@ -15603,8 +17599,10 @@ "YOUNES": "YOUNES", "YOURAI": "YOUR AI", "YOURMOM": "YOUR MOM DOG", + "YOUSIM": "YouSim", "YOVI": "YobitVirtualCoin", "YOYOW": "Yoyow", + "YOZI": "YoZi Protocol", "YPC": "YoungParrot", "YPIE": "PieDAO Yearn Ecosystem Pie", "YPRISMA": "Yearn yPRISMA", @@ -15612,6 +17610,7 @@ "YSEC": "Yearn Secure", "YSR": "Ystar", "YTA": "YottaChain", + "YTC": "Yachtscoin", "YTJIA": "Jia Yueting", "YTN": "YENTEN", "YTS": "YetiSwap", @@ -15625,12 +17624,15 @@ "YUKI": "YUKI", "YUKIE": "Yukie", "YUKKY": "YUKKY", + "YUKO": "YUKO", + "YULI": "Yuliverse", "YUM": "Yumerium", "YUMMI": "Yummi Universe", "YUMMY": "Yummy", "YUP": "Crowdholding", "YURI": "YURI", - "YUSD": "YUSD Stablecoin", + "YURU": "YURU COIN", + "YUSD": "YieldFi yToken", "YUSE": "Yuse Token", "YUSRA": "YUSRA", "YUSUF": "Yusuf Dikec Meme", @@ -15642,19 +17644,24 @@ "YYE": "YYE Energy", "YYFI": "YYFI.Protocol", "YYOLO": "yYOLO", + "YZY": "Swasticoin", "Z3": "Z-Cubed", + "ZAAR": "THE•ORDZAAR•RUNES", "ZABAKU": "Zabaku Inu", "ZACK": "Zack Morris", "ZAFI": "ZakumiFi", - "ZAI": "Zero Collateral Dai", + "ZAI": "Zen AI", "ZAIF": "Zaif Token", + "ZAIFIN": "Zero Collateral Dai", "ZAM": "Zamio", "ZAMZAM": "ZAMZAM", "ZANO": "Zano", "ZAO": "zkTAO", - "ZAP": "Zap", + "ZAP": "ZAP", "ZAPI": "Zapicorn", "ZAPO": "Zapo AI", + "ZAPTOKEN": "Zap", + "ZARO": "Zaro Coin", "ZARP": "ZARP Stablecoin", "ZARX": "eToro South African Rand", "ZASH": "ZIMBOCASH", @@ -15667,6 +17674,7 @@ "ZBCN": "Zebec Network", "ZBIT": "zbit", "ZBU": "Zeebu", + "ZBUV1": "ZEEBU v1", "ZCC": "ZCC Coin", "ZCC1": "ZeroCarbon", "ZCD": "ZChains", @@ -15693,27 +17701,33 @@ "ZEDCOIN": "ZedCoin", "ZEDD": "ZedDex", "ZEDTOKEN": "Zed Token", - "ZEDX": "ZEDXION", + "ZEDX": "ZEDX Сoin", "ZEDXION": "Zedxion", + "ZEDXIONV1": "Zedxion v1", "ZEE": "ZeroSwap", + "ZEEP": "ZEEPR", "ZEFI": "ZCore Finance", "ZEFU": "Zenfuse", "ZEIT": "ZeitCoin", "ZEL": "Zelcash", "ZELIX": "ZELIX", "ZEN": "Horizen", + "ZENAD": "Zenad", + "ZENAI": "Zen AI", "ZENC": "Zenc Coin", "ZEND": "zkLend", "ZENF": "Zenland", "ZENI": "Zennies", "ZENIQ": "Zeniq Coin", "ZENITH": "Zenith Chain", + "ZENPROTOCOL": "Zen Protocol", "ZENQ": "Zenqira", "ZENT": "Zentry", "ZEON": "Zeon Network", "ZEP": "Zeppelin Dao", "ZEPH": "Zephyr Protocol", "ZER": "Zero", + "ZERC": "zkRace Coin", "ZEREBRO": "Zerebro", "ZERO": "ZeroLend", "ZEROB": "ZeroBank", @@ -15729,9 +17743,11 @@ "ZEUM": "Colizeum", "ZEUS": "Zeus Network", "ZEUSPEPES": "Zeus", + "ZEX": "Zeta", "ZEXI": "ZEXICON", "ZEXY": "ZEXY", "ZF": "zkSwap Finance ", + "ZFI": "Zyfi", "ZFL": "Zuflo Coin", "ZFLOKI": "zkFloki", "ZFM": "ZFMCOIN", @@ -15739,6 +17755,7 @@ "ZGEM": "GemSwap", "ZHC": "ZHC : Zero Hour Cash", "ZHOA": "Chengpang Zhoa", + "ZHOUKING": "ZhouKing", "ZIBU": "Zibu", "ZIG": "Zignaly", "ZIGAP": "ZIGAP", @@ -15755,12 +17772,14 @@ "ZIPT": "Zippie", "ZIRVE": "Zirve Coin", "ZIV4": "Ziv4 Labs", - "ZIX": "ZIX Token", + "ZIX": "Coinzix Token", + "ZIXTOKEN": "ZIX Token", "ZIZLE": "Zizle", "ZIZY": "ZIZY", "ZJLT": "ZJLT Distributed Factoring Network", "ZJOE": "zJOE", "ZK": "zkSync", + "ZKAI": "ZKCrypt AI", "ZKARCH": "zkArchive", "ZKB": "ZKBase", "ZKBOB": "BOB", @@ -15769,7 +17788,9 @@ "ZKDX": "ZKDX", "ZKE": "zkEra Finance", "ZKEVM": "zkEVMChain (BSC)", + "ZKEX": "zkExchange", "ZKF": "ZKFair", + "ZKGPT": "ZKGPT", "ZKGROK": "ZKGROK", "ZKGUN": "zkGUN", "ZKHIVE": "zkHive", @@ -15788,10 +17809,12 @@ "ZKSP": "zkSwap", "ZKT": "zkTube", "ZKVAULT": "zkVAULT", + "ZKWASM": "ZKWASM Token", "ZKX": "ZKX", "ZKZ": "Zkzone", "ZLA": "Zilla", - "ZLDA": "Zelda Inu", + "ZLDA": "ZELDA 2.0", + "ZLDAV1": "ZELDA v1", "ZLK": "Zenlink Network", "ZLOT": "zLOT Finance", "ZLP": "ZilPay Wallet", @@ -15800,7 +17823,7 @@ "ZMBE": "RugZombie", "ZMN": "ZMINE", "ZMT": "Zipmex Token", - "ZND": "Zenad", + "ZND": "ZND Token", "ZNE": "ZoneCoin", "ZNN": "Zenon", "ZNT": "Zenith Finance", @@ -15812,6 +17835,7 @@ "ZODI": "Zodium", "ZOE": "Zoe Cash", "ZOI": "Zoin", + "ZON": "Zon Token", "ZONE": "Zone", "ZONO": "Zono Swap", "ZONX": "METAZONX", @@ -15822,12 +17846,13 @@ "ZOOMER": "Zoomer Coin", "ZOON": "CryptoZoon", "ZOOT": "Zoo Token", - "ZORA": "Zoracles", + "ZORA": "Zora", + "ZORACLES": "Zoracles", "ZORKSEES": "Zorksees", "ZORO": "Zoro Inu", "ZORRO": "Zorro", "ZORT": "Zort", - "ZP": "Zen Protocol", + "ZP": "Zombie Power", "ZPAE": "ZelaaPayAE", "ZPAY": "ZoidPay", "ZPC": "Zen Panda Coin", @@ -15836,7 +17861,8 @@ "ZPRO": "ZAT Project", "ZPT": "Zeepin", "ZPTC": "Zeptacoin", - "ZRC": "ZrCoin", + "ZRC": "Zircuit", + "ZRCOIN": "ZrCoin", "ZRO": "LayerZero", "ZRPY": "Zerpaay", "ZRS": "Zaros", @@ -15853,6 +17879,7 @@ "ZUC": "Zeux", "ZUCKPEPE": "ZuckPepe", "ZUKI": "Zuki Moba", + "ZULU": "Zulu Network", "ZUM": "ZumCoin", "ZUN": "Zunami Governance Token", "ZUNA": "ZUNA", @@ -15881,7 +17908,9 @@ "ZYTARA": "Zytara dollar", "ZZ": "ZigZag", "ZZC": "ZudgeZury", - "ZZZ": "zzz.finance", + "ZZZ": "ZZZ", + "ZZZV1": "zzz.finance", + "anyeth1": "anyeth1", "eFIC": "FIC Network", "ePRX": "eProxy", "gOHM": "Governance OHM", diff --git a/apps/client/src/assets/site.webmanifest b/apps/api/src/assets/site.webmanifest similarity index 92% rename from apps/client/src/assets/site.webmanifest rename to apps/api/src/assets/site.webmanifest index 8f1eceefb..a28719625 100644 --- a/apps/client/src/assets/site.webmanifest +++ b/apps/api/src/assets/site.webmanifest @@ -25,7 +25,7 @@ "name": "Ghostfolio", "orientation": "portrait", "short_name": "Ghostfolio", - "start_url": "/en/", + "start_url": "/${languageCode}/", "theme_color": "#FFFFFF", - "url": "https://ghostfol.io" + "url": "${rootUrl}" } diff --git a/apps/api/src/assets/sitemap.xml b/apps/api/src/assets/sitemap.xml index 5a49f6710..fb2a5403e 100644 --- a/apps/api/src/assets/sitemap.xml +++ b/apps/api/src/assets/sitemap.xml @@ -4,589 +4,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> - - - https://ghostfol.io/de - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/blog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/features - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/haeufig-gestellte-fragen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/maerkte - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/preise - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/registrierung - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ressourcen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ressourcen/lexikon - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ressourcen/maerkte - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ressourcen/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ressourcen/ratgeber - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ueber-uns - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ueber-uns/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ueber-uns/datenschutzbestimmungen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ueber-uns/lizenz - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/de/ueber-uns/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/about - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/about/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/about/license - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/about/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2021/07/hello-ghostfolio - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/08/500-stars-on-github - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/11/black-friday-2022 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2022/12/the-importance-of-tracking-your-personal-finances - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/02/ghostfolio-meets-umbrel - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/03/ghostfolio-reaches-1000-stars-on-github - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/05/unlock-your-financial-potential-with-ghostfolio - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/07/exploring-the-path-to-fire - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/08/ghostfolio-joins-oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/09/ghostfolio-2 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/09/hacktoberfest-2023 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/11/black-week-2023 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2023/11/hacktoberfest-2023-debriefing - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2024/09/hacktoberfest-2024 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/blog/2024/11/black-weeks-2024 - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/faq - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/saas - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/self-hosting - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/features - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/markets - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/pricing - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/register - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/resources - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/resources/glossary - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/resources/guides - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/resources/markets - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/en/resources/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/funcionalidades - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/mercados - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/precios - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/preguntas-mas-frecuentes - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/recursos - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/recursos/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/registro - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/sobre - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/sobre/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/sobre/licencia - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/sobre/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/es/sobre/politica-de-privacidad - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/a-propos - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/a-propos/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/a-propos/licence - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/a-propos/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/a-propos/politique-de-confidentialite - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/enregistrement - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/fonctionnalites - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/foire-aux-questions - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/marches - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/prix - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/ressources - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/fr/ressources/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/domande-piu-frequenti - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/funzionalita - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/informazioni-su - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/informazioni-su/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/informazioni-su/informativa-sulla-privacy - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/informazioni-su/licenza - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/informazioni-su/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/iscrizione - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/mercati - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/prezzi - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/risorse - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/it/risorse/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/bronnen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/bronnen/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/functionaliteiten - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/markten - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/open - daily - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/over - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/over/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/over/licentie - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/over/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/over/privacybeleid - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/prijzen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/registratie - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/nl/veelgestelde-vragen - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pl - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pl/blog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pl/cennik - ${currentDate}T00:00:00+00:00 - - - - https://ghostfol.io/pl/funkcje - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pl/o-ghostfolio - ${currentDate}T00:00:00+00:00 - - - - https://ghostfol.io/pl/rynki - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pl/zarejestruj - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/blog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/funcionalidades - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/mercados - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/open - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/perguntas-mais-frequentes - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/precos - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/recursos - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/recursos/personal-finance-tools - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/registo - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/sobre - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/sobre/changelog - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/sobre/licenca - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/sobre/oss-friends - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/pt/sobre/politica-de-privacidade - ${currentDate}T00:00:00+00:00 - - - https://ghostfol.io/tr - ${currentDate}T00:00:00+00:00 - - + ${publicRoutes} ${personalFinanceTools} diff --git a/apps/api/src/environments/environment.prod.ts b/apps/api/src/environments/environment.prod.ts index 81b324963..6d4cbb4bf 100644 --- a/apps/api/src/environments/environment.prod.ts +++ b/apps/api/src/environments/environment.prod.ts @@ -1,4 +1,7 @@ +import { DEFAULT_HOST, DEFAULT_PORT } from '@ghostfolio/common/config'; + export const environment = { production: true, + rootUrl: `http://${DEFAULT_HOST}:${DEFAULT_PORT}`, version: `${require('../../../../package.json').version}` }; diff --git a/apps/api/src/environments/environment.ts b/apps/api/src/environments/environment.ts index c0ae2e7e5..054766460 100644 --- a/apps/api/src/environments/environment.ts +++ b/apps/api/src/environments/environment.ts @@ -1,4 +1,7 @@ +import { DEFAULT_HOST } from '@ghostfolio/common/config'; + export const environment = { production: false, + rootUrl: `https://${DEFAULT_HOST}:4200`, version: 'dev' }; diff --git a/apps/api/src/helper/object.helper.spec.ts b/apps/api/src/helper/object.helper.spec.ts index 85fb8f4eb..d7caf9bc9 100644 --- a/apps/api/src/helper/object.helper.spec.ts +++ b/apps/api/src/helper/object.helper.spec.ts @@ -1515,11 +1515,11 @@ describe('redactAttributes', () => { } }, summary: { + activityCount: 29, annualizedPerformancePercent: 0.16690880197786, annualizedPerformancePercentWithCurrencyEffect: 0.1694019484552876, cash: null, excludedAccountsAndActivities: null, - firstOrderDate: '2017-01-02T23:00:00.000Z', netPerformance: null, netPerformancePercentage: 2.3039314216696174, netPerformancePercentageWithCurrencyEffect: 2.3589806001456606, @@ -1539,7 +1539,6 @@ describe('redactAttributes', () => { interest: null, items: null, liabilities: null, - ordersCount: 29, totalInvestment: null, totalValueInBaseCurrency: null, currentNetWorth: null @@ -3019,11 +3018,11 @@ describe('redactAttributes', () => { } }, summary: { + activityCount: 29, annualizedPerformancePercent: 0.16690880197786, annualizedPerformancePercentWithCurrencyEffect: 0.1694019484552876, cash: null, excludedAccountsAndActivities: null, - firstOrderDate: '2017-01-02T23:00:00.000Z', netPerformance: null, netPerformancePercentage: 2.3039314216696174, netPerformancePercentageWithCurrencyEffect: 2.3589806001456606, @@ -3043,7 +3042,6 @@ describe('redactAttributes', () => { interest: null, items: null, liabilities: null, - ordersCount: 29, totalInvestment: null, totalValueInBaseCurrency: null, currentNetWorth: null diff --git a/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts index 227d06d7b..1600bd137 100644 --- a/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts @@ -26,7 +26,7 @@ export class TransformDataSourceInRequestInterceptor const request = http.getRequest(); if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - if (request.body.activities) { + if (request.body?.activities) { request.body.activities = request.body.activities.map((activity) => { if (DataSource[activity.dataSource]) { return activity; @@ -43,7 +43,16 @@ export class TransformDataSourceInRequestInterceptor const dataSourceValue = request[type]?.dataSource; if (dataSourceValue && !DataSource[dataSourceValue]) { - request[type].dataSource = decodeDataSource(dataSourceValue); + // In Express 5, request.query is read-only, so request[type].dataSource cannot be directly modified + Object.defineProperty(request, type, { + configurable: true, + enumerable: true, + value: { + ...request[type], + dataSource: decodeDataSource(dataSourceValue) + }, + writable: true + }); } } } diff --git a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts index f5034927c..fcbf3e76e 100644 --- a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts @@ -33,9 +33,12 @@ export class TransformDataSourceInResponseInterceptor attribute: 'dataSource', valueMap: Object.keys(DataSource).reduce( (valueMap, dataSource) => { - valueMap[dataSource] = encodeDataSource( - DataSource[dataSource] - ); + if (!['MANUAL'].includes(dataSource)) { + valueMap[dataSource] = encodeDataSource( + DataSource[dataSource] + ); + } + return valueMap; }, {} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index fdd6c1d99..41f156cbf 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,3 +1,10 @@ +import { + DEFAULT_HOST, + DEFAULT_PORT, + STORYBOOK_PATH, + SUPPORTED_LANGUAGE_CODES +} from '@ghostfolio/common/config'; + import { Logger, LogLevel, @@ -7,11 +14,11 @@ import { import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import type { NestExpressApplication } from '@nestjs/platform-express'; +import { NextFunction, Request, Response } from 'express'; import helmet from 'helmet'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; -import { HtmlTemplateMiddleware } from './middlewares/html-template.middleware'; async function bootstrap() { const configApp = await NestFactory.create(AppModule); @@ -37,7 +44,15 @@ async function bootstrap() { defaultVersion: '1', type: VersioningType.URI }); - app.setGlobalPrefix('api', { exclude: ['sitemap.xml'] }); + app.setGlobalPrefix('api', { + exclude: [ + 'sitemap.xml', + ...SUPPORTED_LANGUAGE_CODES.map((languageCode) => { + // Exclude language-specific routes with an optional wildcard + return `/${languageCode}{/*wildcard}`; + }) + ] + }); app.useGlobalPipes( new ValidationPipe({ forbidNonWhitelisted: true, @@ -50,26 +65,28 @@ async function bootstrap() { app.useBodyParser('json', { limit: '10mb' }); if (configService.get('ENABLE_FEATURE_SUBSCRIPTION') === 'true') { - app.use( - helmet({ - contentSecurityPolicy: { - directives: { - connectSrc: ["'self'", 'https://js.stripe.com'], // Allow connections to Stripe - frameSrc: ["'self'", 'https://js.stripe.com'], // Allow loading frames from Stripe - scriptSrc: ["'self'", "'unsafe-inline'", 'https://js.stripe.com'], // Allow inline scripts and scripts from Stripe - scriptSrcAttr: ["'self'", "'unsafe-inline'"], // Allow inline event handlers - styleSrc: ["'self'", "'unsafe-inline'"] // Allow inline styles - } - }, - crossOriginOpenerPolicy: false // Disable Cross-Origin-Opener-Policy header (for Internet Identity) - }) - ); + app.use((req: Request, res: Response, next: NextFunction) => { + if (req.path.startsWith(STORYBOOK_PATH)) { + next(); + } else { + helmet({ + contentSecurityPolicy: { + directives: { + connectSrc: ["'self'", 'https://js.stripe.com'], // Allow connections to Stripe + frameSrc: ["'self'", 'https://js.stripe.com'], // Allow loading frames from Stripe + scriptSrc: ["'self'", "'unsafe-inline'", 'https://js.stripe.com'], // Allow inline scripts and scripts from Stripe + scriptSrcAttr: ["'self'", "'unsafe-inline'"], // Allow inline event handlers + styleSrc: ["'self'", "'unsafe-inline'"] // Allow inline styles + } + }, + crossOriginOpenerPolicy: false // Disable Cross-Origin-Opener-Policy header (for Internet Identity) + })(req, res, next); + } + }); } - app.use(HtmlTemplateMiddleware); - - const HOST = configService.get('HOST') || '0.0.0.0'; - const PORT = configService.get('PORT') || 3333; + const HOST = configService.get('HOST') || DEFAULT_HOST; + const PORT = configService.get('PORT') || DEFAULT_PORT; await app.listen(PORT, HOST, () => { logLogo(); diff --git a/apps/api/src/middlewares/html-template.middleware.ts b/apps/api/src/middlewares/html-template.middleware.ts index 6c929c388..5cf353e9a 100644 --- a/apps/api/src/middlewares/html-template.middleware.ts +++ b/apps/api/src/middlewares/html-template.middleware.ts @@ -2,35 +2,19 @@ import { environment } from '@ghostfolio/api/environments/environment'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { DEFAULT_LANGUAGE_CODE, - DEFAULT_ROOT_URL, + STORYBOOK_PATH, SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config'; import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper'; +import { Injectable, Logger, NestMiddleware } from '@nestjs/common'; import { format } from 'date-fns'; import { NextFunction, Request, Response } from 'express'; import * as fs from 'fs'; import { join } from 'path'; -const i18nService = new I18nService(); - -let indexHtmlMap: { [languageCode: string]: string } = {}; - const title = 'Ghostfolio'; -try { - indexHtmlMap = SUPPORTED_LANGUAGE_CODES.reduce( - (map, languageCode) => ({ - ...map, - [languageCode]: fs.readFileSync( - join(__dirname, '..', 'client', languageCode, 'index.html'), - 'utf8' - ) - }), - {} - ); -} catch {} - const locales = { '/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt': { featureGraphicPath: 'assets/images/blog/ghostfolio-x-sackgeld.png', @@ -94,70 +78,93 @@ const locales = { } }; -const isFileRequest = (filename: string) => { - if (filename === '/assets/LICENSE') { - return true; - } else if ( - filename.includes('auth/ey') || - filename.includes( - 'personal-finance-tools/open-source-alternative-to-de.fi' - ) || - filename.includes( - 'personal-finance-tools/open-source-alternative-to-markets.sh' - ) - ) { - return false; - } +@Injectable() +export class HtmlTemplateMiddleware implements NestMiddleware { + private indexHtmlMap: { [languageCode: string]: string } = {}; - return filename.split('.').pop() !== filename; -}; + public constructor(private readonly i18nService: I18nService) { + try { + this.indexHtmlMap = SUPPORTED_LANGUAGE_CODES.reduce( + (map, languageCode) => ({ + ...map, + [languageCode]: fs.readFileSync( + join(__dirname, '..', 'client', languageCode, 'index.html'), + 'utf8' + ) + }), + {} + ); + } catch (error) { + Logger.error( + 'Failed to initialize index HTML map', + error, + 'HTMLTemplateMiddleware' + ); + } + } -export const HtmlTemplateMiddleware = async ( - request: Request, - response: Response, - next: NextFunction -) => { - const path = request.originalUrl.replace(/\/$/, ''); - let languageCode = path.substr(1, 2); + public use(request: Request, response: Response, next: NextFunction) { + const path = request.originalUrl.replace(/\/$/, ''); + let languageCode = path.substr(1, 2); - if (!SUPPORTED_LANGUAGE_CODES.includes(languageCode)) { - languageCode = DEFAULT_LANGUAGE_CODE; - } + if (!SUPPORTED_LANGUAGE_CODES.includes(languageCode)) { + languageCode = DEFAULT_LANGUAGE_CODE; + } - const currentDate = format(new Date(), DATE_FORMAT); - const rootUrl = process.env.ROOT_URL || DEFAULT_ROOT_URL; + const currentDate = format(new Date(), DATE_FORMAT); + const rootUrl = process.env.ROOT_URL || environment.rootUrl; - if ( - path.startsWith('/api/') || - isFileRequest(path) || - !environment.production - ) { - // Skip - next(); - } else { - const indexHtml = interpolate(indexHtmlMap[languageCode], { - currentDate, - languageCode, - path, - rootUrl, - description: i18nService.getTranslation({ + if ( + path.startsWith('/api/') || + path.startsWith(STORYBOOK_PATH) || + this.isFileRequest(path) || + !environment.production + ) { + // Skip + next(); + } else { + const indexHtml = interpolate(this.indexHtmlMap[languageCode], { + currentDate, languageCode, - id: 'metaDescription' - }), - featureGraphicPath: - locales[path]?.featureGraphicPath ?? 'assets/cover.png', - keywords: i18nService.getTranslation({ - languageCode, - id: 'metaKeywords' - }), - title: - locales[path]?.title ?? - `${title} – ${i18nService.getTranslation({ + path, + rootUrl, + description: this.i18nService.getTranslation({ + languageCode, + id: 'metaDescription' + }), + featureGraphicPath: + locales[path]?.featureGraphicPath ?? 'assets/cover.png', + keywords: this.i18nService.getTranslation({ languageCode, - id: 'slogan' - })}` - }); + id: 'metaKeywords' + }), + title: + locales[path]?.title ?? + `${title} – ${this.i18nService.getTranslation({ + languageCode, + id: 'slogan' + })}` + }); - return response.send(indexHtml); + return response.send(indexHtml); + } } -}; + + private isFileRequest(filename: string) { + if (filename === '/assets/LICENSE') { + return true; + } else if ( + filename.includes('auth/ey') || + filename.includes( + 'personal-finance-tools/open-source-alternative-to-de.fi' + ) || + filename.includes( + 'personal-finance-tools/open-source-alternative-to-markets.sh' + ) + ) { + return false; + } + + return filename.split('.').pop() !== filename; + } +} diff --git a/apps/api/src/models/interfaces/portfolio.interface.ts b/apps/api/src/models/interfaces/portfolio.interface.ts deleted file mode 100644 index b369202cd..000000000 --- a/apps/api/src/models/interfaces/portfolio.interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PortfolioItem, Position } from '@ghostfolio/common/interfaces'; - -import { Order } from '../order'; - -export interface PortfolioInterface { - get(aDate?: Date): PortfolioItem[]; - - getFees(): number; - - getPositions(aDate: Date): { - [symbol: string]: Position; - }; - - getSymbols(aDate?: Date): string[]; - - getTotalBuy(): number; - - getTotalSell(): number; - - getOrders(): Order[]; - - getValue(aDate?: Date): number; -} diff --git a/apps/api/src/models/order.ts b/apps/api/src/models/order.ts deleted file mode 100644 index 6e6762101..000000000 --- a/apps/api/src/models/order.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { IOrder } from '@ghostfolio/api/services/interfaces/interfaces'; - -import { Account, SymbolProfile, Type as ActivityType } from '@prisma/client'; -import { v4 as uuidv4 } from 'uuid'; - -export class Order { - private account: Account; - private currency: string; - private fee: number; - private date: string; - private id: string; - private isDraft: boolean; - private quantity: number; - private symbol: string; - private symbolProfile: SymbolProfile; - private total: number; - private type: ActivityType; - private unitPrice: number; - - public constructor(data: IOrder) { - this.account = data.account; - this.currency = data.currency; - this.fee = data.fee; - this.date = data.date; - this.id = data.id || uuidv4(); - this.isDraft = data.isDraft; - this.quantity = data.quantity; - this.symbol = data.symbol; - this.symbolProfile = data.symbolProfile; - this.type = data.type; - this.unitPrice = data.unitPrice; - - this.total = this.quantity * data.unitPrice; - } - - public getAccount() { - return this.account; - } - - public getCurrency() { - return this.currency; - } - - public getDate() { - return this.date; - } - - public getFee() { - return this.fee; - } - - public getId() { - return this.id; - } - - public getIsDraft() { - return this.isDraft; - } - - public getQuantity() { - return this.quantity; - } - - public getSymbol() { - return this.symbol; - } - - getSymbolProfile() { - return this.symbolProfile; - } - - public getTotal() { - return this.total; - } - - public getType() { - return this.type; - } - - public getUnitPrice() { - return this.unitPrice; - } -} diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index 187527fbb..52491a0b7 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -1,5 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; import { groupBy } from '@ghostfolio/common/helper'; import { PortfolioPosition, @@ -14,28 +15,28 @@ import { RuleInterface } from './interfaces/rule.interface'; export abstract class Rule implements RuleInterface { private key: string; - private name: string; + private languageCode: string; public constructor( protected exchangeRateDataService: ExchangeRateDataService, { key, - name + languageCode = DEFAULT_LANGUAGE_CODE }: { key: string; - name: string; + languageCode?: string; // TODO: Make mandatory } ) { this.key = key; - this.name = name; + this.languageCode = languageCode; } public getKey() { return this.key; } - public getName() { - return this.name; + public getLanguageCode() { + return this.languageCode; } public groupCurrentHoldingsByAttribute( @@ -69,9 +70,13 @@ export abstract class Rule implements RuleInterface { public abstract evaluate(aRuleSettings: T): EvaluationResult; + public abstract getCategoryName(): string; + public abstract getConfiguration(): Partial< PortfolioReportRule['configuration'] >; + public abstract getName(): string; + public abstract getSettings(aUserSettings: UserSettings): T; } diff --git a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts index 564af935d..dbf3fee4d 100644 --- a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts @@ -1,22 +1,23 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { - PortfolioDetails, - PortfolioPosition, - UserSettings -} from '@ghostfolio/common/interfaces'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { PortfolioDetails, UserSettings } from '@ghostfolio/common/interfaces'; + +import { Account } from '@prisma/client'; export class AccountClusterRiskCurrentInvestment extends Rule { private accounts: PortfolioDetails['accounts']; public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, accounts: PortfolioDetails['accounts'] ) { super(exchangeRateDataService, { - key: AccountClusterRiskCurrentInvestment.name, - name: 'Investment' + languageCode, + key: AccountClusterRiskCurrentInvestment.name }); this.accounts = accounts; @@ -24,58 +25,83 @@ export class AccountClusterRiskCurrentInvestment extends Rule { public evaluate(ruleSettings: Settings) { const accounts: { - [symbol: string]: Pick & { + [symbol: string]: Pick & { investment: number; }; } = {}; for (const [accountId, account] of Object.entries(this.accounts)) { accounts[accountId] = { - name: account.name, - investment: account.valueInBaseCurrency + investment: account.valueInBaseCurrency, + name: account.name + }; + } + + if (Object.keys(accounts).length === 0) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskCurrentInvestment.false.invalid', + languageCode: this.getLanguageCode() + }), + value: false }; } - let maxItem: (typeof accounts)[0]; + let maxAccount: (typeof accounts)[0]; let totalInvestment = 0; for (const account of Object.values(accounts)) { - if (!maxItem) { - maxItem = account; + if (!maxAccount) { + maxAccount = account; } // Calculate total investment totalInvestment += account.investment; // Find maximum - if (account.investment > maxItem?.investment) { - maxItem = account; + if (account.investment > maxAccount?.investment) { + maxAccount = account; } } - const maxInvestmentRatio = maxItem?.investment / totalInvestment || 0; + const maxInvestmentRatio = maxAccount?.investment / totalInvestment || 0; if (maxInvestmentRatio > ruleSettings.thresholdMax) { return { - evaluation: `Over ${ - ruleSettings.thresholdMax * 100 - }% of your current investment is at ${maxItem.name} (${( - maxInvestmentRatio * 100 - ).toPrecision(3)}%)`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskCurrentInvestment.false', + languageCode: this.getLanguageCode(), + placeholders: { + maxAccountName: maxAccount.name, + maxInvestmentRatio: (maxInvestmentRatio * 100).toPrecision(3), + thresholdMax: ruleSettings.thresholdMax * 100 + } + }), value: false }; } return { - evaluation: `The major part of your current investment is at ${ - maxItem.name - } (${(maxInvestmentRatio * 100).toPrecision(3)}%) and does not exceed ${ - ruleSettings.thresholdMax * 100 - }%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskCurrentInvestment.true', + languageCode: this.getLanguageCode(), + placeholders: { + maxAccountName: maxAccount.name, + maxInvestmentRatio: (maxInvestmentRatio * 100).toPrecision(3), + thresholdMax: ruleSettings.thresholdMax * 100 + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.accountClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -88,6 +114,13 @@ export class AccountClusterRiskCurrentInvestment extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskCurrentInvestment', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/account-cluster-risk/single-account.ts b/apps/api/src/models/rules/account-cluster-risk/single-account.ts index ef549e579..6045e5892 100644 --- a/apps/api/src/models/rules/account-cluster-risk/single-account.ts +++ b/apps/api/src/models/rules/account-cluster-risk/single-account.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioDetails, UserSettings } from '@ghostfolio/common/interfaces'; export class AccountClusterRiskSingleAccount extends Rule { @@ -8,36 +9,69 @@ export class AccountClusterRiskSingleAccount extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, accounts: PortfolioDetails['accounts'] ) { super(exchangeRateDataService, { - key: AccountClusterRiskSingleAccount.name, - name: 'Single Account' + languageCode, + key: AccountClusterRiskSingleAccount.name }); this.accounts = accounts; } public evaluate() { - const accounts: string[] = Object.keys(this.accounts); + const accountIds: string[] = Object.keys(this.accounts); - if (accounts.length === 1) { + if (accountIds.length === 0) { return { - evaluation: `Your net worth is managed by a single account`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskSingleAccount.false.invalid', + languageCode: this.getLanguageCode() + }), + value: false + }; + } else if (accountIds.length === 1) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskSingleAccount.false', + languageCode: this.getLanguageCode() + }), value: false }; } return { - evaluation: `Your net worth is managed by ${accounts.length} accounts`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskSingleAccount.true', + languageCode: this.getLanguageCode(), + placeholders: { + accountsLength: accountIds.length + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.accountClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return undefined; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.accountClusterRiskSingleAccount', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ xRayRules }: UserSettings): RuleSettings { return { isActive: xRayRules?.[this.getKey()].isActive ?? true diff --git a/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts b/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts index b67e01e61..5cef0333c 100644 --- a/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts +++ b/apps/api/src/models/rules/asset-class-cluster-risk/equity.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioPosition, UserSettings } from '@ghostfolio/common/interfaces'; export class AssetClassClusterRiskEquity extends Rule { @@ -8,11 +9,13 @@ export class AssetClassClusterRiskEquity extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, holdings: PortfolioPosition[] ) { super(exchangeRateDataService, { - key: AssetClassClusterRiskEquity.name, - name: 'Equity' + languageCode, + key: AssetClassClusterRiskEquity.name }); this.holdings = holdings; @@ -41,30 +44,50 @@ export class AssetClassClusterRiskEquity extends Rule { if (equityValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (equityValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } - return { - evaluation: `The equity contribution of your current investment (${(equityValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity.true', + languageCode: this.getLanguageCode(), + placeholders: { + equityValueRatio: (equityValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -78,6 +101,13 @@ export class AssetClassClusterRiskEquity extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskEquity', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts b/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts index eb744a143..ec20892e2 100644 --- a/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts +++ b/apps/api/src/models/rules/asset-class-cluster-risk/fixed-income.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioPosition, UserSettings } from '@ghostfolio/common/interfaces'; export class AssetClassClusterRiskFixedIncome extends Rule { @@ -8,11 +9,13 @@ export class AssetClassClusterRiskFixedIncome extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, holdings: PortfolioPosition[] ) { super(exchangeRateDataService, { - key: AssetClassClusterRiskFixedIncome.name, - name: 'Fixed Income' + languageCode, + key: AssetClassClusterRiskFixedIncome.name }); this.holdings = holdings; @@ -41,30 +44,50 @@ export class AssetClassClusterRiskFixedIncome extends Rule { if (fixedIncomeValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (fixedIncomeValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } - return { - evaluation: `The fixed income contribution of your current investment (${(fixedIncomeValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome.true', + languageCode: this.getLanguageCode(), + placeholders: { + fixedIncomeValueRatio: (fixedIncomeValueRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -78,6 +101,13 @@ export class AssetClassClusterRiskFixedIncome extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.assetClassClusterRiskFixedIncome', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index 90ee29c54..c427a842e 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PortfolioPosition, UserSettings } from '@ghostfolio/common/interfaces'; export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule { @@ -8,11 +9,13 @@ export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule { @@ -8,11 +9,13 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, - holdings: PortfolioPosition[] + private i18nService: I18nService, + holdings: PortfolioPosition[], + languageCode: string ) { super(exchangeRateDataService, { key: CurrencyClusterRiskCurrentInvestment.name, - name: 'Investment' + languageCode }); this.holdings = holdings; @@ -42,25 +45,40 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule { if (maxValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `Over ${ - ruleSettings.thresholdMax * 100 - }% of your current investment is in ${maxItem.groupKey} (${( - maxValueRatio * 100 - ).toPrecision(3)}%)`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.currencyClusterRiskCurrentInvestment.false', + languageCode: this.getLanguageCode(), + placeholders: { + currency: maxItem.groupKey as string, + maxValueRatio: (maxValueRatio * 100).toPrecision(3), + thresholdMax: ruleSettings.thresholdMax * 100 + } + }), value: false }; } return { - evaluation: `The major part of your current investment is in ${ - maxItem?.groupKey ?? ruleSettings.baseCurrency - } (${(maxValueRatio * 100).toPrecision(3)}%) and does not exceed ${ - ruleSettings.thresholdMax * 100 - }%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.currencyClusterRiskCurrentInvestment.true', + languageCode: this.getLanguageCode(), + placeholders: { + currency: maxItem.groupKey as string, + maxValueRatio: (maxValueRatio * 100).toPrecision(3), + thresholdMax: ruleSettings.thresholdMax * 100 + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.currencyClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -73,6 +91,13 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.currencyClusterRiskCurrentInvestment', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/economic-market-cluster-risk/developed-markets.ts b/apps/api/src/models/rules/economic-market-cluster-risk/developed-markets.ts index 15e113927..7ca7a2d76 100644 --- a/apps/api/src/models/rules/economic-market-cluster-risk/developed-markets.ts +++ b/apps/api/src/models/rules/economic-market-cluster-risk/developed-markets.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { UserSettings } from '@ghostfolio/common/interfaces'; export class EconomicMarketClusterRiskDevelopedMarkets extends Rule { @@ -9,12 +10,14 @@ export class EconomicMarketClusterRiskDevelopedMarkets extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, currentValueInBaseCurrency: number, - developedMarketsValueInBaseCurrency: number + developedMarketsValueInBaseCurrency: number, + languageCode: string ) { super(exchangeRateDataService, { - key: EconomicMarketClusterRiskDevelopedMarkets.name, - name: 'Developed Markets' + languageCode, + key: EconomicMarketClusterRiskDevelopedMarkets.name }); this.currentValueInBaseCurrency = currentValueInBaseCurrency; @@ -30,30 +33,57 @@ export class EconomicMarketClusterRiskDevelopedMarkets extends Rule { if (developedMarketsValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The developed markets contribution of your current investment (${(developedMarketsValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskDevelopedMarkets.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + developedMarketsValueRatio: ( + developedMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (developedMarketsValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The developed markets contribution of your current investment (${(developedMarketsValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskDevelopedMarkets.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + developedMarketsValueRatio: ( + developedMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The developed markets contribution of your current investment (${(developedMarketsValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskDevelopedMarkets.true', + languageCode: this.getLanguageCode(), + placeholders: { + developedMarketsValueRatio: ( + developedMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -67,6 +97,13 @@ export class EconomicMarketClusterRiskDevelopedMarkets extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskDevelopedMarkets', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/economic-market-cluster-risk/emerging-markets.ts b/apps/api/src/models/rules/economic-market-cluster-risk/emerging-markets.ts index 8fccdf1d8..cbf9f98b7 100644 --- a/apps/api/src/models/rules/economic-market-cluster-risk/emerging-markets.ts +++ b/apps/api/src/models/rules/economic-market-cluster-risk/emerging-markets.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { UserSettings } from '@ghostfolio/common/interfaces'; export class EconomicMarketClusterRiskEmergingMarkets extends Rule { @@ -9,12 +10,14 @@ export class EconomicMarketClusterRiskEmergingMarkets extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, currentValueInBaseCurrency: number, - emergingMarketsValueInBaseCurrency: number + emergingMarketsValueInBaseCurrency: number, + languageCode: string ) { super(exchangeRateDataService, { - key: EconomicMarketClusterRiskEmergingMarkets.name, - name: 'Emerging Markets' + languageCode, + key: EconomicMarketClusterRiskEmergingMarkets.name }); this.currentValueInBaseCurrency = currentValueInBaseCurrency; @@ -30,30 +33,57 @@ export class EconomicMarketClusterRiskEmergingMarkets extends Rule { if (emergingMarketsValueRatio > ruleSettings.thresholdMax) { return { - evaluation: `The emerging markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) exceeds ${( - ruleSettings.thresholdMax * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskEmergingMarkets.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + emergingMarketsValueRatio: ( + emergingMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: false }; } else if (emergingMarketsValueRatio < ruleSettings.thresholdMin) { return { - evaluation: `The emerging markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) is below ${( - ruleSettings.thresholdMin * 100 - ).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskEmergingMarkets.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + emergingMarketsValueRatio: ( + emergingMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The emerging markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) is within the range of ${( - ruleSettings.thresholdMin * 100 - ).toPrecision( - 3 - )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskEmergingMarkets.true', + languageCode: this.getLanguageCode(), + placeholders: { + emergingMarketsValueRatio: ( + emergingMarketsValueRatio * 100 + ).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3) + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRisk.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -67,6 +97,13 @@ export class EconomicMarketClusterRiskEmergingMarkets extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.economicMarketClusterRiskEmergingMarkets', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts b/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts index d13f2ffc5..1de51d0e7 100644 --- a/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts +++ b/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { UserSettings } from '@ghostfolio/common/interfaces'; export class EmergencyFundSetup extends Rule { @@ -8,11 +9,13 @@ export class EmergencyFundSetup extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, emergencyFund: number ) { super(exchangeRateDataService, { - key: EmergencyFundSetup.name, - name: 'Emergency Fund: Set up' + languageCode, + key: EmergencyFundSetup.name }); this.emergencyFund = emergencyFund; @@ -21,21 +24,41 @@ export class EmergencyFundSetup extends Rule { public evaluate() { if (!this.emergencyFund) { return { - evaluation: 'No emergency fund has been set up', + evaluation: this.i18nService.getTranslation({ + id: 'rule.emergencyFundSetup.false', + languageCode: this.getLanguageCode() + }), value: false }; } return { - evaluation: 'An emergency fund has been set up', + evaluation: this.i18nService.getTranslation({ + id: 'rule.emergencyFundSetup.true', + languageCode: this.getLanguageCode() + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.emergencyFund.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return undefined; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.emergencyFundSetup', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index fa9d7e7bc..805b86fd4 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -1,6 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { UserSettings } from '@ghostfolio/common/interfaces'; export class FeeRatioInitialInvestment extends Rule { @@ -9,12 +10,14 @@ export class FeeRatioInitialInvestment extends Rule { public constructor( protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, totalInvestment: number, fees: number ) { super(exchangeRateDataService, { - key: FeeRatioInitialInvestment.name, - name: 'Fee Ratio' + languageCode, + key: FeeRatioInitialInvestment.name }); this.fees = fees; @@ -28,21 +31,38 @@ export class FeeRatioInitialInvestment extends Rule { if (feeRatio > ruleSettings.thresholdMax) { return { - evaluation: `The fees do exceed ${ - ruleSettings.thresholdMax * 100 - }% of your initial investment (${(feeRatio * 100).toPrecision(3)}%)`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.feeRatioInitialInvestment.false', + languageCode: this.getLanguageCode(), + placeholders: { + feeRatio: (ruleSettings.thresholdMax * 100).toFixed(2), + thresholdMax: (feeRatio * 100).toPrecision(3) + } + }), value: false }; } return { - evaluation: `The fees do not exceed ${ - ruleSettings.thresholdMax * 100 - }% of your initial investment (${(feeRatio * 100).toPrecision(3)}%)`, + evaluation: this.i18nService.getTranslation({ + id: 'rule.feeRatioInitialInvestment.true', + languageCode: this.getLanguageCode(), + placeholders: { + feeRatio: (feeRatio * 100).toPrecision(3), + thresholdMax: (ruleSettings.thresholdMax * 100).toFixed(2) + } + }), value: true }; } + public getCategoryName() { + return this.i18nService.getTranslation({ + id: 'rule.fees.category', + languageCode: this.getLanguageCode() + }); + } + public getConfiguration() { return { threshold: { @@ -55,6 +75,13 @@ export class FeeRatioInitialInvestment extends Rule { }; } + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.feeRatioInitialInvestment', + languageCode: this.getLanguageCode() + }); + } + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts b/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts new file mode 100644 index 000000000..5d6cc999a --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/asia-pacific.ts @@ -0,0 +1,105 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskAsiaPacific extends Rule { + private asiaPacificValueInBaseCurrency: number; + private currentValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, + currentValueInBaseCurrency: number, + asiaPacificValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + languageCode, + key: RegionalMarketClusterRiskAsiaPacific.name + }); + + this.asiaPacificValueInBaseCurrency = asiaPacificValueInBaseCurrency; + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const asiaPacificMarketValueRatio = this.currentValueInBaseCurrency + ? this.asiaPacificValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (asiaPacificMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } else if (asiaPacificMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } + + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (asiaPacificMarketValueRatio * 100).toPrecision(3) + } + }), + value: true + }; + } + + public getCategoryName() { + return 'Regional Market Cluster Risk'; // TODO: Replace hardcoded text with i18n translation + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskAsiaPacific', + languageCode: this.getLanguageCode() + }); + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.03, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.02 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts new file mode 100644 index 000000000..fa13a9e57 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts @@ -0,0 +1,107 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskEmergingMarkets extends Rule { + private currentValueInBaseCurrency: number; + private emergingMarketsValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, + currentValueInBaseCurrency: number, + emergingMarketsValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + languageCode, + key: RegionalMarketClusterRiskEmergingMarkets.name + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.emergingMarketsValueInBaseCurrency = + emergingMarketsValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const emergingMarketsValueRatio = this.currentValueInBaseCurrency + ? this.emergingMarketsValueInBaseCurrency / + this.currentValueInBaseCurrency + : 0; + + if (emergingMarketsValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } else if (emergingMarketsValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } + + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (emergingMarketsValueRatio * 100).toPrecision(3) + } + }), + value: true + }; + } + + public getCategoryName() { + return 'Regional Market Cluster Risk'; // TODO: Replace hardcoded text with i18n translation + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEmergingMarkets', + languageCode: this.getLanguageCode() + }); + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.12, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.08 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts new file mode 100644 index 000000000..3bbe7af84 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts @@ -0,0 +1,105 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskEurope extends Rule { + private currentValueInBaseCurrency: number; + private europeValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, + currentValueInBaseCurrency: number, + europeValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + languageCode, + key: RegionalMarketClusterRiskEurope.name + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.europeValueInBaseCurrency = europeValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const europeMarketValueRatio = this.currentValueInBaseCurrency + ? this.europeValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (europeMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } else if (europeMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } + + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (europeMarketValueRatio * 100).toPrecision(3) + } + }), + value: true + }; + } + + public getCategoryName() { + return 'Regional Market Cluster Risk'; // TODO: Replace hardcoded text with i18n translation + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskEurope', + languageCode: this.getLanguageCode() + }); + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.15, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.11 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts b/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts new file mode 100644 index 000000000..8b9fddf3a --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts @@ -0,0 +1,7 @@ +import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; + +export interface Settings extends RuleSettings { + baseCurrency: string; + thresholdMin: number; + thresholdMax: number; +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts b/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts new file mode 100644 index 000000000..952e14795 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/japan.ts @@ -0,0 +1,105 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskJapan extends Rule { + private currentValueInBaseCurrency: number; + private japanValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, + currentValueInBaseCurrency: number, + japanValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + languageCode, + key: RegionalMarketClusterRiskJapan.name + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.japanValueInBaseCurrency = japanValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const japanMarketValueRatio = this.currentValueInBaseCurrency + ? this.japanValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (japanMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } else if (japanMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } + + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (japanMarketValueRatio * 100).toPrecision(3) + } + }), + value: true + }; + } + + public getCategoryName() { + return 'Regional Market Cluster Risk'; // TODO: Replace hardcoded text with i18n translation + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskJapan', + languageCode: this.getLanguageCode() + }); + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.06, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.04 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts new file mode 100644 index 000000000..f022ecff9 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts @@ -0,0 +1,105 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskNorthAmerica extends Rule { + private currentValueInBaseCurrency: number; + private northAmericaValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private i18nService: I18nService, + languageCode: string, + currentValueInBaseCurrency: number, + northAmericaValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + languageCode, + key: RegionalMarketClusterRiskNorthAmerica.name + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.northAmericaValueInBaseCurrency = northAmericaValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const northAmericaMarketValueRatio = this.currentValueInBaseCurrency + ? this.northAmericaValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (northAmericaMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica.false.max', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } else if (northAmericaMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica.false.min', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), + value: false + }; + } + + return { + evaluation: this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica.true', + languageCode: this.getLanguageCode(), + placeholders: { + thresholdMax: (ruleSettings.thresholdMax * 100).toPrecision(3), + thresholdMin: (ruleSettings.thresholdMin * 100).toPrecision(3), + valueRatio: (northAmericaMarketValueRatio * 100).toPrecision(3) + } + }), + value: true + }; + } + + public getCategoryName() { + return 'Regional Market Cluster Risk'; // TODO: Replace hardcoded text with i18n translation + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getName() { + return this.i18nService.getTranslation({ + id: 'rule.regionalMarketClusterRiskNorthAmerica', + languageCode: this.getLanguageCode() + }); + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.69, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.65 + }; + } +} diff --git a/apps/api/src/services/benchmark/benchmark.module.ts b/apps/api/src/services/benchmark/benchmark.module.ts new file mode 100644 index 000000000..870ef244f --- /dev/null +++ b/apps/api/src/services/benchmark/benchmark.module.ts @@ -0,0 +1,24 @@ +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; +import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; + +import { Module } from '@nestjs/common'; + +import { BenchmarkService } from './benchmark.service'; + +@Module({ + exports: [BenchmarkService], + imports: [ + DataProviderModule, + MarketDataModule, + PrismaModule, + PropertyModule, + RedisCacheModule, + SymbolProfileModule + ], + providers: [BenchmarkService] +}) +export class BenchmarkModule {} diff --git a/apps/api/src/app/benchmark/benchmark.service.spec.ts b/apps/api/src/services/benchmark/benchmark.service.spec.ts similarity index 74% rename from apps/api/src/app/benchmark/benchmark.service.spec.ts rename to apps/api/src/services/benchmark/benchmark.service.spec.ts index 5371fcdc0..833dbcdfc 100644 --- a/apps/api/src/app/benchmark/benchmark.service.spec.ts +++ b/apps/api/src/services/benchmark/benchmark.service.spec.ts @@ -4,17 +4,7 @@ describe('BenchmarkService', () => { let benchmarkService: BenchmarkService; beforeAll(async () => { - benchmarkService = new BenchmarkService( - null, - null, - null, - null, - null, - null, - null, - null, - null - ); + benchmarkService = new BenchmarkService(null, null, null, null, null, null); }); it('calculateChangeInPercentage', async () => { diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/services/benchmark/benchmark.service.ts similarity index 64% rename from apps/api/src/app/benchmark/benchmark.service.ts rename to apps/api/src/services/benchmark/benchmark.service.ts index a659281d7..4b1d9a65f 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/services/benchmark/benchmark.service.ts @@ -1,8 +1,5 @@ import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; -import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; -import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; @@ -11,16 +8,10 @@ import { CACHE_TTL_INFINITE, PROPERTY_BENCHMARKS } from '@ghostfolio/common/config'; -import { - DATE_FORMAT, - calculateBenchmarkTrend, - parseDate, - resetHours -} from '@ghostfolio/common/helper'; +import { calculateBenchmarkTrend } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, Benchmark, - BenchmarkMarketDataDetails, BenchmarkProperty, BenchmarkResponse } from '@ghostfolio/common/interfaces'; @@ -29,16 +20,8 @@ import { BenchmarkTrend } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { - addHours, - differenceInDays, - eachDayOfInterval, - format, - isAfter, - isSameDay, - subDays -} from 'date-fns'; -import { isNumber, last, uniqBy } from 'lodash'; +import { addHours, isAfter, subDays } from 'date-fns'; +import { uniqBy } from 'lodash'; import ms from 'ms'; import { BenchmarkValue } from './interfaces/benchmark-value.interface'; @@ -48,15 +31,12 @@ export class BenchmarkService { private readonly CACHE_KEY_BENCHMARKS = 'BENCHMARKS'; public constructor( - private readonly configurationService: ConfigurationService, private readonly dataProviderService: DataProviderService, - private readonly exchangeRateDataService: ExchangeRateDataService, private readonly marketDataService: MarketDataService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly redisCacheService: RedisCacheService, - private readonly symbolProfileService: SymbolProfileService, - private readonly symbolService: SymbolService + private readonly symbolProfileService: SymbolProfileService ) {} public calculateChangeInPercentage(baseValue: number, currentValue: number) { @@ -126,9 +106,9 @@ export class BenchmarkService { enableSharing = false } = {}): Promise[]> { const symbolProfileIds: string[] = ( - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_BENCHMARKS - )) as BenchmarkProperty[]) ?? [] + )) ?? [] ) .filter((benchmark) => { if (enableSharing) { @@ -153,139 +133,9 @@ export class BenchmarkService { symbol }; }) - .sort((a, b) => a.name.localeCompare(b.name)); - } - - public async getMarketDataForUser({ - dataSource, - endDate = new Date(), - startDate, - symbol, - userCurrency - }: { - endDate?: Date; - startDate: Date; - userCurrency: string; - } & AssetProfileIdentifier): Promise { - const marketData: { date: string; value: number }[] = []; - - const days = differenceInDays(endDate, startDate) + 1; - const dates = eachDayOfInterval( - { - start: startDate, - end: endDate - }, - { - step: Math.round( - days / - Math.min(days, this.configurationService.get('MAX_CHART_ITEMS')) - ) - } - ).map((date) => { - return resetHours(date); - }); - - const [currentSymbolItem, marketDataItems] = await Promise.all([ - this.symbolService.get({ - dataGatheringItem: { - dataSource, - symbol - } - }), - this.marketDataService.marketDataItems({ - orderBy: { - date: 'asc' - }, - where: { - dataSource, - symbol, - date: { - in: dates - } - } - }) - ]); - - const exchangeRates = - await this.exchangeRateDataService.getExchangeRatesByCurrency({ - startDate, - currencies: [currentSymbolItem.currency], - targetCurrency: userCurrency - }); - - const exchangeRateAtStartDate = - exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ - format(startDate, DATE_FORMAT) - ]; - - const marketPriceAtStartDate = marketDataItems?.find(({ date }) => { - return isSameDay(date, startDate); - })?.marketPrice; - - if (!marketPriceAtStartDate) { - Logger.error( - `No historical market data has been found for ${symbol} (${dataSource}) at ${format( - startDate, - DATE_FORMAT - )}`, - 'BenchmarkService' - ); - - return { marketData }; - } - - for (const marketDataItem of marketDataItems) { - const exchangeRate = - exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ - format(marketDataItem.date, DATE_FORMAT) - ]; - - const exchangeRateFactor = - isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate) - ? exchangeRate / exchangeRateAtStartDate - : 1; - - marketData.push({ - date: format(marketDataItem.date, DATE_FORMAT), - value: - marketPriceAtStartDate === 0 - ? 0 - : this.calculateChangeInPercentage( - marketPriceAtStartDate, - marketDataItem.marketPrice * exchangeRateFactor - ) * 100 + .sort((a, b) => { + return a.name?.localeCompare(b?.name) ?? 0; }); - } - - const includesEndDate = isSameDay( - parseDate(last(marketData).date), - endDate - ); - - if (currentSymbolItem?.marketPrice && !includesEndDate) { - const exchangeRate = - exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ - format(endDate, DATE_FORMAT) - ]; - - const exchangeRateFactor = - isNumber(exchangeRateAtStartDate) && isNumber(exchangeRate) - ? exchangeRate / exchangeRateAtStartDate - : 1; - - marketData.push({ - date: format(endDate, DATE_FORMAT), - value: - this.calculateChangeInPercentage( - marketPriceAtStartDate, - currentSymbolItem.marketPrice * exchangeRateFactor - ) * 100 - }); - } - - return { - marketData - }; } public async addBenchmark({ @@ -304,9 +154,9 @@ export class BenchmarkService { } let benchmarks = - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_BENCHMARKS - )) as BenchmarkProperty[]) ?? []; + )) ?? []; benchmarks.push({ symbolProfileId: assetProfile.id }); @@ -341,9 +191,9 @@ export class BenchmarkService { } let benchmarks = - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_BENCHMARKS - )) as BenchmarkProperty[]) ?? []; + )) ?? []; benchmarks = benchmarks.filter(({ symbolProfileId }) => { return symbolProfileId !== assetProfile.id; @@ -362,6 +212,18 @@ export class BenchmarkService { }; } + public getMarketCondition( + aPerformanceInPercent: number + ): Benchmark['marketCondition'] { + if (aPerformanceInPercent >= 0) { + return 'ALL_TIME_HIGH'; + } else if (aPerformanceInPercent <= -0.2) { + return 'BEAR_MARKET'; + } else { + return 'NEUTRAL_MARKET'; + } + } + private async calculateAndCacheBenchmarks({ enableSharing = false }): Promise { @@ -452,16 +314,4 @@ export class BenchmarkService { return benchmarks; } - - private getMarketCondition( - aPerformanceInPercent: number - ): Benchmark['marketCondition'] { - if (aPerformanceInPercent >= 0) { - return 'ALL_TIME_HIGH'; - } else if (aPerformanceInPercent <= -0.2) { - return 'BEAR_MARKET'; - } else { - return 'NEUTRAL_MARKET'; - } - } } diff --git a/apps/api/src/app/benchmark/interfaces/benchmark-value.interface.ts b/apps/api/src/services/benchmark/interfaces/benchmark-value.interface.ts similarity index 100% rename from apps/api/src/app/benchmark/interfaces/benchmark-value.interface.ts rename to apps/api/src/services/benchmark/interfaces/benchmark-value.interface.ts diff --git a/apps/api/src/services/configuration/configuration.service.ts b/apps/api/src/services/configuration/configuration.service.ts index 3dfe5d5c5..602ad5e9c 100644 --- a/apps/api/src/services/configuration/configuration.service.ts +++ b/apps/api/src/services/configuration/configuration.service.ts @@ -1,11 +1,13 @@ +import { environment } from '@ghostfolio/api/environments/environment'; import { Environment } from '@ghostfolio/api/services/interfaces/environment.interface'; import { CACHE_TTL_NO_CACHE, + DEFAULT_HOST, + DEFAULT_PORT, DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY, DEFAULT_PROCESSOR_GATHER_HISTORICAL_MARKET_DATA_CONCURRENCY, DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_CONCURRENCY, - DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_TIMEOUT, - DEFAULT_ROOT_URL + DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_TIMEOUT } from '@ghostfolio/common/config'; import { Injectable } from '@nestjs/common'; @@ -38,6 +40,9 @@ export class ConfigurationService { DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER: json({ default: [] }), + DATA_SOURCES_LEGACY: json({ + default: [] + }), ENABLE_FEATURE_FEAR_AND_GREED_INDEX: bool({ default: false }), ENABLE_FEATURE_READ_ONLY_MODE: bool({ default: false }), ENABLE_FEATURE_SOCIAL_LOGIN: bool({ default: false }), @@ -49,11 +54,11 @@ export class ConfigurationService { GOOGLE_SHEETS_ACCOUNT: str({ default: '' }), GOOGLE_SHEETS_ID: str({ default: '' }), GOOGLE_SHEETS_PRIVATE_KEY: str({ default: '' }), - HOST: host({ default: '0.0.0.0' }), + HOST: host({ default: DEFAULT_HOST }), JWT_SECRET_KEY: str({}), MAX_ACTIVITIES_TO_IMPORT: num({ default: Number.MAX_SAFE_INTEGER }), MAX_CHART_ITEMS: num({ default: 365 }), - PORT: port({ default: 3333 }), + PORT: port({ default: DEFAULT_PORT }), PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY: num({ default: DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY }), @@ -71,7 +76,9 @@ export class ConfigurationService { REDIS_PASSWORD: str({ default: '' }), REDIS_PORT: port({ default: 6379 }), REQUEST_TIMEOUT: num({ default: ms('3 seconds') }), - ROOT_URL: url({ default: DEFAULT_ROOT_URL }), + ROOT_URL: url({ + default: environment.rootUrl + }), STRIPE_PUBLIC_KEY: str({ default: '' }), STRIPE_SECRET_KEY: str({ default: '' }), TWITTER_ACCESS_TOKEN: str({ default: 'dummyAccessToken' }), diff --git a/apps/api/src/services/cron/cron.module.ts b/apps/api/src/services/cron/cron.module.ts new file mode 100644 index 000000000..06f9d2caa --- /dev/null +++ b/apps/api/src/services/cron/cron.module.ts @@ -0,0 +1,23 @@ +import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; +import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; +import { TwitterBotModule } from '@ghostfolio/api/services/twitter-bot/twitter-bot.module'; + +import { Module } from '@nestjs/common'; + +import { CronService } from './cron.service'; + +@Module({ + imports: [ + ConfigurationModule, + DataGatheringModule, + ExchangeRateDataModule, + PropertyModule, + TwitterBotModule, + UserModule + ], + providers: [CronService] +}) +export class CronModule {} diff --git a/apps/api/src/services/cron.service.ts b/apps/api/src/services/cron/cron.service.ts similarity index 71% rename from apps/api/src/services/cron.service.ts rename to apps/api/src/services/cron/cron.service.ts index 7a1b30b5f..b770aa2d7 100644 --- a/apps/api/src/services/cron.service.ts +++ b/apps/api/src/services/cron/cron.service.ts @@ -1,8 +1,13 @@ import { UserService } from '@ghostfolio/api/app/user/user.service'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; +import { TwitterBotService } from '@ghostfolio/api/services/twitter-bot/twitter-bot.service'; import { DATA_GATHERING_QUEUE_PRIORITY_LOW, - GATHER_ASSET_PROFILE_PROCESS, - GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, + GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, PROPERTY_IS_DATA_GATHERING_ENABLED } from '@ghostfolio/common/config'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; @@ -10,12 +15,6 @@ import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { Injectable } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; -import { ConfigurationService } from './configuration/configuration.service'; -import { ExchangeRateDataService } from './exchange-rate-data/exchange-rate-data.service'; -import { PropertyService } from './property/property.service'; -import { DataGatheringService } from './queues/data-gathering/data-gathering.service'; -import { TwitterBotService } from './twitter-bot/twitter-bot.service'; - @Injectable() export class CronService { private static readonly EVERY_SUNDAY_AT_LUNCH_TIME = '0 12 * * 0'; @@ -43,7 +42,9 @@ export class CronService { @Cron(CronExpression.EVERY_DAY_AT_5PM) public async runEveryDayAtFivePm() { - this.twitterBotService.tweetFearAndGreedIndex(); + if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { + this.twitterBotService.tweetFearAndGreedIndex(); + } } @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) @@ -57,7 +58,7 @@ export class CronService { public async runEverySundayAtTwelvePm() { if (await this.isDataGatheringEnabled()) { const assetProfileIdentifiers = - await this.dataGatheringService.getAllAssetProfileIdentifiers(); + await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { @@ -66,9 +67,9 @@ export class CronService { dataSource, symbol }, - name: GATHER_ASSET_PROFILE_PROCESS, + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, opts: { - ...GATHER_ASSET_PROFILE_PROCESS_OPTIONS, + ...GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, jobId: getAssetProfileIdentifier({ dataSource, symbol }), priority: DATA_GATHERING_QUEUE_PRIORITY_LOW } diff --git a/apps/api/src/services/cryptocurrency/cryptocurrency.service.ts b/apps/api/src/services/cryptocurrency/cryptocurrency.service.ts index db5cf0876..b814fc186 100644 --- a/apps/api/src/services/cryptocurrency/cryptocurrency.service.ts +++ b/apps/api/src/services/cryptocurrency/cryptocurrency.service.ts @@ -1,3 +1,5 @@ +import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; + import { Injectable } from '@nestjs/common'; const cryptocurrencies = require('../../assets/cryptocurrencies/cryptocurrencies.json'); @@ -9,7 +11,11 @@ export class CryptocurrencyService { public isCryptocurrency(aSymbol = '') { const cryptocurrencySymbol = aSymbol.substring(0, aSymbol.length - 3); - return this.getCryptocurrencies().includes(cryptocurrencySymbol); + + return ( + aSymbol.endsWith(DEFAULT_CURRENCY) && + this.getCryptocurrencies().includes(cryptocurrencySymbol) + ); } private getCryptocurrencies() { diff --git a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts index 5c9eee127..1e8f7eefa 100644 --- a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts +++ b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -10,6 +11,7 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; +import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { DataProviderInfo, @@ -41,9 +43,7 @@ export class AlphaVantageService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { return { symbol, dataSource: this.getName() @@ -52,6 +52,7 @@ export class AlphaVantageService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.ALPHA_VANTAGE, isPremium: false, name: 'Alpha Vantage', url: 'https://www.alphavantage.co' @@ -73,7 +74,9 @@ export class AlphaVantageService implements DataProviderInterface { const historicalData: { [symbol: string]: IAlphaVantageHistoricalResponse[]; } = await this.alphaVantage.crypto.daily( - symbol.substring(0, symbol.length - 3).toLowerCase(), + symbol + .substring(0, symbol.length - DEFAULT_CURRENCY.length) + .toLowerCase(), 'usd' ); diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index ddc04ffcd..7776ff46c 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -26,12 +27,11 @@ import { SymbolProfile } from '@prisma/client'; import { format, fromUnixTime, getUnixTime } from 'date-fns'; -import got, { Headers } from 'got'; @Injectable() export class CoinGeckoService implements DataProviderInterface { private readonly apiUrl: string; - private readonly headers: Headers = {}; + private readonly headers: HeadersInit = {}; public constructor( private readonly configurationService: ConfigurationService @@ -57,9 +57,7 @@ export class CoinGeckoService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { const response: Partial = { symbol, assetClass: AssetClass.LIQUIDITY, @@ -69,19 +67,18 @@ export class CoinGeckoService implements DataProviderInterface { }; try { - const { name } = await got(`${this.apiUrl}/coins/${symbol}`, { + const { name } = await fetch(`${this.apiUrl}/coins/${symbol}`, { headers: this.headers, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) - }).json(); + }).then((res) => res.json()); response.name = name; } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to get the asset profile for ${symbol} was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; @@ -95,6 +92,7 @@ export class CoinGeckoService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.COINGECKO, isPremium: false, name: 'CoinGecko', url: 'https://coingecko.com' @@ -114,7 +112,7 @@ export class CoinGeckoService implements DataProviderInterface { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { try { - const { prices } = await got( + const { error, prices, status } = await fetch( `${ this.apiUrl }/coins/${symbol}/market_chart/range?vs_currency=${DEFAULT_CURRENCY.toLowerCase()}&from=${getUnixTime( @@ -122,10 +120,17 @@ export class CoinGeckoService implements DataProviderInterface { )}&to=${getUnixTime(to)}`, { headers: this.headers, - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); + + if (error?.status) { + throw new Error(error.status.error_message); + } + + if (status) { + throw new Error(status.error_message); + } const result: { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; @@ -169,16 +174,15 @@ export class CoinGeckoService implements DataProviderInterface { } try { - const quotes = await got( + const quotes = await fetch( `${this.apiUrl}/simple/price?ids=${symbols.join( ',' )}&vs_currencies=${DEFAULT_CURRENCY.toLowerCase()}`, { headers: this.headers, - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); for (const symbol in quotes) { response[symbol] = { @@ -192,7 +196,7 @@ export class CoinGeckoService implements DataProviderInterface { } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; @@ -212,13 +216,12 @@ export class CoinGeckoService implements DataProviderInterface { let items: LookupItem[] = []; try { - const { coins } = await got(`${this.apiUrl}/search?query=${query}`, { + const { coins } = await fetch(`${this.apiUrl}/search?query=${query}`, { headers: this.headers, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) - }).json(); + }).then((res) => res.json()); items = coins.map(({ id: symbol, name }) => { return { @@ -234,7 +237,7 @@ export class CoinGeckoService implements DataProviderInterface { } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; diff --git a/apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts b/apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts index 3efe7e40d..bb9d0606c 100644 --- a/apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/openfigi/openfigi.service.ts @@ -4,7 +4,6 @@ import { parseSymbol } from '@ghostfolio/common/helper'; import { Injectable } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; -import got, { Headers } from 'got'; @Injectable() export class OpenFigiDataEnhancerService implements DataEnhancerInterface { @@ -32,7 +31,7 @@ export class OpenFigiDataEnhancerService implements DataEnhancerInterface { return response; } - const headers: Headers = {}; + const headers: HeadersInit = {}; const { exchange, ticker } = parseSymbol({ symbol, dataSource: response.dataSource @@ -43,14 +42,20 @@ export class OpenFigiDataEnhancerService implements DataEnhancerInterface { this.configurationService.get('API_KEY_OPEN_FIGI'); } - const mappings = await got - .post(`${OpenFigiDataEnhancerService.baseUrl}/v3/mapping`, { - headers, - json: [{ exchCode: exchange, idType: 'TICKER', idValue: ticker }], - // @ts-ignore + const mappings = (await fetch( + `${OpenFigiDataEnhancerService.baseUrl}/v3/mapping`, + { + body: JSON.stringify([ + { exchCode: exchange, idType: 'TICKER', idValue: ticker } + ]), + headers: { + 'Content-Type': 'application/json', + ...headers + }, + method: 'POST', signal: AbortSignal.timeout(requestTimeout) - }) - .json(); + } + ).then((res) => res.json())) as any[]; if (mappings?.length === 1 && mappings[0].data?.length === 1) { const { compositeFIGI, figi, shareClassFIGI } = mappings[0].data[0]; diff --git a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts index a4e695284..8b885c013 100644 --- a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts @@ -7,7 +7,6 @@ import { Sector } from '@ghostfolio/common/interfaces/sector.interface'; import { Injectable } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { countries } from 'countries-list'; -import got from 'got'; @Injectable() export class TrackinsightDataEnhancerService implements DataEnhancerInterface { @@ -45,64 +44,54 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { return response; } - const profile = await got( - `${TrackinsightDataEnhancerService.baseUrl}/funds/${symbol}.json`, + let trackinsightSymbol = await this.searchTrackinsightSymbol({ + requestTimeout, + symbol + }); + + if (!trackinsightSymbol) { + trackinsightSymbol = await this.searchTrackinsightSymbol({ + requestTimeout, + symbol: symbol.split('.')?.[0] + }); + } + + if (!trackinsightSymbol) { + return response; + } + + const profile = await fetch( + `${TrackinsightDataEnhancerService.baseUrl}/funds/${trackinsightSymbol}.json`, { - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } ) - .json() + .then((res) => res.json()) .catch(() => { - return got( - `${TrackinsightDataEnhancerService.baseUrl}/funds/${ - symbol.split('.')?.[0] - }.json`, - { - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - } - ) - .json() - .catch(() => { - return {}; - }); + return {}; }); - const isin = profile?.isin?.split(';')?.[0]; + const cusip = profile?.cusip; + + if (cusip) { + response.cusip = cusip; + } + + const isin = profile?.isins?.[0]; if (isin) { response.isin = isin; } - const holdings = await got( - `${TrackinsightDataEnhancerService.baseUrl}/holdings/${symbol}.json`, + const holdings = await fetch( + `${TrackinsightDataEnhancerService.baseUrl}/holdings/${trackinsightSymbol}.json`, { - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) + signal: AbortSignal.timeout(requestTimeout) } ) - .json() + .then((res) => res.json()) .catch(() => { - return got( - `${TrackinsightDataEnhancerService.baseUrl}/holdings/${ - symbol.split('.')?.[0] - }.json`, - { - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - } - ) - .json() - .catch(() => { - return {}; - }); + return {}; }); if ( @@ -185,4 +174,36 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { public getTestSymbol() { return 'QQQ'; } + + private async searchTrackinsightSymbol({ + requestTimeout, + symbol + }: { + requestTimeout: number; + symbol: string; + }) { + return fetch( + `https://www.trackinsight.com/search-api/search_v2/${symbol}/_/ticker/default/0/3`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ) + .then((res) => res.json()) + .then((jsonRes) => { + if ( + jsonRes['results']?.['count'] === 1 || + // Allow exact match + jsonRes['results']?.['docs']?.[0]?.['ticker'] === symbol || + // Allow EXCHANGE:SYMBOL + jsonRes['results']?.['docs']?.[0]?.['ticker']?.endsWith(`:${symbol}`) + ) { + return jsonRes['results']['docs'][0]['ticker']; + } + + return undefined; + }) + .catch(() => { + return undefined; + }); + } } diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts index 8a8ab1f08..c37a9fe3e 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts @@ -47,11 +47,21 @@ describe('YahooFinanceDataEnhancerService', () => { 'BTC-USD' ) ).toEqual('BTCUSD'); + expect( + await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( + 'USD.AX' + ) + ).toEqual('USD.AX'); expect( await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( 'EURUSD=X' ) ).toEqual('EURUSD'); + expect( + await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( + 'USDCHF=X' + ) + ).toEqual('USDCHF'); }); it('convertToYahooFinanceSymbol', async () => { @@ -65,6 +75,16 @@ describe('YahooFinanceDataEnhancerService', () => { 'DOGEUSD' ) ).toEqual('DOGE-USD'); + expect( + await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + 'EURUSD' + ) + ).toEqual('EURUSD=X'); + expect( + await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + 'USD.AX' + ) + ).toEqual('USD.AX'); expect( await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( 'USDCHF' diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index b71e3e316..54167bc5b 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -1,4 +1,5 @@ import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service'; +import { AssetProfileDelistedError } from '@ghostfolio/api/services/data-provider/errors/asset-profile-delisted.error'; import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface'; import { DEFAULT_CURRENCY, @@ -17,11 +18,15 @@ import { } from '@prisma/client'; import { isISIN } from 'class-validator'; import { countries } from 'countries-list'; -import yahooFinance from 'yahoo-finance2'; -import type { Price } from 'yahoo-finance2/dist/esm/src/modules/quoteSummary-iface'; +import YahooFinance from 'yahoo-finance2'; +import type { Price } from 'yahoo-finance2/esm/src/modules/quoteSummary-iface'; @Injectable() export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { + private readonly yahooFinance = new YahooFinance({ + suppressNotices: ['yahooSurvey'] + }); + public constructor( private readonly cryptocurrencyService: CryptocurrencyService ) {} @@ -58,7 +63,8 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { if ( isCurrency( aSymbol.substring(0, aSymbol.length - DEFAULT_CURRENCY.length) - ) + ) && + isCurrency(aSymbol.substring(aSymbol.length - DEFAULT_CURRENCY.length)) ) { return `${aSymbol}=X`; } else if ( @@ -98,8 +104,8 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { if (response.dataSource === 'YAHOO') { yahooSymbol = symbol; } else { - const { quotes } = await yahooFinance.search(response.isin); - yahooSymbol = quotes[0].symbol; + const { quotes } = await this.yahooFinance.search(response.isin); + yahooSymbol = quotes[0].symbol as string; } const { countries, sectors, url } = @@ -164,17 +170,19 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { if (isISIN(symbol)) { try { - const { quotes } = await yahooFinance.search(symbol); + const { quotes } = await this.yahooFinance.search(symbol); if (quotes?.[0]?.symbol) { - symbol = quotes[0].symbol; + symbol = quotes[0].symbol as string; } } catch {} + } else if (symbol?.endsWith(`-${DEFAULT_CURRENCY}`)) { + throw new Error(`${symbol} is not valid`); } else { symbol = this.convertToYahooFinanceSymbol(symbol); } - const assetProfile = await yahooFinance.quoteSummary(symbol, { + const assetProfile = await this.yahooFinance.quoteSummary(symbol, { modules: ['price', 'summaryProfile', 'topHoldings'] }); @@ -197,17 +205,20 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { assetProfile.price.symbol ); - if (assetSubClass === AssetSubClass.MUTUALFUND) { + if (['ETF', 'MUTUALFUND'].includes(assetSubClass)) { response.sectors = []; for (const sectorWeighting of assetProfile.topHoldings ?.sectorWeightings ?? []) { for (const [sector, weight] of Object.entries(sectorWeighting)) { - response.sectors.push({ weight, name: this.parseSector(sector) }); + response.sectors.push({ + name: this.parseSector(sector), + weight: weight as number + }); } } } else if ( - assetSubClass === AssetSubClass.STOCK && + assetSubClass === 'STOCK' && assetProfile.summaryProfile?.country ) { // Add country if asset is stock and country available @@ -234,7 +245,13 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { response.url = url; } } catch (error) { - Logger.error(error, 'YahooFinanceService'); + if (error.message === `Quote not found for symbol: ${aSymbol}`) { + throw new AssetProfileDelistedError( + `No data found, ${aSymbol} (${this.getName()}) may be delisted` + ); + } else { + Logger.error(error, 'YahooFinanceService'); + } } return response; diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index 7c0df7a9f..674672326 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -18,6 +18,7 @@ import { DATE_FORMAT, getCurrencyFromSymbol, getStartOfUtcDate, + isCurrency, isDerivedCurrency } from '@ghostfolio/common/helper'; import { @@ -25,17 +26,18 @@ import { LookupItem, LookupResponse } from '@ghostfolio/common/interfaces'; +import { hasRole } from '@ghostfolio/common/permissions'; import type { Granularity, UserWithSettings } from '@ghostfolio/common/types'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { DataSource, MarketData, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { eachDayOfInterval, format, isValid } from 'date-fns'; +import { eachDayOfInterval, format, isBefore, isValid } from 'date-fns'; import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash'; import ms from 'ms'; @Injectable() -export class DataProviderService { +export class DataProviderService implements OnModuleInit { private dataProviderMapping: { [dataProviderName: string]: string }; public constructor( @@ -46,15 +48,13 @@ export class DataProviderService { private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly redisCacheService: RedisCacheService - ) { - this.initialize(); - } + ) {} - public async initialize() { + public async onModuleInit() { this.dataProviderMapping = - ((await this.propertyService.getByKey(PROPERTY_DATA_SOURCE_MAPPING)) as { + (await this.propertyService.getByKey<{ [dataProviderName: string]: string; - }) ?? {}; + }>(PROPERTY_DATA_SOURCE_MAPPING)) ?? {}; } public async checkQuote(dataSource: DataSource) { @@ -114,7 +114,13 @@ export class DataProviderService { } } - await Promise.all(promises); + try { + await Promise.all(promises); + } catch (error) { + Logger.error(error, 'DataProviderService'); + + throw error; + } return response; } @@ -154,18 +160,34 @@ export class DataProviderService { return DataSource[this.configurationService.get('DATA_SOURCE_IMPORT')]; } - public async getDataSources(): Promise { + public async getDataSources({ + includeGhostfolio = false, + user + }: { + includeGhostfolio?: boolean; + user: UserWithSettings; + }): Promise { + let dataSourcesKey: 'DATA_SOURCES' | 'DATA_SOURCES_LEGACY' = 'DATA_SOURCES'; + + if ( + !hasRole(user, 'ADMIN') && + isBefore(user.createdAt, new Date('2025-03-23')) && + this.configurationService.get('DATA_SOURCES_LEGACY')?.length > 0 + ) { + dataSourcesKey = 'DATA_SOURCES_LEGACY'; + } + const dataSources: DataSource[] = this.configurationService - .get('DATA_SOURCES') + .get(dataSourcesKey) .map((dataSource) => { return DataSource[dataSource]; }); - const ghostfolioApiKey = (await this.propertyService.getByKey( + const ghostfolioApiKey = await this.propertyService.getByKey( PROPERTY_API_KEY_GHOSTFOLIO - )) as string; + ); - if (ghostfolioApiKey) { + if (includeGhostfolio || ghostfolioApiKey) { dataSources.push('GHOSTFOLIO'); } @@ -449,17 +471,21 @@ export class DataProviderService { )) { const dataProvider = this.getDataProvider(DataSource[dataSource]); - if ( - dataProvider.getDataProviderInfo().isPremium && - this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - user?.subscription.type === 'Basic' - ) { - continue; - } - const symbols = assetProfileIdentifiers .filter(({ symbol }) => { - return !isDerivedCurrency(getCurrencyFromSymbol(symbol)); + if (isCurrency(getCurrencyFromSymbol(symbol))) { + // Keep non-derived currencies + return !isDerivedCurrency(getCurrencyFromSymbol(symbol)); + } else if ( + dataProvider.getDataProviderInfo().isPremium && + this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && + user?.subscription.type === 'Basic' + ) { + // Skip symbols of Premium data providers for users without subscription + return false; + } + + return true; }) .map(({ symbol }) => { return symbol; @@ -608,7 +634,7 @@ export class DataProviderService { return { items: lookupItems }; } - const dataSources = await this.getDataSources(); + const dataSources = await this.getDataSources({ user }); const dataProviderServices = dataSources.map((dataSource) => { return this.getDataProvider(DataSource[dataSource]); @@ -637,22 +663,34 @@ export class DataProviderService { // Only allow symbols with supported currency return currency ? true : false; }) - .sort(({ name: name1 }, { name: name2 }) => { - return name1?.toLowerCase().localeCompare(name2?.toLowerCase()); - }) .map((lookupItem) => { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { if (user.subscription.type === 'Premium') { lookupItem.dataProviderInfo.isPremium = false; } + lookupItem.dataProviderInfo.dataSource = undefined; lookupItem.dataProviderInfo.name = undefined; lookupItem.dataProviderInfo.url = undefined; } else { lookupItem.dataProviderInfo.isPremium = false; } + if ( + lookupItem.assetSubClass === 'CRYPTOCURRENCY' && + user?.settings?.settings.isExperimentalFeatures + ) { + // Remove DEFAULT_CURRENCY at the end of cryptocurrency names + lookupItem.name = lookupItem.name.replace( + new RegExp(` ${DEFAULT_CURRENCY}$`), + '' + ); + } + return lookupItem; + }) + .sort(({ name: name1 }, { name: name2 }) => { + return name1?.toLowerCase().localeCompare(name2?.toLowerCase()); }); return { diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index 3ba8eb04f..ddb94bb1a 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -31,7 +32,6 @@ import { SymbolProfile } from '@prisma/client'; import { addDays, format, isSameDay, isToday } from 'date-fns'; -import got from 'got'; import { isNumber } from 'lodash'; @Injectable() @@ -52,9 +52,7 @@ export class EodHistoricalDataService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { const [searchResult] = await this.getSearchResult(symbol); return { @@ -70,6 +68,7 @@ export class EodHistoricalDataService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.EOD_HISTORICAL_DATA, isPremium: true, name: 'EOD Historical Data', url: 'https://eodhd.com' @@ -95,7 +94,7 @@ export class EodHistoricalDataService implements DataProviderInterface { [date: string]: IDataProviderHistoricalResponse; } = {}; - const historicalResult = await got( + const historicalResult = await fetch( `${this.URL}/div/${symbol}?api_token=${ this.apiKey }&fmt=json&from=${format(from, DATE_FORMAT)}&to=${format( @@ -103,10 +102,9 @@ export class EodHistoricalDataService implements DataProviderInterface { DATE_FORMAT )}`, { - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); for (const { date, value } of historicalResult) { response[date] = { @@ -140,7 +138,7 @@ export class EodHistoricalDataService implements DataProviderInterface { symbol = this.convertToEodSymbol(symbol); try { - const response = await got( + const response = await fetch( `${this.URL}/eod/${symbol}?api_token=${ this.apiKey }&fmt=json&from=${format(from, DATE_FORMAT)}&to=${format( @@ -148,10 +146,9 @@ export class EodHistoricalDataService implements DataProviderInterface { DATE_FORMAT )}&period=${granularity}`, { - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); return response.reduce( (result, { adjusted_close, date }) => { @@ -205,15 +202,14 @@ export class EodHistoricalDataService implements DataProviderInterface { }); try { - const realTimeResponse = await got( + const realTimeResponse = await fetch( `${this.URL}/real-time/${eodHistoricalDataSymbols[0]}?api_token=${ this.apiKey }&fmt=json&s=${eodHistoricalDataSymbols.join(',')}`, { - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); const quotes: { close: number; @@ -286,7 +282,7 @@ export class EodHistoricalDataService implements DataProviderInterface { } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; @@ -400,15 +396,14 @@ export class EodHistoricalDataService implements DataProviderInterface { })[] = []; try { - const response = await got( + const response = await fetch( `${this.URL}/search/${aQuery}?api_token=${this.apiKey}`, { - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).json(); + ).then((res) => res.json()); searchResult = response.map( ({ Code, Currency, Exchange, ISIN: isin, Name: name, Type }) => { @@ -431,7 +426,7 @@ export class EodHistoricalDataService implements DataProviderInterface { } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to search for ${aQuery} was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; diff --git a/apps/api/src/services/data-provider/errors/asset-profile-delisted.error.ts b/apps/api/src/services/data-provider/errors/asset-profile-delisted.error.ts new file mode 100644 index 000000000..dabe0aa5b --- /dev/null +++ b/apps/api/src/services/data-provider/errors/asset-profile-delisted.error.ts @@ -0,0 +1,7 @@ +export class AssetProfileDelistedError extends Error { + public constructor(message: string) { + super(message); + + this.name = 'AssetProfileDelistedError'; + } +} diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index 933af4802..2dcb689a7 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -1,6 +1,8 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -10,26 +12,44 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; -import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; -import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; +import { + DEFAULT_CURRENCY, + REPLACE_NAME_PARTS +} from '@ghostfolio/common/config'; +import { DATE_FORMAT, isCurrency, parseDate } from '@ghostfolio/common/helper'; import { DataProviderInfo, LookupItem, LookupResponse } from '@ghostfolio/common/interfaces'; +import { MarketState } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; -import { DataSource, SymbolProfile } from '@prisma/client'; -import { format, isAfter, isBefore, isSameDay } from 'date-fns'; -import got from 'got'; +import { + AssetClass, + AssetSubClass, + DataSource, + SymbolProfile +} from '@prisma/client'; +import { isISIN } from 'class-validator'; +import { countries } from 'countries-list'; +import { + addDays, + addYears, + format, + isAfter, + isBefore, + isSameDay, + parseISO +} from 'date-fns'; @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { private apiKey: string; - private readonly URL = 'https://financialmodelingprep.com/api/v3'; public constructor( - private readonly configurationService: ConfigurationService + private readonly configurationService: ConfigurationService, + private readonly cryptocurrencyService: CryptocurrencyService ) { this.apiKey = this.configurationService.get( 'API_KEY_FINANCIAL_MODELING_PREP' @@ -41,26 +61,216 @@ export class FinancialModelingPrepService implements DataProviderInterface { } public async getAssetProfile({ + requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'), symbol - }: { - symbol: string; - }): Promise> { - return { + }: GetAssetProfileParams): Promise> { + const response: Partial = { symbol, dataSource: this.getName() }; + + try { + if ( + isCurrency(symbol.substring(0, symbol.length - DEFAULT_CURRENCY.length)) + ) { + response.assetClass = AssetClass.LIQUIDITY; + response.assetSubClass = AssetSubClass.CASH; + response.currency = symbol.substring( + symbol.length - DEFAULT_CURRENCY.length + ); + } else if (this.cryptocurrencyService.isCryptocurrency(symbol)) { + const [quote] = await fetch( + `${this.getUrl({ version: 'stable' })}/quote?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + response.assetClass = AssetClass.LIQUIDITY; + response.assetSubClass = AssetSubClass.CRYPTOCURRENCY; + response.currency = symbol.substring( + symbol.length - DEFAULT_CURRENCY.length + ); + response.name = quote.name; + } else { + const [assetProfile] = await fetch( + `${this.getUrl({ version: 'stable' })}/profile?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + const { assetClass, assetSubClass } = + this.parseAssetClass(assetProfile); + + response.assetClass = assetClass; + response.assetSubClass = assetSubClass; + + if (assetSubClass === AssetSubClass.ETF) { + const etfCountryWeightings = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/country-weightings?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + response.countries = etfCountryWeightings.map( + ({ country: countryName, weightPercentage }) => { + let countryCode: string; + + for (const [code, country] of Object.entries(countries)) { + if (country.name === countryName) { + countryCode = code; + break; + } + } + + return { + code: countryCode, + weight: parseFloat(weightPercentage.slice(0, -1)) / 100 + }; + } + ); + + const etfHoldings = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/holdings?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + const sortedTopHoldings = etfHoldings + .sort((a, b) => { + return b.weightPercentage - a.weightPercentage; + }) + .slice(0, 10); + + response.holdings = sortedTopHoldings.map( + ({ name, weightPercentage }) => { + return { name, weight: weightPercentage / 100 }; + } + ); + + const [etfInformation] = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/info?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + if (etfInformation.website) { + response.url = etfInformation.website; + } + + const etfSectorWeightings = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/sector-weightings?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + response.sectors = etfSectorWeightings.map( + ({ sector, weightPercentage }) => { + return { + name: sector, + weight: weightPercentage / 100 + }; + } + ); + } else if (assetSubClass === AssetSubClass.STOCK) { + if (assetProfile.country) { + response.countries = [{ code: assetProfile.country, weight: 1 }]; + } + + if (assetProfile.sector) { + response.sectors = [{ name: assetProfile.sector, weight: 1 }]; + } + } + + response.currency = assetProfile.currency; + + if (assetProfile.isin) { + response.isin = assetProfile.isin; + } + + response.name = this.formatName({ name: assetProfile.companyName }); + + if (assetProfile.website) { + response.url = assetProfile.website; + } + } + } catch (error) { + let message = error; + + if (error?.name === 'AbortError') { + message = `RequestError: The operation to get the asset profile for ${symbol} was aborted because the request to the data provider took more than ${( + requestTimeout / 1000 + ).toFixed(3)} seconds`; + } + + Logger.error(message, 'FinancialModelingPrepService'); + } + + return response; } public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.FINANCIAL_MODELING_PREP, isPremium: true, name: 'Financial Modeling Prep', url: 'https://financialmodelingprep.com/developer/docs' }; } - public async getDividends({}: GetDividendsParams) { - return {}; + public async getDividends({ + from, + requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'), + symbol, + to + }: GetDividendsParams) { + if (isSameDay(from, to)) { + to = addDays(to, 1); + } + + try { + const response: { + [date: string]: IDataProviderHistoricalResponse; + } = {}; + + const dividends = await fetch( + `${this.getUrl({ version: 'stable' })}/dividends?symbol=${symbol}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); + + dividends + .filter(({ date }) => { + return ( + (isSameDay(parseISO(date), from) || + isAfter(parseISO(date), from)) && + isBefore(parseISO(date), to) + ); + }) + .forEach(({ adjDividend, date }) => { + response[date] = { + marketPrice: adjDividend + }; + }); + + return response; + } catch (error) { + Logger.error( + `Could not get dividends for ${symbol} (${this.getName()}) from ${format( + from, + DATE_FORMAT + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`, + 'FinancialModelingPrepService' + ); + + return {}; + } } public async getHistorical({ @@ -71,31 +281,44 @@ export class FinancialModelingPrepService implements DataProviderInterface { }: GetHistoricalParams): Promise<{ [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { + const MAX_YEARS_PER_REQUEST = 5; + const result: { + [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; + } = { + [symbol]: {} + }; + + let currentFrom = from; + try { - const { historical } = await got( - `${this.URL}/historical-price-full/${symbol}?apikey=${this.apiKey}`, - { - // @ts-ignore - signal: AbortSignal.timeout(requestTimeout) - } - ).json(); + while (isBefore(currentFrom, to) || isSameDay(currentFrom, to)) { + const currentTo = isBefore( + addYears(currentFrom, MAX_YEARS_PER_REQUEST), + to + ) + ? addYears(currentFrom, MAX_YEARS_PER_REQUEST) + : to; - const result: { - [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; - } = { - [symbol]: {} - }; + const historical = await fetch( + `${this.getUrl({ version: 'stable' })}/historical-price-eod/full?symbol=${symbol}&apikey=${this.apiKey}&from=${format(currentFrom, DATE_FORMAT)}&to=${format(currentTo, DATE_FORMAT)}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()); - for (const { close, date } of historical) { - if ( - (isSameDay(parseDate(date), from) || - isAfter(parseDate(date), from)) && - isBefore(parseDate(date), to) - ) { - result[symbol][date] = { - marketPrice: close - }; + for (const { close, date } of historical) { + if ( + (isSameDay(parseDate(date), currentFrom) || + isAfter(parseDate(date), currentFrom)) && + isBefore(parseDate(date), currentTo) + ) { + result[symbol][date] = { + marketPrice: close + }; + } } + + currentFrom = addYears(currentFrom, MAX_YEARS_PER_REQUEST); } return result; @@ -109,6 +332,10 @@ export class FinancialModelingPrepService implements DataProviderInterface { } } + public getMaxNumberOfSymbolsPerRequest() { + return 20; + } + public getName(): DataSource { return DataSource.FINANCIAL_MODELING_PREP; } @@ -124,29 +351,50 @@ export class FinancialModelingPrepService implements DataProviderInterface { } try { - const quotes = await got( - `${this.URL}/quote/${symbols.join(',')}?apikey=${this.apiKey}`, + const currencyBySymbolMap: { + [symbol: string]: Pick; + } = {}; + + const quotes = await fetch( + `${this.getUrl({ version: 'stable' })}/batch-quote-short?symbols=${symbols.join(',')}&apikey=${this.apiKey}`, { - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json()); + + await Promise.all( + quotes.map(({ symbol }) => { + return this.getAssetProfile({ symbol }).then(({ currency }) => { + currencyBySymbolMap[symbol] = { currency }; + }); + }) + ); for (const { price, symbol } of quotes) { + let marketState: MarketState = 'delayed'; + + if ( + isCurrency( + symbol.substring(0, symbol.length - DEFAULT_CURRENCY.length) + ) + ) { + marketState = 'open'; + } + response[symbol] = { - currency: DEFAULT_CURRENCY, + marketState, + currency: currencyBySymbolMap[symbol]?.currency, dataProviderInfo: this.getDataProviderInfo(), dataSource: DataSource.FINANCIAL_MODELING_PREP, - marketPrice: price, - marketState: 'delayed' + marketPrice: price }; } } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${( - this.configurationService.get('REQUEST_TIMEOUT') / 1000 + requestTimeout / 1000 ).toFixed(3)} seconds`; } @@ -161,33 +409,67 @@ export class FinancialModelingPrepService implements DataProviderInterface { } public async search({ query }: GetSearchParams): Promise { + const assetProfileBySymbolMap: { + [symbol: string]: Partial; + } = {}; let items: LookupItem[] = []; try { - const result = await got( - `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, - { - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - } - ).json(); - - items = result.map(({ currency, name, symbol }) => { - return { - // TODO: Add assetClass - // TODO: Add assetSubClass - currency, - name, - symbol, - dataSource: this.getName() - }; - }); + if (isISIN(query?.toUpperCase())) { + const result = await fetch( + `${this.getUrl({ version: 'stable' })}/search-isin?isin=${query.toUpperCase()}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + await Promise.all( + result.map(({ symbol }) => { + return this.getAssetProfile({ symbol }).then((assetProfile) => { + assetProfileBySymbolMap[symbol] = assetProfile; + }); + }) + ); + + items = result.map(({ assetClass, assetSubClass, name, symbol }) => { + return { + assetClass, + assetSubClass, + symbol, + currency: assetProfileBySymbolMap[symbol]?.currency, + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName(), + name: this.formatName({ name }) + }; + }); + } else { + const result = await fetch( + `${this.getUrl({ version: 'stable' })}/search-symbol?query=${query}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + items = result.map(({ currency, name, symbol }) => { + return { + currency, + symbol, + assetClass: undefined, // TODO + assetSubClass: undefined, // TODO + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName(), + name: this.formatName({ name }) + }; + }); + } } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; @@ -198,4 +480,49 @@ export class FinancialModelingPrepService implements DataProviderInterface { return { items }; } + + private formatName({ name }: { name: string }) { + if (name) { + for (const part of REPLACE_NAME_PARTS) { + name = name.replace(part, ''); + } + + name = name.trim(); + } + + return name; + } + + private getUrl({ version }: { version: number | 'stable' }) { + const baseUrl = 'https://financialmodelingprep.com'; + + if (version === 'stable') { + return `${baseUrl}/stable`; + } + + return `${baseUrl}/api/v${version}`; + } + + private parseAssetClass(profile: any): { + assetClass: AssetClass; + assetSubClass: AssetSubClass; + } { + let assetClass: AssetClass; + let assetSubClass: AssetSubClass; + + if (profile) { + if (profile.isEtf) { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.ETF; + } else if (profile.isFund) { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.MUTUALFUND; + } else { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.STOCK; + } + } + + return { assetClass, assetSubClass }; + } } diff --git a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts index b6e86949b..3fd9e1bea 100644 --- a/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts @@ -2,6 +2,7 @@ import { environment } from '@ghostfolio/api/environments/environment'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -18,6 +19,7 @@ import { } from '@ghostfolio/common/config'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { + DataProviderGhostfolioAssetProfileResponse, DataProviderInfo, DividendsResponse, HistoricalResponse, @@ -28,7 +30,6 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import { format } from 'date-fns'; -import got from 'got'; import { StatusCodes } from 'http-status-codes'; @Injectable() @@ -47,28 +48,54 @@ export class GhostfolioService implements DataProviderInterface { } public async getAssetProfile({ + requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'), symbol - }: { - symbol: string; - }): Promise> { - const { items } = await this.search({ query: symbol }); - const searchResult = items?.[0]; + }: GetAssetProfileParams): Promise> { + let response: DataProviderGhostfolioAssetProfileResponse = {}; - return { - symbol, - assetClass: searchResult?.assetClass, - assetSubClass: searchResult?.assetSubClass, - currency: searchResult?.currency, - dataSource: this.getName(), - name: searchResult?.name - }; + try { + const assetProfile = (await fetch( + `${this.URL}/v1/data-providers/ghostfolio/asset-profile/${symbol}`, + { + headers: await this.getRequestHeaders(), + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => + res.json() + )) as DataProviderGhostfolioAssetProfileResponse; + + response = assetProfile; + } catch (error) { + let message = error; + + if (error.name === 'AbortError') { + message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${( + requestTimeout / 1000 + ).toFixed(3)} seconds`; + } else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) { + message = 'RequestError: The daily request limit has been exceeded'; + } else if (error.response?.statusCode === StatusCodes.UNAUTHORIZED) { + if (!error.request?.options?.headers?.authorization?.includes('-')) { + message = + 'RequestError: The provided API key is invalid. Please update it in the Settings section of the Admin Control panel.'; + } else { + message = + 'RequestError: The provided API key has expired. Please request a new one and update it in the Settings section of the Admin Control panel.'; + } + } + + Logger.error(message, 'GhostfolioService'); + } + + return response; } public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.GHOSTFOLIO, isPremium: true, name: 'Ghostfolio', - url: 'https://ghostfo.io' + url: 'https://ghostfol.io' }; } @@ -86,17 +113,16 @@ export class GhostfolioService implements DataProviderInterface { } = {}; try { - const { dividends } = await got( + const { dividends } = (await fetch( `${this.URL}/v2/data-providers/ghostfolio/dividends/${symbol}?from=${format(from, DATE_FORMAT)}&granularity=${granularity}&to=${format( to, DATE_FORMAT )}`, { headers: await this.getRequestHeaders(), - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json())) as DividendsResponse; response = dividends; } catch (error) { @@ -130,17 +156,16 @@ export class GhostfolioService implements DataProviderInterface { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { try { - const { historicalData } = await got( + const { historicalData } = (await fetch( `${this.URL}/v2/data-providers/ghostfolio/historical/${symbol}?from=${format(from, DATE_FORMAT)}&granularity=${granularity}&to=${format( to, DATE_FORMAT )}`, { headers: await this.getRequestHeaders(), - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json())) as HistoricalResponse; return { [symbol]: historicalData @@ -192,22 +217,21 @@ export class GhostfolioService implements DataProviderInterface { } try { - const { quotes } = await got( + const { quotes } = (await fetch( `${this.URL}/v2/data-providers/ghostfolio/quotes?symbols=${symbols.join(',')}`, { headers: await this.getRequestHeaders(), - // @ts-ignore signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json())) as QuotesResponse; response = quotes; } catch (error) { let message = error; - if (error.code === 'ABORT_ERR') { + if (error.name === 'AbortError') { message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${( - this.configurationService.get('REQUEST_TIMEOUT') / 1000 + requestTimeout / 1000 ).toFixed(3)} seconds`; } else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) { message = 'RequestError: The daily request limit has been exceeded'; @@ -228,29 +252,29 @@ export class GhostfolioService implements DataProviderInterface { } public getTestSymbol() { - return 'AAPL.US'; + return 'AAPL'; } - public async search({ query }: GetSearchParams): Promise { + public async search({ + requestTimeout = this.configurationService.get('REQUEST_TIMEOUT'), + query + }: GetSearchParams): Promise { let searchResult: LookupResponse = { items: [] }; try { - searchResult = await got( + searchResult = (await fetch( `${this.URL}/v2/data-providers/ghostfolio/lookup?query=${query}`, { headers: await this.getRequestHeaders(), - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) + signal: AbortSignal.timeout(requestTimeout) } - ).json(); + ).then((res) => res.json())) as LookupResponse; } catch (error) { let message = error; - if (error.code === 'ABORT_ERR') { + if (error.name === 'AbortError') { message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${( - this.configurationService.get('REQUEST_TIMEOUT') / 1000 + requestTimeout / 1000 ).toFixed(3)} seconds`; } else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) { message = 'RequestError: The daily request limit has been exceeded'; @@ -271,9 +295,9 @@ export class GhostfolioService implements DataProviderInterface { } private async getRequestHeaders() { - const apiKey = (await this.propertyService.getByKey( + const apiKey = await this.propertyService.getByKey( PROPERTY_API_KEY_GHOSTFOLIO - )) as string; + ); return { [HEADER_KEY_TOKEN]: `Api-Key ${apiKey}` diff --git a/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts b/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts index f18d670d1..f067f042c 100644 --- a/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts +++ b/apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -37,9 +38,7 @@ export class GoogleSheetsService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { return { symbol, dataSource: this.getName() @@ -48,6 +47,7 @@ export class GoogleSheetsService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.GOOGLE_SHEETS, isPremium: false, name: 'Google Sheets', url: 'https://docs.google.com/spreadsheets' diff --git a/apps/api/src/services/data-provider/interfaces/data-provider.interface.ts b/apps/api/src/services/data-provider/interfaces/data-provider.interface.ts index 5c316aac2..475205a01 100644 --- a/apps/api/src/services/data-provider/interfaces/data-provider.interface.ts +++ b/apps/api/src/services/data-provider/interfaces/data-provider.interface.ts @@ -15,9 +15,7 @@ export interface DataProviderInterface { getAssetProfile({ symbol - }: { - symbol: string; - }): Promise>; + }: GetAssetProfileParams): Promise>; getDataProviderInfo(): DataProviderInfo; @@ -55,6 +53,11 @@ export interface DataProviderInterface { search({ includeIndices, query }: GetSearchParams): Promise; } +export interface GetAssetProfileParams { + requestTimeout?: number; + symbol: string; +} + export interface GetDividendsParams { from: Date; granularity?: Granularity; @@ -79,5 +82,6 @@ export interface GetQuotesParams { export interface GetSearchParams { includeIndices?: boolean; query: string; + requestTimeout?: number; userId?: string; } diff --git a/apps/api/src/services/data-provider/manual/manual.service.ts b/apps/api/src/services/data-provider/manual/manual.service.ts index 3e98a9d77..1c1c4c2da 100644 --- a/apps/api/src/services/data-provider/manual/manual.service.ts +++ b/apps/api/src/services/data-provider/manual/manual.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -27,7 +28,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import * as cheerio from 'cheerio'; import { addDays, format, isBefore } from 'date-fns'; -import got, { Headers } from 'got'; import * as jsonpath from 'jsonpath'; @Injectable() @@ -44,9 +44,7 @@ export class ManualService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { const assetProfile: Partial = { symbol, dataSource: this.getName() @@ -66,6 +64,7 @@ export class ManualService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.MANUAL, isPremium: false }; } @@ -105,7 +104,7 @@ export class ManualService implements DataProviderInterface { } return historical; - } else if (selector === undefined || url === undefined) { + } else if (!selector || !url) { return {}; } @@ -163,7 +162,11 @@ export class ManualService implements DataProviderInterface { const symbolProfilesWithScraperConfigurationAndInstantMode = symbolProfiles.filter(({ scraperConfiguration }) => { - return scraperConfiguration?.mode === 'instant'; + return ( + scraperConfiguration?.mode === 'instant' && + scraperConfiguration?.selector && + scraperConfiguration?.url + ); }); const scraperResultPromises = @@ -274,39 +277,48 @@ export class ManualService implements DataProviderInterface { private async scrape( scraperConfiguration: ScraperConfiguration ): Promise { - try { - let locale = scraperConfiguration.locale; - const { body, headers } = await got(scraperConfiguration.url, { - headers: scraperConfiguration.headers as Headers, - // @ts-ignore - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - }); + let locale = scraperConfiguration.locale; - if (headers['content-type'].includes('application/json')) { - const data = JSON.parse(body); - const value = String( - jsonpath.query(data, scraperConfiguration.selector)[0] - ); + const response = await fetch(scraperConfiguration.url, { + headers: scraperConfiguration.headers as HeadersInit, + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + }); - return extractNumberFromString({ locale, value }); - } else { - const $ = cheerio.load(body); + let value: string; - if (!locale) { - try { - locale = $('html').attr('lang'); - } catch {} - } + if (response.headers.get('content-type')?.includes('application/json')) { + const data = await response.json(); - return extractNumberFromString({ - locale, - value: $(scraperConfiguration.selector).first().text() - }); + value = String(jsonpath.query(data, scraperConfiguration.selector)[0]); + } else { + const $ = cheerio.load(await response.text()); + + if (!locale) { + try { + locale = $('html').attr('lang'); + } catch {} } - } catch (error) { - throw error; + + value = $(scraperConfiguration.selector).first().text(); + + const lines = value?.split('\n') ?? []; + + const lineWithDigits = lines.find((line) => { + return /\d/.test(line); + }); + + if (lineWithDigits) { + value = lineWithDigits; + } + + return extractNumberFromString({ + locale, + value + }); } + + return extractNumberFromString({ locale, value }); } } diff --git a/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts b/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts index 08cc2ef05..5675f1eb0 100644 --- a/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts +++ b/apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts @@ -1,6 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -10,7 +11,10 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; -import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; +import { + ghostfolioFearAndGreedIndexSymbol, + ghostfolioFearAndGreedIndexSymbolStocks +} from '@ghostfolio/common/config'; import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper'; import { DataProviderInfo, @@ -20,7 +24,6 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import { format } from 'date-fns'; -import got from 'got'; @Injectable() export class RapidApiService implements DataProviderInterface { @@ -34,9 +37,7 @@ export class RapidApiService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { return { symbol, dataSource: this.getName() @@ -45,6 +46,7 @@ export class RapidApiService implements DataProviderInterface { public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.RAPID_API, isPremium: false, name: 'Rapid API', url: 'https://rapidapi.com' @@ -63,11 +65,16 @@ export class RapidApiService implements DataProviderInterface { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { try { - if (symbol === ghostfolioFearAndGreedIndexSymbol) { + if ( + [ + ghostfolioFearAndGreedIndexSymbol, + ghostfolioFearAndGreedIndexSymbolStocks + ].includes(symbol) + ) { const fgi = await this.getFearAndGreedIndex(); return { - [ghostfolioFearAndGreedIndexSymbol]: { + [symbol]: { [format(getYesterday(), DATE_FORMAT)]: { marketPrice: fgi.previousClose.value } @@ -100,11 +107,16 @@ export class RapidApiService implements DataProviderInterface { try { const symbol = symbols[0]; - if (symbol === ghostfolioFearAndGreedIndexSymbol) { + if ( + [ + ghostfolioFearAndGreedIndexSymbol, + ghostfolioFearAndGreedIndexSymbolStocks + ].includes(symbol) + ) { const fgi = await this.getFearAndGreedIndex(); return { - [ghostfolioFearAndGreedIndexSymbol]: { + [symbol]: { currency: undefined, dataSource: this.getName(), marketPrice: fgi.now.value, @@ -135,7 +147,7 @@ export class RapidApiService implements DataProviderInterface { oneYearAgo: { value: number; valueText: string }; }> { try { - const { fgi } = await got( + const { fgi } = await fetch( `https://fear-and-greed-index.p.rapidapi.com/v1/fgi`, { headers: { @@ -143,18 +155,17 @@ export class RapidApiService implements DataProviderInterface { 'x-rapidapi-host': 'fear-and-greed-index.p.rapidapi.com', 'x-rapidapi-key': this.configurationService.get('API_KEY_RAPID_API') }, - // @ts-ignore signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') ) } - ).json(); + ).then((res) => res.json()); return fgi; } catch (error) { let message = error; - if (error?.code === 'ABORT_ERR') { + if (error?.name === 'AbortError') { message = `RequestError: The operation was aborted because the request to the data provider took more than ${( this.configurationService.get('REQUEST_TIMEOUT') / 1000 ).toFixed(3)} seconds`; diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts index 27da18ab0..eb6f85d73 100644 --- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts @@ -1,7 +1,9 @@ import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/cryptocurrency.service'; import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service'; +import { AssetProfileDelistedError } from '@ghostfolio/api/services/data-provider/errors/asset-profile-delisted.error'; import { DataProviderInterface, + GetAssetProfileParams, GetDividendsParams, GetHistoricalParams, GetQuotesParams, @@ -22,16 +24,24 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import { addDays, format, isSameDay } from 'date-fns'; -import yahooFinance from 'yahoo-finance2'; -import { ChartResultArray } from 'yahoo-finance2/dist/esm/src/modules/chart'; +import YahooFinance from 'yahoo-finance2'; +import { ChartResultArray } from 'yahoo-finance2/esm/src/modules/chart'; import { HistoricalDividendsResult, HistoricalHistoryResult -} from 'yahoo-finance2/dist/esm/src/modules/historical'; -import { Quote } from 'yahoo-finance2/dist/esm/src/modules/quote'; +} from 'yahoo-finance2/esm/src/modules/historical'; +import { + Quote, + QuoteResponseArray +} from 'yahoo-finance2/esm/src/modules/quote'; +import { SearchQuoteNonYahoo } from 'yahoo-finance2/esm/src/modules/search'; @Injectable() export class YahooFinanceService implements DataProviderInterface { + private readonly yahooFinance = new YahooFinance({ + suppressNotices: ['yahooSurvey'] + }); + public constructor( private readonly cryptocurrencyService: CryptocurrencyService, private readonly yahooFinanceDataEnhancerService: YahooFinanceDataEnhancerService @@ -43,14 +53,13 @@ export class YahooFinanceService implements DataProviderInterface { public async getAssetProfile({ symbol - }: { - symbol: string; - }): Promise> { + }: GetAssetProfileParams): Promise> { return this.yahooFinanceDataEnhancerService.getAssetProfile(symbol); } public getDataProviderInfo(): DataProviderInfo { return { + dataSource: DataSource.YAHOO, isPremium: false, name: 'Yahoo Finance', url: 'https://finance.yahoo.com' @@ -69,7 +78,7 @@ export class YahooFinanceService implements DataProviderInterface { try { const historicalResult = this.convertToDividendResult( - await yahooFinance.chart( + await this.yahooFinance.chart( this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( symbol ), @@ -118,7 +127,7 @@ export class YahooFinanceService implements DataProviderInterface { try { const historicalResult = this.convertToHistoricalResult( - await yahooFinance.chart( + await this.yahooFinance.chart( this.yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( symbol ), @@ -144,12 +153,18 @@ export class YahooFinanceService implements DataProviderInterface { return response; } catch (error) { - throw new Error( - `Could not get historical market data for ${symbol} (${this.getName()}) from ${format( - from, - DATE_FORMAT - )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` - ); + if (error.message === 'No data found, symbol may be delisted') { + throw new AssetProfileDelistedError( + `No data found, ${symbol} (${this.getName()}) may be delisted` + ); + } else { + throw new Error( + `Could not get historical market data for ${symbol} (${this.getName()}) from ${format( + from, + DATE_FORMAT + )} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}` + ); + } } } @@ -181,7 +196,7 @@ export class YahooFinanceService implements DataProviderInterface { >[] = []; try { - quotes = await yahooFinance.quote(yahooFinanceSymbols); + quotes = await this.yahooFinance.quote(yahooFinanceSymbols); } catch (error) { Logger.error(error, 'YahooFinanceService'); @@ -237,13 +252,15 @@ export class YahooFinanceService implements DataProviderInterface { quoteTypes.push('INDEX'); } - const searchResult = await yahooFinance.search(query); + const searchResult = await this.yahooFinance.search(query); const quotes = searchResult.quotes - .filter((quote) => { - // Filter out undefined symbols - return quote.symbol; - }) + .filter( + (quote): quote is Exclude => { + // Filter out undefined symbols + return !!quote.symbol; + } + ) .filter(({ quoteType, symbol }) => { return ( (quoteType === 'CRYPTOCURRENCY' && @@ -269,11 +286,19 @@ export class YahooFinanceService implements DataProviderInterface { return true; }); - const marketData = await yahooFinance.quote( - quotes.map(({ symbol }) => { - return symbol; - }) - ); + let marketData: QuoteResponseArray = []; + + try { + marketData = await this.yahooFinance.quote( + quotes.map(({ symbol }) => { + return symbol; + }) + ); + } catch (error) { + if (error?.result?.length > 0) { + marketData = error.result; + } + } for (const marketDataItem of marketData) { const quote = quotes.find((currentQuote) => { @@ -329,7 +354,7 @@ export class YahooFinanceService implements DataProviderInterface { private async getQuotesWithQuoteSummary(aYahooFinanceSymbols: string[]) { const quoteSummaryPromises = aYahooFinanceSymbols.map((symbol) => { - return yahooFinance.quoteSummary(symbol).catch(() => { + return this.yahooFinance.quoteSummary(symbol).catch(() => { Logger.error( `Could not get quote summary for ${symbol}`, 'YahooFinanceService' diff --git a/apps/api/src/services/demo/demo.module.ts b/apps/api/src/services/demo/demo.module.ts new file mode 100644 index 000000000..8f86de058 --- /dev/null +++ b/apps/api/src/services/demo/demo.module.ts @@ -0,0 +1,13 @@ +import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; + +import { Module } from '@nestjs/common'; + +import { DemoService } from './demo.service'; + +@Module({ + exports: [DemoService], + imports: [PrismaModule, PropertyModule], + providers: [DemoService] +}) +export class DemoModule {} diff --git a/apps/api/src/services/demo/demo.service.ts b/apps/api/src/services/demo/demo.service.ts new file mode 100644 index 000000000..8f3658736 --- /dev/null +++ b/apps/api/src/services/demo/demo.service.ts @@ -0,0 +1,59 @@ +import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { + PROPERTY_DEMO_ACCOUNT_ID, + PROPERTY_DEMO_USER_ID, + TAG_ID_DEMO +} from '@ghostfolio/common/config'; + +import { Injectable } from '@nestjs/common'; +import { v4 as uuidv4 } from 'uuid'; + +@Injectable() +export class DemoService { + public constructor( + private readonly prismaService: PrismaService, + private readonly propertyService: PropertyService + ) {} + + public async syncDemoUserAccount() { + const [demoAccountId, demoUserId] = await Promise.all([ + this.propertyService.getByKey(PROPERTY_DEMO_ACCOUNT_ID), + this.propertyService.getByKey(PROPERTY_DEMO_USER_ID) + ]); + + let activities = await this.prismaService.order.findMany({ + orderBy: { + date: 'asc' + }, + where: { + tags: { + some: { + id: TAG_ID_DEMO + } + } + } + }); + + activities = activities.map((activity) => { + return { + ...activity, + accountId: demoAccountId, + accountUserId: demoUserId, + comment: null, + id: uuidv4(), + userId: demoUserId + }; + }); + + await this.prismaService.order.deleteMany({ + where: { + userId: demoUserId + } + }); + + return this.prismaService.order.createMany({ + data: activities + }); + } +} diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts index db95a3487..433547c94 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts @@ -23,7 +23,7 @@ import { isToday, subDays } from 'date-fns'; -import { isNumber, uniq } from 'lodash'; +import { isNumber } from 'lodash'; import ms from 'ms'; @Injectable() @@ -497,9 +497,8 @@ export class ExchangeRateDataService { currencies.push(currency); }); - const customCurrencies = (await this.propertyService.getByKey( - PROPERTY_CURRENCIES - )) as string[]; + const customCurrencies = + await this.propertyService.getByKey(PROPERTY_CURRENCIES); if (customCurrencies?.length > 0) { currencies = currencies.concat(customCurrencies); @@ -515,7 +514,7 @@ export class ExchangeRateDataService { } } - return uniq(currencies).filter(Boolean).sort(); + return Array.from(new Set(currencies)).filter(Boolean).sort(); } private prepareCurrencyPairs(aCurrencies: string[]) { diff --git a/apps/api/src/services/i18n/i18n.module.ts b/apps/api/src/services/i18n/i18n.module.ts new file mode 100644 index 000000000..68211de40 --- /dev/null +++ b/apps/api/src/services/i18n/i18n.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { I18nService } from './i18n.service'; + +@Module({ + exports: [I18nService], + providers: [I18nService] +}) +export class I18nModule {} diff --git a/apps/api/src/services/i18n/i18n.service.ts b/apps/api/src/services/i18n/i18n.service.ts index 13193fc6a..a0389ab36 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -1,10 +1,11 @@ import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; -import { Logger } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as cheerio from 'cheerio'; import { readFileSync, readdirSync } from 'fs'; import { join } from 'path'; +@Injectable() export class I18nService { private localesPath = join(__dirname, 'assets', 'locales'); private translations: { [locale: string]: cheerio.CheerioAPI } = {}; @@ -15,10 +16,12 @@ export class I18nService { public getTranslation({ id, - languageCode + languageCode, + placeholders }: { id: string; languageCode: string; + placeholders?: Record; }): string { const $ = this.translations[languageCode]; @@ -26,7 +29,7 @@ export class I18nService { Logger.warn(`Translation not found for locale '${languageCode}'`); } - const translatedText = $( + let translatedText = $( `trans-unit[id="${id}"] > ${ languageCode === DEFAULT_LANGUAGE_CODE ? 'source' : 'target' }` @@ -38,6 +41,12 @@ export class I18nService { ); } + if (placeholders) { + for (const [key, value] of Object.entries(placeholders)) { + translatedText = translatedText.replace(`\${${key}}`, String(value)); + } + } + return translatedText.trim(); } diff --git a/apps/api/src/services/impersonation/impersonation.service.ts b/apps/api/src/services/impersonation/impersonation.service.ts index 223aa60c8..71c543a43 100644 --- a/apps/api/src/services/impersonation/impersonation.service.ts +++ b/apps/api/src/services/impersonation/impersonation.service.ts @@ -16,7 +16,7 @@ export class ImpersonationService { if (this.request.user) { const accessObject = await this.prismaService.access.findFirst({ where: { - GranteeUser: { id: this.request.user.id }, + granteeUserId: this.request.user.id, id: aId } }); @@ -35,8 +35,8 @@ export class ImpersonationService { // Public access const accessObject = await this.prismaService.access.findFirst({ where: { - GranteeUser: null, - User: { id: aId } + granteeUserId: null, + user: { id: aId } } }); diff --git a/apps/api/src/services/interfaces/environment.interface.ts b/apps/api/src/services/interfaces/environment.interface.ts index 2f94739fb..c0e228429 100644 --- a/apps/api/src/services/interfaces/environment.interface.ts +++ b/apps/api/src/services/interfaces/environment.interface.ts @@ -16,6 +16,7 @@ export interface Environment extends CleanedEnvAccessors { DATA_SOURCE_IMPORT: string; DATA_SOURCES: string[]; DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER: string[]; + DATA_SOURCES_LEGACY: string[]; ENABLE_FEATURE_FEAR_AND_GREED_INDEX: boolean; ENABLE_FEATURE_READ_ONLY_MODE: boolean; ENABLE_FEATURE_SOCIAL_LOGIN: boolean; diff --git a/apps/api/src/services/interfaces/interfaces.ts b/apps/api/src/services/interfaces/interfaces.ts index fa7fc4d09..0eaa149a3 100644 --- a/apps/api/src/services/interfaces/interfaces.ts +++ b/apps/api/src/services/interfaces/interfaces.ts @@ -4,26 +4,7 @@ import { } from '@ghostfolio/common/interfaces'; import { MarketState } from '@ghostfolio/common/types'; -import { - Account, - DataSource, - SymbolProfile, - Type as ActivityType -} from '@prisma/client'; - -export interface IOrder { - account: Account; - currency: string; - date: string; - fee: number; - id?: string; - isDraft: boolean; - quantity: number; - symbol: string; - symbolProfile: SymbolProfile; - type: ActivityType; - unitPrice: number; -} +import { DataSource } from '@prisma/client'; export interface IDataProviderHistoricalResponse { marketPrice: number; diff --git a/apps/api/src/services/market-data/market-data.service.ts b/apps/api/src/services/market-data/market-data.service.ts index c0abdf04e..58b9b09ec 100644 --- a/apps/api/src/services/market-data/market-data.service.ts +++ b/apps/api/src/services/market-data/market-data.service.ts @@ -60,12 +60,18 @@ export class MarketDataService { public async getRange({ assetProfileIdentifiers, - dateQuery + dateQuery, + skip, + take }: { assetProfileIdentifiers: AssetProfileIdentifier[]; dateQuery: DateQuery; + skip?: number; + take?: number; }): Promise { return this.prismaService.marketData.findMany({ + skip, + take, orderBy: [ { date: 'asc' @@ -75,17 +81,33 @@ export class MarketDataService { } ], where: { - dataSource: { - in: assetProfileIdentifiers.map(({ dataSource }) => { - return dataSource; - }) - }, date: dateQuery, - symbol: { - in: assetProfileIdentifiers.map(({ symbol }) => { - return symbol; - }) - } + OR: assetProfileIdentifiers.map(({ dataSource, symbol }) => { + return { + dataSource, + symbol + }; + }) + } + }); + } + + public async getRangeCount({ + assetProfileIdentifiers, + dateQuery + }: { + assetProfileIdentifiers: AssetProfileIdentifier[]; + dateQuery: DateQuery; + }): Promise { + return this.prismaService.marketData.count({ + where: { + date: dateQuery, + OR: assetProfileIdentifiers.map(({ dataSource, symbol }) => { + return { + dataSource, + symbol + }; + }) } }); } @@ -110,6 +132,22 @@ export class MarketDataService { }); } + public async updateAssetProfileIdentifier( + oldAssetProfileIdentifier: AssetProfileIdentifier, + newAssetProfileIdentifier: AssetProfileIdentifier + ) { + return this.prismaService.marketData.updateMany({ + data: { + dataSource: newAssetProfileIdentifier.dataSource, + symbol: newAssetProfileIdentifier.symbol + }, + where: { + dataSource: oldAssetProfileIdentifier.dataSource, + symbol: oldAssetProfileIdentifier.symbol + } + }); + } + public async updateMarketData(params: { data: { state: MarketDataState; diff --git a/apps/api/src/services/property/interfaces/interfaces.ts b/apps/api/src/services/property/interfaces/interfaces.ts new file mode 100644 index 000000000..be9bc530d --- /dev/null +++ b/apps/api/src/services/property/interfaces/interfaces.ts @@ -0,0 +1 @@ +export type PropertyValue = boolean | object | string | string[]; diff --git a/apps/api/src/services/property/property.service.ts b/apps/api/src/services/property/property.service.ts index 34ce5713b..212635f49 100644 --- a/apps/api/src/services/property/property.service.ts +++ b/apps/api/src/services/property/property.service.ts @@ -6,6 +6,8 @@ import { import { Injectable } from '@nestjs/common'; +import { PropertyValue } from './interfaces/interfaces'; + @Injectable() export class PropertyService { public constructor(private readonly prismaService: PrismaService) {} @@ -18,7 +20,7 @@ export class PropertyService { public async get() { const response: { - [key: string]: boolean | object | string | string[]; + [key: string]: PropertyValue; } = { [PROPERTY_CURRENCIES]: [] }; @@ -38,15 +40,14 @@ export class PropertyService { return response; } - public async getByKey(aKey: string) { + public async getByKey(aKey: string) { const properties = await this.get(); - return properties?.[aKey]; + return properties[aKey] as TValue; } public async isUserSignupEnabled() { return ( - ((await this.getByKey(PROPERTY_IS_USER_SIGNUP_ENABLED)) as boolean) ?? - true + (await this.getByKey(PROPERTY_IS_USER_SIGNUP_ENABLED)) ?? true ); } diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts index eedad7475..9cf6f63e6 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts @@ -1,11 +1,13 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; +import { AssetProfileDelistedError } from '@ghostfolio/api/services/data-provider/errors/asset-profile-delisted.error'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; +import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { DATA_GATHERING_QUEUE, DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY, DEFAULT_PROCESSOR_GATHER_HISTORICAL_MARKET_DATA_CONCURRENCY, - GATHER_ASSET_PROFILE_PROCESS, + GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME } from '@ghostfolio/common/config'; import { DATE_FORMAT, getStartOfUtcDate } from '@ghostfolio/common/helper'; @@ -33,7 +35,8 @@ export class DataGatheringProcessor { public constructor( private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, - private readonly marketDataService: MarketDataService + private readonly marketDataService: MarketDataService, + private readonly symbolProfileService: SymbolProfileService ) {} @Process({ @@ -42,28 +45,49 @@ export class DataGatheringProcessor { DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY.toString(), 10 ), - name: GATHER_ASSET_PROFILE_PROCESS + name: GATHER_ASSET_PROFILE_PROCESS_JOB_NAME }) public async gatherAssetProfile(job: Job) { + const { dataSource, symbol } = job.data; + try { Logger.log( - `Asset profile data gathering has been started for ${job.data.symbol} (${job.data.dataSource})`, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS})` + `Asset profile data gathering has been started for ${symbol} (${dataSource})`, + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` ); await this.dataGatheringService.gatherAssetProfiles([job.data]); Logger.log( - `Asset profile data gathering has been completed for ${job.data.symbol} (${job.data.dataSource})`, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS})` + `Asset profile data gathering has been completed for ${symbol} (${dataSource})`, + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` ); } catch (error) { + if (error instanceof AssetProfileDelistedError) { + await this.symbolProfileService.updateSymbolProfile( + { + dataSource, + symbol + }, + { + isActive: false + } + ); + + Logger.log( + `Asset profile data gathering has been discarded for ${symbol} (${dataSource})`, + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` + ); + + return job.discard(); + } + Logger.error( error, - `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS})` + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS_JOB_NAME})` ); - throw new Error(error); + throw error; } } @@ -76,8 +100,9 @@ export class DataGatheringProcessor { name: GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME }) public async gatherHistoricalMarketData(job: Job) { + const { dataSource, date, symbol } = job.data; + try { - const { dataSource, date, symbol } = job.data; let currentDate = parseISO(date as unknown as string); Logger.log( @@ -142,12 +167,31 @@ export class DataGatheringProcessor { `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` ); } catch (error) { + if (error instanceof AssetProfileDelistedError) { + await this.symbolProfileService.updateSymbolProfile( + { + dataSource, + symbol + }, + { + isActive: false + } + ); + + Logger.log( + `Historical market data gathering has been discarded for ${symbol} (${dataSource})`, + `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` + ); + + return job.discard(); + } + Logger.error( error, `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` ); - throw new Error(error); + throw error; } } } diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index b79b2a098..31edf6ffc 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -159,7 +159,8 @@ export class DataGatheringService { ); if (!assetProfileIdentifiers) { - assetProfileIdentifiers = await this.getAllAssetProfileIdentifiers(); + assetProfileIdentifiers = + await this.getAllActiveAssetProfileIdentifiers(); } if (assetProfileIdentifiers.length <= 0) { @@ -200,6 +201,7 @@ export class DataGatheringService { assetSubClass, countries, currency, + cusip, dataSource, figi, figiComposite, @@ -218,6 +220,7 @@ export class DataGatheringService { assetSubClass, countries, currency, + cusip, dataSource, figi, figiComposite, @@ -234,6 +237,7 @@ export class DataGatheringService { assetSubClass, countries, currency, + cusip, figi, figiComposite, figiShareClass, @@ -293,11 +297,14 @@ export class DataGatheringService { ); } - public async getAllAssetProfileIdentifiers(): Promise< + public async getAllActiveAssetProfileIdentifiers(): Promise< AssetProfileIdentifier[] > { const symbolProfiles = await this.prismaService.symbolProfile.findMany({ - orderBy: [{ symbol: 'asc' }] + orderBy: [{ symbol: 'asc' }], + where: { + isActive: true + } }); return symbolProfiles @@ -367,9 +374,11 @@ export class DataGatheringService { withUserSubscription?: boolean; }): Promise { const symbolProfiles = - await this.symbolProfileService.getSymbolProfilesByUserSubscription({ - withUserSubscription - }); + await this.symbolProfileService.getActiveSymbolProfilesByUserSubscription( + { + withUserSubscription + } + ); const assetProfileIdentifiersWithCompleteMarketData = await this.getAssetProfileIdentifiersWithCompleteMarketData(); @@ -397,9 +406,9 @@ export class DataGatheringService { private async getSymbolsMax(): Promise { const benchmarkAssetProfileIdMap: { [key: string]: boolean } = {}; ( - ((await this.propertyService.getByKey( + (await this.propertyService.getByKey( PROPERTY_BENCHMARKS - )) as BenchmarkProperty[]) ?? [] + )) ?? [] ).forEach(({ symbolProfileId }) => { benchmarkAssetProfileIdMap[symbolProfileId] = true; }); @@ -424,15 +433,18 @@ export class DataGatheringService { await this.prismaService.symbolProfile.findMany({ orderBy: [{ symbol: 'asc' }], select: { - dataSource: true, - id: true, - Order: { + activities: { orderBy: [{ date: 'asc' }], select: { date: true }, take: 1 }, + dataSource: true, + id: true, scraperConfiguration: true, symbol: true + }, + where: { + isActive: true } }) ) @@ -447,7 +459,7 @@ export class DataGatheringService { ); }) .map((symbolProfile) => { - let date = symbolProfile.Order?.[0]?.date ?? startDate; + let date = symbolProfile.activities?.[0]?.date ?? startDate; if (benchmarkAssetProfileIdMap[symbolProfile.id]) { date = this.getEarliestDate(startDate); diff --git a/apps/api/src/services/queues/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts b/apps/api/src/services/queues/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts index 24948e211..b9f315c5d 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts @@ -1,6 +1,8 @@ import { Filter } from '@ghostfolio/common/interfaces'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; export interface IPortfolioSnapshotQueueJob { + calculationType: PerformanceCalculationType; filters: Filter[]; userCurrency: string; userId: string; diff --git a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts index 93b34cbdf..6a2a3114e 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts @@ -1,9 +1,6 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { OrderService } from '@ghostfolio/api/app/order/order.service'; -import { - PerformanceCalculationType, - PortfolioCalculatorFactory -} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; @@ -68,7 +65,7 @@ export class PortfolioSnapshotProcessor { const portfolioCalculator = this.calculatorFactory.createCalculator({ accountBalanceItems, activities, - calculationType: PerformanceCalculationType.TWR, + calculationType: job.data.calculationType, currency: job.data.userCurrency, filters: job.data.filters, userId: job.data.userId diff --git a/apps/api/src/services/symbol-profile/symbol-profile.service.ts b/apps/api/src/services/symbol-profile/symbol-profile.service.ts index eb8778c34..c41a59c78 100644 --- a/apps/api/src/services/symbol-profile/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile/symbol-profile.service.ts @@ -35,6 +35,41 @@ export class SymbolProfileService { }); } + public async getActiveSymbolProfilesByUserSubscription({ + withUserSubscription = false + }: { + withUserSubscription?: boolean; + }) { + return this.prismaService.symbolProfile.findMany({ + include: { + activities: { + include: { + user: true + } + } + }, + orderBy: [{ symbol: 'asc' }], + where: { + activities: withUserSubscription + ? { + some: { + user: { + subscriptions: { some: { expiresAt: { gt: new Date() } } } + } + } + } + : { + every: { + user: { + subscriptions: { none: { expiresAt: { gt: new Date() } } } + } + } + }, + isActive: true + } + }); + } + public async getSymbolProfiles( aAssetProfileIdentifiers: AssetProfileIdentifier[] ): Promise { @@ -42,9 +77,9 @@ export class SymbolProfileService { .findMany({ include: { _count: { - select: { Order: true } + select: { activities: true } }, - Order: { + activities: { orderBy: { date: 'asc' }, @@ -74,7 +109,7 @@ export class SymbolProfileService { .findMany({ include: { _count: { - select: { Order: true } + select: { activities: true } }, SymbolProfileOverrides: true }, @@ -91,56 +126,42 @@ export class SymbolProfileService { }); } - public async getSymbolProfilesByUserSubscription({ - withUserSubscription = false - }: { - withUserSubscription?: boolean; - }) { - return this.prismaService.symbolProfile.findMany({ - include: { - Order: { - include: { - User: true - } - } + public updateAssetProfileIdentifier( + oldAssetProfileIdentifier: AssetProfileIdentifier, + newAssetProfileIdentifier: AssetProfileIdentifier + ) { + return this.prismaService.symbolProfile.update({ + data: { + dataSource: newAssetProfileIdentifier.dataSource, + symbol: newAssetProfileIdentifier.symbol }, - orderBy: [{ symbol: 'asc' }], where: { - Order: withUserSubscription - ? { - some: { - User: { - Subscription: { some: { expiresAt: { gt: new Date() } } } - } - } - } - : { - every: { - User: { - Subscription: { none: { expiresAt: { gt: new Date() } } } - } - } - } + dataSource_symbol: { + dataSource: oldAssetProfileIdentifier.dataSource, + symbol: oldAssetProfileIdentifier.symbol + } } }); } - public updateSymbolProfile({ - assetClass, - assetSubClass, - comment, - countries, - currency, - dataSource, - holdings, - name, - scraperConfiguration, - sectors, - symbol, - symbolMapping, - SymbolProfileOverrides, - url - }: AssetProfileIdentifier & Prisma.SymbolProfileUpdateInput) { + public updateSymbolProfile( + { dataSource, symbol }: AssetProfileIdentifier, + { + assetClass, + assetSubClass, + comment, + countries, + currency, + holdings, + isActive, + name, + scraperConfiguration, + sectors, + symbolMapping, + SymbolProfileOverrides, + url + }: Prisma.SymbolProfileUpdateInput + ) { return this.prismaService.symbolProfile.update({ data: { assetClass, @@ -149,6 +170,7 @@ export class SymbolProfileService { countries, currency, holdings, + isActive, name, scraperConfiguration, sectors, @@ -162,8 +184,8 @@ export class SymbolProfileService { private enhanceSymbolProfiles( symbolProfiles: (SymbolProfile & { - _count: { Order: number }; - Order?: { + _count: { activities: number }; + activities?: { date: Date; }[]; SymbolProfileOverrides: SymbolProfileOverrides; @@ -177,17 +199,21 @@ export class SymbolProfileService { symbolProfile?.countries as unknown as Prisma.JsonArray ), dateOfFirstActivity: undefined as Date, - holdings: this.getHoldings(symbolProfile), + holdings: this.getHoldings( + symbolProfile?.holdings as unknown as Prisma.JsonArray + ), scraperConfiguration: this.getScraperConfiguration(symbolProfile), - sectors: this.getSectors(symbolProfile), + sectors: this.getSectors( + symbolProfile?.sectors as unknown as Prisma.JsonArray + ), symbolMapping: this.getSymbolMapping(symbolProfile) }; - item.activitiesCount = symbolProfile._count.Order; + item.activitiesCount = symbolProfile._count.activities; delete item._count; - item.dateOfFirstActivity = symbolProfile.Order?.[0]?.date; - delete item.Order; + item.dateOfFirstActivity = symbolProfile.activities?.[0]?.date; + delete item.activities; if (item.SymbolProfileOverrides) { item.assetClass = @@ -200,8 +226,7 @@ export class SymbolProfileService { ?.length > 0 ) { item.countries = this.getCountries( - item.SymbolProfileOverrides - ?.countries as unknown as Prisma.JsonArray + item.SymbolProfileOverrides.countries as unknown as Prisma.JsonArray ); } @@ -209,21 +234,23 @@ export class SymbolProfileService { (item.SymbolProfileOverrides.holdings as unknown as Holding[]) ?.length > 0 ) { - item.holdings = item.SymbolProfileOverrides - .holdings as unknown as Holding[]; + item.holdings = this.getHoldings( + item.SymbolProfileOverrides.holdings as unknown as Prisma.JsonArray + ); } - item.name = item.SymbolProfileOverrides?.name ?? item.name; + item.name = item.SymbolProfileOverrides.name ?? item.name; if ( (item.SymbolProfileOverrides.sectors as unknown as Sector[])?.length > 0 ) { - item.sectors = item.SymbolProfileOverrides - .sectors as unknown as Sector[]; + item.sectors = this.getSectors( + item.SymbolProfileOverrides.sectors as unknown as Prisma.JsonArray + ); } - item.url = item.SymbolProfileOverrides?.url ?? item.url; + item.url = item.SymbolProfileOverrides.url ?? item.url; delete item.SymbolProfileOverrides; } @@ -249,18 +276,20 @@ export class SymbolProfileService { }); } - private getHoldings(symbolProfile: SymbolProfile): Holding[] { - return ((symbolProfile?.holdings as Prisma.JsonArray) ?? []).map( - (holding) => { - const { name, weight } = holding as Prisma.JsonObject; + private getHoldings(aHoldings: Prisma.JsonArray = []): Holding[] { + if (aHoldings === null) { + return []; + } - return { - allocationInPercentage: weight as number, - name: (name as string) ?? UNKNOWN_KEY, - valueInBaseCurrency: undefined - }; - } - ); + return aHoldings.map((holding) => { + const { name, weight } = holding as Prisma.JsonObject; + + return { + allocationInPercentage: weight as number, + name: (name as string) ?? UNKNOWN_KEY, + valueInBaseCurrency: undefined + }; + }); } private getScraperConfiguration( @@ -285,17 +314,19 @@ export class SymbolProfileService { return null; } - private getSectors(symbolProfile: SymbolProfile): Sector[] { - return ((symbolProfile?.sectors as Prisma.JsonArray) ?? []).map( - (sector) => { - const { name, weight } = sector as Prisma.JsonObject; + private getSectors(aSectors: Prisma.JsonArray = []): Sector[] { + if (aSectors === null) { + return []; + } - return { - name: (name as string) ?? UNKNOWN_KEY, - weight: weight as number - }; - } - ); + return aSectors.map((sector) => { + const { name, weight } = sector as Prisma.JsonObject; + + return { + name: (name as string) ?? UNKNOWN_KEY, + weight: weight as number + }; + }); } private getSymbolMapping(symbolProfile: SymbolProfile) { diff --git a/apps/api/src/services/tag/tag.service.ts b/apps/api/src/services/tag/tag.service.ts index b16f22fbb..eb2d7bfef 100644 --- a/apps/api/src/services/tag/tag.service.ts +++ b/apps/api/src/services/tag/tag.service.ts @@ -1,17 +1,58 @@ import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { Injectable } from '@nestjs/common'; +import { Prisma, Tag } from '@prisma/client'; @Injectable() export class TagService { public constructor(private readonly prismaService: PrismaService) {} + public async createTag(data: Prisma.TagCreateInput) { + return this.prismaService.tag.create({ + data + }); + } + + public async deleteTag(where: Prisma.TagWhereUniqueInput): Promise { + return this.prismaService.tag.delete({ where }); + } + + public async getTag( + tagWhereUniqueInput: Prisma.TagWhereUniqueInput + ): Promise { + return this.prismaService.tag.findUnique({ + where: tagWhereUniqueInput + }); + } + + public async getTags({ + cursor, + orderBy, + skip, + take, + where + }: { + cursor?: Prisma.TagWhereUniqueInput; + orderBy?: Prisma.TagOrderByWithRelationInput; + skip?: number; + take?: number; + where?: Prisma.TagWhereInput; + } = {}) { + return this.prismaService.tag.findMany({ + cursor, + orderBy, + skip, + take, + where + }); + } + public async getTagsForUser(userId: string) { const tags = await this.prismaService.tag.findMany({ include: { _count: { select: { - orders: { + activities: { where: { userId } @@ -38,7 +79,39 @@ export class TagService { id, name, userId, - isUsed: _count.orders > 0 + isUsed: _count.activities > 0 })); } + + public async getTagsWithActivityCount() { + const tagsWithOrderCount = await this.prismaService.tag.findMany({ + include: { + _count: { + select: { activities: true } + } + } + }); + + return tagsWithOrderCount.map(({ _count, id, name, userId }) => { + return { + id, + name, + userId, + activityCount: _count.activities + }; + }); + } + + public async updateTag({ + data, + where + }: { + data: Prisma.TagUpdateInput; + where: Prisma.TagWhereUniqueInput; + }): Promise { + return this.prismaService.tag.update({ + data, + where + }); + } } diff --git a/apps/api/src/services/twitter-bot/twitter-bot.module.ts b/apps/api/src/services/twitter-bot/twitter-bot.module.ts index 4a2b1589a..80d53169c 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.module.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.module.ts @@ -1,5 +1,5 @@ -import { BenchmarkModule } from '@ghostfolio/api/app/benchmark/benchmark.module'; import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; +import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { TwitterBotService } from '@ghostfolio/api/services/twitter-bot/twitter-bot.service'; diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts index a32882aed..ee951820d 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts @@ -1,8 +1,8 @@ -import { BenchmarkService } from '@ghostfolio/api/app/benchmark/benchmark.service'; import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; +import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { - ghostfolioFearAndGreedIndexDataSource, + ghostfolioFearAndGreedIndexDataSourceStocks, ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; import { @@ -44,7 +44,7 @@ export class TwitterBotService { try { const symbolItem = await this.symbolService.get({ dataGatheringItem: { - dataSource: ghostfolioFearAndGreedIndexDataSource, + dataSource: ghostfolioFearAndGreedIndexDataSourceStocks, symbol: ghostfolioFearAndGreedIndexSymbol } }); diff --git a/apps/api/src/validators/is-currency-code.ts b/apps/api/src/validators/is-currency-code.ts index 34a82c481..771818b05 100644 --- a/apps/api/src/validators/is-currency-code.ts +++ b/apps/api/src/validators/is-currency-code.ts @@ -1,4 +1,4 @@ -import { DERIVED_CURRENCIES } from '@ghostfolio/common/config'; +import { isDerivedCurrency } from '@ghostfolio/common/helper'; import { registerDecorator, @@ -25,19 +25,18 @@ export class IsExtendedCurrencyConstraint implements ValidatorConstraintInterface { public defaultMessage() { - return '$value must be a valid ISO4217 currency code'; + return '$property must be a valid ISO4217 currency code'; } - public validate(currency: any) { - // Return true if currency is a standard ISO 4217 code or a derived currency + public validate(currency: string) { + // Return true if currency is a derived currency or a standard ISO 4217 code return ( - isISO4217CurrencyCode(currency) || - [ - ...DERIVED_CURRENCIES.map((derivedCurrency) => { - return derivedCurrency.currency; - }), - 'USX' - ].includes(currency) + isDerivedCurrency(currency) || + (this.isUpperCase(currency) && isISO4217CurrencyCode(currency)) ); } + + private isUpperCase(aString: string) { + return aString === aString?.toUpperCase(); + } } diff --git a/apps/client-e2e/project.json b/apps/client-e2e/project.json index 16d13e012..92e2f09ef 100644 --- a/apps/client-e2e/project.json +++ b/apps/client-e2e/project.json @@ -3,12 +3,13 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "apps/client-e2e/src", "projectType": "application", + "tags": [], + "implicitDependencies": ["client"], "targets": { "e2e": { "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "apps/client-e2e/cypress.json", - "tsConfig": "apps/client-e2e/tsconfig.e2e.json", "devServerTarget": "client:serve" }, "configurations": { @@ -17,7 +18,5 @@ } } } - }, - "tags": [], - "implicitDependencies": ["client"] + } } diff --git a/apps/client/.eslintrc.json b/apps/client/.eslintrc.json deleted file mode 100644 index fdb4f84f1..000000000 --- a/apps/client/.eslintrc.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "parserOptions": { - "project": ["apps/client/tsconfig.*?.json"] - }, - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/prefer-standalone": "off" - } - } - ], - "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"], - "rules": { - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "gf", - "style": "kebab-case" - } - ], - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "gf", - "style": "camelCase" - } - ] - } -} diff --git a/apps/client/eslint.config.cjs b/apps/client/eslint.config.cjs new file mode 100644 index 000000000..96ecefd50 --- /dev/null +++ b/apps/client/eslint.config.cjs @@ -0,0 +1,63 @@ +const baseConfig = require('../../eslint.config.cjs'); +const angularEslintPlugin = require('@angular-eslint/eslint-plugin'); +const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); + +module.exports = [ + { + ignores: ['**/dist'] + }, + ...baseConfig, + { + plugins: { + '@angular-eslint': angularEslintPlugin, + '@typescript-eslint': typescriptEslintPlugin + } + }, + { + rules: { + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'gf', + style: 'kebab-case' + } + ], + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'gf', + style: 'camelCase' + } + ], + '@angular-eslint/prefer-inject': 'off' + } + }, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {}, + languageOptions: { + parserOptions: { + project: ['apps/client/tsconfig.*?.json'] + } + } + }, + { + files: ['**/*.ts', '**/*.tsx'], + // Override or add rules here + rules: {} + }, + { + files: ['**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {} + }, + { + files: ['**/*.ts'], + rules: { + '@angular-eslint/prefer-standalone': 'off' + } + } +]; diff --git a/apps/client/localhost.cert b/apps/client/localhost.cert index 12f31dd27..882ddd2a4 100644 --- a/apps/client/localhost.cert +++ b/apps/client/localhost.cert @@ -1,18 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIC5TCCAc2gAwIBAgIJAJAMHOFnJ6oyMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV -BAMMCWxvY2FsaG9zdDAeFw0yNDAyMjcxNTQ2MzFaFw0yNDAzMjgxNTQ2MzFaMBQx -EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAJ0hRjViikEKVIyukXR4CfuYVvFEFzB6AwAQ9Jrz2MseqpLacLTXFFAS54mp -iDuqPBzs9ta40mlSrqSBuAWKikpW5kTNnmqUnDZ6iSJezbYWx9YyULGqqb1q3C4/ -5pH9m6NHJ+2uaUNKlDxYNKbntqs3drQEdxH9yv672Z53nvogTcf9jz6zjutEQGSV -HgVkCTTQmzf3+3st+VJ5D8JeYFR+tpZ6yleqgXFaTMtPZRfKLvTkQ+KeyCJLnsUJ -BQvdCKI0PGsG6d6ygXFmSePolD9KW3VTKKDPCsndID89vAnRWDj9UhzvycxmKpcF -GrUPH5+Pis1PM1R7OnAvnFygnyECAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo -b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B -AQsFAAOCAQEAOdzrY3RTAPnBVAd3/GKIEkielYyOgKPnvd+RcOB+je8cXZY+vaxX -uEFP0526G00+kRZ2Tx9t0SmjoSpwg3lHUPMko0dIxgRlqISDAohdrEptHpcVujsD -ak88LLnAurr60JNjWX2wbEoJ18KLtqGSnATdmCgKwDPIN5a7+ssp44BGyzH6VYCg -wV3VjJl0pp4C5M0Jfu0p1FrQjzIVhgqR7JFYmvqIogWrGwYAQK/3XRXq8t48J5X3 -IsfWiLAA2ZdCoWAnZ6PAGBOoGivtkJm967pHjd/28qYY6mQo4sN2ksEOjx6/YslF -2mOJdLV/DzqoggUsTpPEG0dRhzQLTGHKDQ== +MIIDSDCCAjACCQCQ2ForVhz+uDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJD +SDEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxFTATBgNVBAoMDE9yZ2Fu +aXphdGlvbjENMAsGA1UECwwEVW5pdDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1 +MDMwOTE2MzQxM1oXDTI2MDMwOTE2MzQxM1owZjELMAkGA1UEBhMCQ0gxDjAMBgNV +BAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MRUwEwYDVQQKDAxPcmdhbml6YXRpb24x +DTALBgNVBAsMBFVuaXQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMkJRKPgV8NDcoIakPc7sZVXQ9VK2PGb8+lF/1Lv +NcIZpD40+p4DzuEw0bjRn17IDClyLMaLbZNtIyTPSkFaffL+rJ0JvnKdG50s+HId +YNuCwKkgHg4hTXFzOPpT3HMG3UxyEwFOm25GMFiikfT96ukMAAkanMqYKZQOClRU +Cw4LP3g0Oks58obbRy4Wltp88K8LJrR+j81+AjElTIGXHhChXzV/NjJ14TMNy5hZ +lwV4xUSwvNqOvWGMIR7J77fINF130ghTSnvzCS52dCeom2I4Lvncz3m37lDttCOs +Wm/i651ro7pwFEs/lJmrnFHPtph2ayPcHBmrQCgLc5xMUMcCAwEAATANBgkqhkiG +9w0BAQsFAAOCAQEAhRA1/+Gl2VH34yN/FvrE5cY0W4ghSCuTdK9pGeo8AcN+TScU +7O+hVsEwZDrYKuDvG8Ab//A+uv5gbfGbYPJVIdJ3Q8HKijNZmbwAgANJU/c0WwOx +XBQ9mCzWRcJxQeUUgh4DT4lZCOfR5pIvAJpKScTcF/yp5gOgrgJH1GHFEYYPoXWO +ezPPMwCNbfamUPlZZnHu74fUrFrDPI9c/YSu8Ex/LegZXJAEzA+8I0g64rjGtzJp +fkRDyQcBuT5SVa+USBlALQmdIuT/fN6R729DcGzvV8JqdoG9sLra4hrRCn3+A3c9 +izZguW1BQNQ2N7II6QCDnWkdUFSQCiQunX/xsg== -----END CERTIFICATE----- diff --git a/apps/client/localhost.pem b/apps/client/localhost.pem index dc2a7ff5a..05a480779 100644 --- a/apps/client/localhost.pem +++ b/apps/client/localhost.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCdIUY1YopBClSM -rpF0eAn7mFbxRBcwegMAEPSa89jLHqqS2nC01xRQEueJqYg7qjwc7PbWuNJpUq6k -gbgFiopKVuZEzZ5qlJw2eokiXs22FsfWMlCxqqm9atwuP+aR/ZujRyftrmlDSpQ8 -WDSm57arN3a0BHcR/cr+u9med576IE3H/Y8+s47rREBklR4FZAk00Js39/t7LflS -eQ/CXmBUfraWespXqoFxWkzLT2UXyi705EPinsgiS57FCQUL3QiiNDxrBunesoFx -Zknj6JQ/Slt1UyigzwrJ3SA/PbwJ0Vg4/VIc78nMZiqXBRq1Dx+fj4rNTzNUezpw -L5xcoJ8hAgMBAAECggEAPU5YOEgELTA8oM8TjV+wdWuQsH2ilpVkSkhTR4nQkh+a -6cU0qDoqgLt/fySYNL9MyPRjso9V+SX7YdAC3paZMjwJh9q57lehQ1g33SMkG+Fz -gs0K0ucFZxQkaB8idN+ANAp1N7UO+ORGRe0cTeqmSNNRCxea5XgiFZVxaPS/IFOR -vVdXS1DulgwHh4H0ljKmkj7jc9zPBSc9ccW5Ml2q4a26Atu4IC/Mlp/DF4GNELbD -ebi9ZOZG33ip2bdhj3WX7NW9GJaaViKtVUpcpR6u+6BfvTXQ6xrqdoxXk9fnPzzf -sSoLPTt8yO4RavP1zQU22PhgIcWudhCiy/2Nv+uLqQKBgQDMPh1/xwdFl8yES8dy -f0xJyCDWPiB+xzGwcOAC90FrNZaqG0WWs3VHE4cilaWjCflvdR6aAEDEY68sZJhl -h+ChT/g61QLMOI+VIDQ1kJXKYgfS/B+BE1PZ0EkuymKFOvbNO8agHodB8CqnZaQh -bLuZaDnZ0JLK4im3KPt70+aKYwKBgQDE8s6xl0SLu+yJLo3VklCRD67Z8/jlvx2t -h3DF6NG8pB3QmvKdJWFKuLAWLGflJwbUW9Pt3hXkc0649KQrtiIYC0ZMh9KMaVCk -WmjS/n2eIUQZ7ZUlwFesi4p4iGynVBavIY8TJ6Y+K3TvsJgXP3IZ96r689PQJo8E -KbSeyYzFqwKBgGQTS4EAlJ+U8bEhMGj51veQCAbyChoUoFRD+n95h6RwbZKMKlzd -MenRt7VKfg6VJJNoX8Y1uYaBEaQ+5i1Zlsdz1718AhLu4+u+C9bzMXIo9ox63TTx -s3RWioVSxVNiwOtvDrQGQWAdvcioFPQLwyA34aDIgiTHDImimxbhjWThAoGAWOqW -Tq9QjxWk0Lpn5ohMP3GpK1VuhasnJvUDARb/uf8ORuPtrOz3Y9jGBvy9W0OnXbCn -mbiugZldbTtl8yYjdl+AuYSIlkPl2I3IzZl/9Shnqp0MvSJ9crT9KzXMeC8Knr6z -7Z30/BR6ksxTngtS5E5grzPt6Qe/gc2ich3kpEkCgYBfBHUhVIKVrDW/8a7U2679 -Wj4i9us/M3iPMxcTv7/ZAg08TEvNBQYtvVQLu0NfDKXx8iGKJJ6evIYgNXVm2sPq -VzSgwGCALi1X0443amZU+mnX+/9RnBqyM+PJU8570mM83jqKlY/BEsi0aqxTioFG -an3xbjjN+Rq9iKLzmPxIMg== +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJCUSj4FfDQ3KC +GpD3O7GVV0PVStjxm/PpRf9S7zXCGaQ+NPqeA87hMNG40Z9eyAwpcizGi22TbSMk +z0pBWn3y/qydCb5ynRudLPhyHWDbgsCpIB4OIU1xczj6U9xzBt1MchMBTptuRjBY +opH0/erpDAAJGpzKmCmUDgpUVAsOCz94NDpLOfKG20cuFpbafPCvCya0fo/NfgIx +JUyBlx4QoV81fzYydeEzDcuYWZcFeMVEsLzajr1hjCEeye+3yDRdd9IIU0p78wku +dnQnqJtiOC753M95t+5Q7bQjrFpv4uuda6O6cBRLP5SZq5xRz7aYdmsj3BwZq0Ao +C3OcTFDHAgMBAAECggEBALJQqDN7QB0QbDb+fWrt5bwDJUXBF+BmZdiZn7jeOJ6r +w8TxlQIneo6/kKYQOP4HDtKMVS7eaRkFCtERlFmXfHPWdSDtjaF3vRCS3OPLLyhF +N8JLnJ0H6PsiKn3PeJAGnK+71yOnp7IOS7+yoyfdOUnwvO9WTZBdmzOZqIvX595R +g7R5yjSYjzFMmaCpyab6kiD7b4bHzDIrB0XuouT2W/fS/i1srwc3eDk78ZyioyiB +g6GDuOwqDfPmkUqKo2oXSoSR8yCwSSdlClc7aOowoNxbsksTDjXf1k02n0lG5MHU +ldCX02WdA0JFW8Os0Ig+YBq7wSkB5oNVt7gEek/MB0ECgYEA+ATkyfX9/5X2kUMY +MatUqKOvLUtyIfHeYUy/Dm+9JlZlrxD0dRAKWhnhRR16v5cwN2RVtEvMDsV1AGHN +e/fh315aAq+I6/eY6syXfkeHHs5UIRPrOlIcp1Ogfg99xpOT0/TZy9bB7lKvtYes +GmKO8n7md1TptdxilSNORI60KvECgYEAz4FX6vH76HgV/seY+vePrj5nFCZnDru7 +16w5LYoHaX0hABJ0qZCqZozdPf9mqM5Ldc8PUbvVsFqXyaHwBAKUsH44a3aLxcXU +JMsQanU5I87SWP/S8Xu2Yxc10L66Oc5VdAeraZvb+wJqTkYKhDYOJVMjyuI/vkAw +fqMPI6wShzcCgYEAndYnb6uf4Eakap9jR0C8mLHKaq3nzVhqaEt6DwrnOf2jqnzE +xbbWj66GoQB4vHLP2YB91kaibwgURJD5PxpqYUdfSvRA08J3S322L0P/5ofyHDbb +7PqSh539thvPtE74tdvNux5Jvoxai9Dyorv0Mri1nF2qefTtu/GC/rg+SlECgYB2 +FaYhhomTVls1/QIat6zlPI/OULhPExineFOljaoAJvwTnW0UXcYKy9jPgjs6jwM0 +TJvsKFdHn5ZHYUdEEO/qrDmRNgn+h0Ddm02BN6pHrVfY2+SAFaXKKBgw7YjugnPw +rrimRdLeuhYi6wrrCBPuu6xftXcO3lp6hnKEG1UD6wKBgEh/C7HQ6cjb7Rr15eRq +2VOgeuz7o2v/OC+jO6yFGRrs2VKoBuJpw/6jx806Cbi2jLEwim21iNYW/2McOWP3 +YUvni7qHXfll8d4sSAuCTA4K/N0MJ/3XbGBPDm/83J2o7uz2GFkQRruruaERvDMF +x26H2i3DOUFzdgbkoNB0ifHd -----END PRIVATE KEY----- diff --git a/apps/client/ngsw-config.json b/apps/client/ngsw-config.json index c0f03a135..56e1cfd63 100644 --- a/apps/client/ngsw-config.json +++ b/apps/client/ngsw-config.json @@ -6,13 +6,7 @@ "name": "app", "installMode": "prefetch", "resources": { - "files": [ - "/favicon.ico", - "/index.html", - "/assets/site.webmanifest", - "/*.css", - "/*.js" - ] + "files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"] } }, { diff --git a/apps/client/project.json b/apps/client/project.json index 7fd28d5ca..0b0dc0a63 100644 --- a/apps/client/project.json +++ b/apps/client/project.json @@ -2,13 +2,63 @@ "name": "client", "$schema": "../../node_modules/nx/schemas/project-schema.json", "projectType": "application", + "sourceRoot": "apps/client/src", + "prefix": "gf", + "i18n": { + "locales": { + "ca": { + "baseHref": "/ca/", + "translation": "apps/client/src/locales/messages.ca.xlf" + }, + "de": { + "baseHref": "/de/", + "translation": "apps/client/src/locales/messages.de.xlf" + }, + "es": { + "baseHref": "/es/", + "translation": "apps/client/src/locales/messages.es.xlf" + }, + "fr": { + "baseHref": "/fr/", + "translation": "apps/client/src/locales/messages.fr.xlf" + }, + "it": { + "baseHref": "/it/", + "translation": "apps/client/src/locales/messages.it.xlf" + }, + "nl": { + "baseHref": "/nl/", + "translation": "apps/client/src/locales/messages.nl.xlf" + }, + "pl": { + "baseHref": "/pl/", + "translation": "apps/client/src/locales/messages.pl.xlf" + }, + "pt": { + "baseHref": "/pt/", + "translation": "apps/client/src/locales/messages.pt.xlf" + }, + "tr": { + "baseHref": "/tr/", + "translation": "apps/client/src/locales/messages.tr.xlf" + }, + "uk": { + "baseHref": "/uk/", + "translation": "apps/client/src/locales/messages.uk.xlf" + }, + "zh": { + "baseHref": "/zh/", + "translation": "apps/client/src/locales/messages.zh.xlf" + } + }, + "sourceLocale": "en" + }, + "tags": [], "generators": { "@schematics/angular:component": { "style": "scss" } }, - "sourceRoot": "apps/client/src", - "prefix": "gf", "targets": { "build": { "executor": "@nx/angular:webpack-browser", @@ -23,7 +73,8 @@ "styles": [ "apps/client/src/assets/fonts/inter.css", "apps/client/src/styles/theme.scss", - "apps/client/src/styles.scss" + "apps/client/src/styles.scss", + "node_modules/open-color/open-color.css" ], "scripts": ["node_modules/marked/marked.min.js"], "vendorChunk": true, @@ -76,6 +127,10 @@ "baseHref": "/tr/", "localize": ["tr"] }, + "development-uk": { + "baseHref": "/uk/", + "localize": ["uk"] + }, "development-zh": { "baseHref": "/zh/", "localize": ["zh"] @@ -124,14 +179,11 @@ { "command": "shx mkdir -p dist/apps/client/assets" }, - { - "command": "shx mkdir -p dist/apps/client/ionicons" - }, { "command": "shx cp -r apps/client/src/assets/* dist/apps/client/assets" }, { - "command": "shx cp -r apps/client/src/assets/.well-known/* dist/apps/client/.well-known" + "command": "shx cp -r apps/client/src/assets/.well-known/assetlinks.json dist/apps/client/.well-known" }, { "command": "shx cp apps/client/src/assets/favicon.ico dist/apps/client" @@ -142,18 +194,6 @@ { "command": "shx cp apps/client/src/assets/robots.txt dist/apps/client" }, - { - "command": "shx cp apps/client/src/assets/site.webmanifest dist/apps/client" - }, - { - "command": "shx cp node_modules/ionicons/dist/index.js dist/apps/client" - }, - { - "command": "shx cp node_modules/ionicons/dist/ionicons.js dist/apps/client" - }, - { - "command": "shx cp -r node_modules/ionicons/dist/ionicons/* dist/apps/client/ionicons" - }, { "command": "shx cp CHANGELOG.md dist/apps/client/assets" }, @@ -201,13 +241,17 @@ "development-tr": { "buildTarget": "client:build:development-tr" }, + "development-uk": { + "buildTarget": "client:build:development-uk" + }, "development-zh": { "buildTarget": "client:build:development-zh" }, "production": { "buildTarget": "client:build:production" } - } + }, + "continuous": true }, "extract-i18n": { "executor": "ng-extract-i18n-merge:ng-extract-i18n-merge", @@ -225,6 +269,7 @@ "messages.pl.xlf", "messages.pt.xlf", "messages.tr.xlf", + "messages.uk.xlf", "messages.zh.xlf" ] } @@ -242,51 +287,5 @@ }, "outputs": ["{workspaceRoot}/coverage/apps/client"] } - }, - "i18n": { - "locales": { - "ca": { - "baseHref": "/ca/", - "translation": "apps/client/src/locales/messages.ca.xlf" - }, - "de": { - "baseHref": "/de/", - "translation": "apps/client/src/locales/messages.de.xlf" - }, - "es": { - "baseHref": "/es/", - "translation": "apps/client/src/locales/messages.es.xlf" - }, - "fr": { - "baseHref": "/fr/", - "translation": "apps/client/src/locales/messages.fr.xlf" - }, - "it": { - "baseHref": "/it/", - "translation": "apps/client/src/locales/messages.it.xlf" - }, - "nl": { - "baseHref": "/nl/", - "translation": "apps/client/src/locales/messages.nl.xlf" - }, - "pl": { - "baseHref": "/pl/", - "translation": "apps/client/src/locales/messages.pl.xlf" - }, - "pt": { - "baseHref": "/pt/", - "translation": "apps/client/src/locales/messages.pt.xlf" - }, - "tr": { - "baseHref": "/tr/", - "translation": "apps/client/src/locales/messages.tr.xlf" - }, - "zh": { - "baseHref": "/zh/", - "translation": "apps/client/src/locales/messages.zh.xlf" - } - }, - "sourceLocale": "en" - }, - "tags": [] + } } diff --git a/apps/client/proxy.conf.json b/apps/client/proxy.conf.json index 94a448238..a31371d9f 100644 --- a/apps/client/proxy.conf.json +++ b/apps/client/proxy.conf.json @@ -6,9 +6,5 @@ "/assets": { "target": "http://0.0.0.0:3333", "secure": false - }, - "/ionicons": { - "target": "http://0.0.0.0:3333", - "secure": false } } diff --git a/apps/client/src/app/app-routing.module.ts b/apps/client/src/app/app-routing.module.ts index f4b61ea33..70d4f8b30 100644 --- a/apps/client/src/app/app-routing.module.ts +++ b/apps/client/src/app/app-routing.module.ts @@ -1,6 +1,6 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; -import { paths } from '@ghostfolio/client/core/paths'; import { PageTitleStrategy } from '@ghostfolio/client/services/page-title.strategy'; +import { publicRoutes, internalRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes, TitleStrategy } from '@angular/router'; @@ -9,28 +9,26 @@ import { ModulePreloadService } from './core/module-preload.service'; const routes: Routes = [ { - path: paths.about, + path: publicRoutes.about.path, loadChildren: () => - import('./pages/about/about-page.module').then((m) => m.AboutPageModule) + import('./pages/about/about-page.routes').then((m) => m.routes) }, { - path: 'account', + path: internalRoutes.account.path, loadChildren: () => - import('./pages/user-account/user-account-page.module').then( - (m) => m.UserAccountPageModule + import('./pages/user-account/user-account-page.routes').then( + (m) => m.routes ) }, { - path: 'accounts', + path: internalRoutes.accounts.path, loadChildren: () => - import('./pages/accounts/accounts-page.module').then( - (m) => m.AccountsPageModule - ) + import('./pages/accounts/accounts-page.routes').then((m) => m.routes) }, { - path: 'admin', + path: internalRoutes.adminControl.path, loadChildren: () => - import('./pages/admin/admin-page.module').then((m) => m.AdminPageModule) + import('./pages/admin/admin-page.routes').then((m) => m.routes) }, { canActivate: [AuthGuard], @@ -38,16 +36,17 @@ const routes: Routes = [ import('./pages/api/api-page.component').then( (c) => c.GfApiPageComponent ), - path: 'api', - title: 'Ghostfolio API' + path: internalRoutes.api.path, + title: internalRoutes.api.title }, { - path: 'auth', + path: internalRoutes.auth.path, loadChildren: () => - import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule) + import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule), + title: internalRoutes.auth.title }, { - path: 'blog', + path: publicRoutes.blog.path, loadChildren: () => import('./pages/blog/blog-page.module').then((m) => m.BlogPageModule) }, @@ -57,12 +56,12 @@ const routes: Routes = [ import('./pages/demo/demo-page.component').then( (c) => c.GfDemoPageComponent ), - path: 'demo' + path: publicRoutes.demo.path }, { - path: paths.faq, + path: publicRoutes.faq.path, loadChildren: () => - import('./pages/faq/faq-page.module').then((m) => m.FaqPageModule) + import('./pages/faq/faq-page.routes').then((m) => m.routes) }, { canActivate: [AuthGuard], @@ -70,13 +69,13 @@ const routes: Routes = [ import('./pages/features/features-page.component').then( (c) => c.GfFeaturesPageComponent ), - path: paths.features, - title: $localize`Features` + path: publicRoutes.features.path, + title: publicRoutes.features.title }, { - path: 'home', + path: internalRoutes.home.path, loadChildren: () => - import('./pages/home/home-page.module').then((m) => m.HomePageModule) + import('./pages/home/home-page.routes').then((m) => m.routes) }, { canActivate: [AuthGuard], @@ -84,58 +83,54 @@ const routes: Routes = [ import('./pages/i18n/i18n-page.component').then( (c) => c.GfI18nPageComponent ), - path: 'i18n', - title: $localize`Internationalization` + path: internalRoutes.i18n.path, + title: internalRoutes.i18n.title }, { - path: paths.markets, + path: publicRoutes.markets.path, loadChildren: () => import('./pages/markets/markets-page.module').then( (m) => m.MarketsPageModule ) }, { - path: 'open', + path: publicRoutes.openStartup.path, loadChildren: () => import('./pages/open/open-page.module').then((m) => m.OpenPageModule) }, { - path: 'p', + path: internalRoutes.portfolio.path, loadChildren: () => - import('./pages/public/public-page.module').then( - (m) => m.PublicPageModule - ) + import('./pages/portfolio/portfolio-page.routes').then((m) => m.routes) }, { - path: 'portfolio', + path: publicRoutes.pricing.path, loadChildren: () => - import('./pages/portfolio/portfolio-page.module').then( - (m) => m.PortfolioPageModule + import('./pages/pricing/pricing-page.module').then( + (m) => m.PricingPageModule ) }, { - path: paths.pricing, + path: publicRoutes.public.path, loadChildren: () => - import('./pages/pricing/pricing-page.module').then( - (m) => m.PricingPageModule + import('./pages/public/public-page.module').then( + (m) => m.PublicPageModule ) }, { - path: paths.register, + path: publicRoutes.register.path, loadChildren: () => import('./pages/register/register-page.module').then( (m) => m.RegisterPageModule ) }, { - path: paths.resources, + path: publicRoutes.resources.path, loadChildren: () => - import('./pages/resources/resources-page.module').then( - (m) => m.ResourcesPageModule - ) + import('./pages/resources/resources-page.routes').then((m) => m.routes) }, { - path: 'start', + path: publicRoutes.start.path, loadChildren: () => import('./pages/landing/landing-page.module').then( (m) => m.LandingPageModule @@ -146,11 +141,11 @@ const routes: Routes = [ import('./pages/webauthn/webauthn-page.component').then( (c) => c.GfWebauthnPageComponent ), - path: 'webauthn', - title: $localize`Sign in` + path: internalRoutes.webauthn.path, + title: internalRoutes.webauthn.title }, { - path: 'zen', + path: internalRoutes.zen.path, loadChildren: () => import('./pages/zen/zen-page.module').then((m) => m.ZenPageModule) }, diff --git a/apps/client/src/app/app.component.html b/apps/client/src/app/app.component.html index 7560e15e5..9680d0830 100644 --- a/apps/client/src/app/app.component.html +++ b/apps/client/src/app/app.component.html @@ -10,7 +10,7 @@ (click)="onCreateAccount()" > You are using the Live Demo. - Create Account + Create Account } @@ -70,7 +70,7 @@
  • About
  • @if (hasPermissionForSubscription) {
  • - Blog + Blog
  • }
  • @@ -84,12 +84,14 @@ >
  • } -
  • - License -
  • + @if (!hasPermissionForSubscription) { +
  • + License +
  • + } @if (hasPermissionForStatistics) {
  • - Open Startup + Open Startup
  • } @if (hasPermissionForSubscription) { @@ -104,6 +106,13 @@ > } + @if (hasPermissionForSubscription) { +
  • + Terms of Service +
  • + } @if (hasPermissionForSubscription) {
  • GitHub
  • +
  • + LinkedIn +
  • Català
  • --> +
  • + Chinese +
  • Deutsch
  • @@ -182,7 +203,7 @@ diff --git a/apps/client/src/app/app.component.scss b/apps/client/src/app/app.component.scss index 241d3331e..f848fe6ff 100644 --- a/apps/client/src/app/app.component.scss +++ b/apps/client/src/app/app.component.scss @@ -15,12 +15,14 @@ z-index: 999; .info-message { - color: rgba(var(--palette-foreground-text), 1); + color: rgba(var(--light-primary-text)); font-size: 80%; + font-weight: 500; max-width: 100%; .a { - font-weight: 500; + border: 1px solid rgba(var(--light-primary-text)); + border-radius: 0.25rem; } } } diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index 088b732dc..a9cc587f7 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -3,13 +3,14 @@ import { HoldingDetailDialogParams } from '@ghostfolio/client/components/holding import { getCssVariable } from '@ghostfolio/common/helper'; import { InfoItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { ColorScheme } from '@ghostfolio/common/types'; -import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DOCUMENT, HostBinding, Inject, OnDestroy, @@ -24,6 +25,8 @@ import { Router } from '@angular/router'; import { DataSource } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { openOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @@ -62,25 +65,23 @@ export class AppComponent implements OnDestroy, OnInit { public hasTabs = false; public info: InfoItem; public pageTitle: string; - public routerLinkAbout = ['/' + $localize`:snake-case:about`]; - public routerLinkAboutChangelog = [ - '/' + $localize`:snake-case:about`, - 'changelog' - ]; - public routerLinkAboutLicense = [ - '/' + $localize`:snake-case:about`, - $localize`:snake-case:license` - ]; - public routerLinkAboutPrivacyPolicy = [ - '/' + $localize`:snake-case:about`, - $localize`:snake-case:privacy-policy` - ]; - public routerLinkFaq = ['/' + $localize`:snake-case:faq`]; - public routerLinkFeatures = ['/' + $localize`:snake-case:features`]; - public routerLinkMarkets = ['/' + $localize`:snake-case:markets`]; - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; - public routerLinkRegister = ['/' + $localize`:snake-case:register`]; - public routerLinkResources = ['/' + $localize`:snake-case:resources`]; + public routerLinkAbout = publicRoutes.about.routerLink; + public routerLinkAboutChangelog = + publicRoutes.about.subRoutes.changelog.routerLink; + public routerLinkAboutLicense = + publicRoutes.about.subRoutes.license.routerLink; + public routerLinkAboutPrivacyPolicy = + publicRoutes.about.subRoutes.privacyPolicy.routerLink; + public routerLinkAboutTermsOfService = + publicRoutes.about.subRoutes.termsOfService.routerLink; + public routerLinkBlog = publicRoutes.blog.routerLink; + public routerLinkFaq = publicRoutes.faq.routerLink; + public routerLinkFeatures = publicRoutes.features.routerLink; + public routerLinkMarkets = publicRoutes.markets.routerLink; + public routerLinkOpenStartup = publicRoutes.openStartup.routerLink; + public routerLinkPricing = publicRoutes.pricing.routerLink; + public routerLinkRegister = publicRoutes.register.routerLink; + public routerLinkResources = publicRoutes.resources.routerLink; public showFooter = false; public user: User; @@ -117,6 +118,8 @@ export class AppComponent implements OnDestroy, OnInit { }); } }); + + addIcons({ openOutline }); } public ngOnInit() { @@ -139,8 +142,8 @@ export class AppComponent implements OnDestroy, OnInit { ); this.hasPromotion = - !!this.info?.subscriptionOffers?.default?.coupon || - !!this.info?.subscriptionOffers?.default?.durationExtension; + !!this.info?.subscriptionOffer?.coupon || + !!this.info?.subscriptionOffer?.durationExtension; this.impersonationStorageService .onChangeHasImpersonation() @@ -159,12 +162,14 @@ export class AppComponent implements OnDestroy, OnInit { this.currentSubRoute = urlSegments[1]?.path; if ( - (this.currentRoute === 'home' && !this.currentSubRoute) || - (this.currentRoute === 'home' && - this.currentSubRoute === 'holdings') || - (this.currentRoute === 'portfolio' && !this.currentSubRoute) || - (this.currentRoute === 'zen' && !this.currentSubRoute) || - (this.currentRoute === 'zen' && this.currentSubRoute === 'holdings') + ((this.currentRoute === internalRoutes.home.path && + !this.currentSubRoute) || + (this.currentRoute === internalRoutes.home.path && + this.currentSubRoute === + internalRoutes.home.subRoutes.holdings.path) || + (this.currentRoute === internalRoutes.portfolio.path && + !this.currentSubRoute)) && + this.user?.settings?.viewMode !== 'ZEN' ) { this.hasPermissionToChangeDateRange = true; } else { @@ -172,14 +177,20 @@ export class AppComponent implements OnDestroy, OnInit { } if ( - (this.currentRoute === 'home' && - this.currentSubRoute === 'holdings') || - (this.currentRoute === 'portfolio' && !this.currentSubRoute) || - (this.currentRoute === 'portfolio' && - this.currentSubRoute === 'activities') || - (this.currentRoute === 'portfolio' && - this.currentSubRoute === 'allocations') || - (this.currentRoute === 'zen' && this.currentSubRoute === 'holdings') + (this.currentRoute === internalRoutes.home.path && + this.currentSubRoute === + internalRoutes.home.subRoutes.holdings.path) || + (this.currentRoute === internalRoutes.portfolio.path && + !this.currentSubRoute) || + (this.currentRoute === internalRoutes.portfolio.path && + this.currentSubRoute === + internalRoutes.portfolio.subRoutes.activities.path) || + (this.currentRoute === internalRoutes.portfolio.path && + this.currentSubRoute === + internalRoutes.portfolio.subRoutes.allocations.path) || + (this.currentRoute === internalRoutes.zen.path && + this.currentSubRoute === + internalRoutes.home.subRoutes.holdings.path) ) { this.hasPermissionToChangeFilters = true; } else { @@ -187,25 +198,25 @@ export class AppComponent implements OnDestroy, OnInit { } this.hasTabs = - (this.currentRoute === this.routerLinkAbout[0].slice(1) || - this.currentRoute === this.routerLinkFaq[0].slice(1) || - this.currentRoute === this.routerLinkResources[0].slice(1) || - this.currentRoute === 'account' || - this.currentRoute === 'admin' || - this.currentRoute === 'home' || - this.currentRoute === 'portfolio' || - this.currentRoute === 'zen') && + (this.currentRoute === publicRoutes.about.path || + this.currentRoute === publicRoutes.faq.path || + this.currentRoute === publicRoutes.resources.path || + this.currentRoute === internalRoutes.account.path || + this.currentRoute === internalRoutes.adminControl.path || + this.currentRoute === internalRoutes.home.path || + this.currentRoute === internalRoutes.portfolio.path || + this.currentRoute === internalRoutes.zen.path) && this.deviceType !== 'mobile'; this.showFooter = - (this.currentRoute === 'blog' || - this.currentRoute === this.routerLinkFeatures[0].slice(1) || - this.currentRoute === this.routerLinkMarkets[0].slice(1) || - this.currentRoute === 'open' || - this.currentRoute === 'p' || - this.currentRoute === this.routerLinkPricing[0].slice(1) || - this.currentRoute === this.routerLinkRegister[0].slice(1) || - this.currentRoute === 'start') && + (this.currentRoute === publicRoutes.blog.path || + this.currentRoute === publicRoutes.features.path || + this.currentRoute === publicRoutes.markets.path || + this.currentRoute === publicRoutes.openStartup.path || + this.currentRoute === publicRoutes.public.path || + this.currentRoute === publicRoutes.pricing.path || + this.currentRoute === publicRoutes.register.path || + this.currentRoute === publicRoutes.start.path) && this.deviceType !== 'mobile'; if (this.deviceType === 'mobile') { @@ -238,12 +249,8 @@ export class AppComponent implements OnDestroy, OnInit { this.canCreateAccount || !!this.user?.systemMessage; this.hasPromotion = - !!this.info?.subscriptionOffers?.[ - this.user?.subscription?.offer ?? 'default' - ]?.coupon || - !!this.info?.subscriptionOffers?.[ - this.user?.subscription?.offer ?? 'default' - ]?.durationExtension; + !!this.user?.subscription?.offer?.coupon || + !!this.user?.subscription?.offer?.durationExtension; this.initializeTheme(this.user?.settings.colorScheme); @@ -313,7 +320,11 @@ export class AppComponent implements OnDestroy, OnInit { colorScheme: this.user?.settings?.colorScheme, deviceType: this.deviceType, hasImpersonationId: this.hasImpersonationId, - hasPermissionToCreateOrder: + hasPermissionToAccessAdminControl: hasPermission( + this.user?.permissions, + permissions.accessAdminControl + ), + hasPermissionToCreateActivity: !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createOrder) && !this.user?.settings?.isRestrictedView, diff --git a/apps/client/src/app/app.module.ts b/apps/client/src/app/app.module.ts index 04602dd2e..ebc03e3ca 100644 --- a/apps/client/src/app/app.module.ts +++ b/apps/client/src/app/app.module.ts @@ -19,8 +19,10 @@ import { MatTooltipModule } from '@angular/material/tooltip'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { ServiceWorkerModule } from '@angular/service-worker'; -import { MarkdownModule } from 'ngx-markdown'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; +import { provideIonicAngular } from '@ionic/angular/standalone'; +import { IonIcon } from '@ionic/angular/standalone'; +import { provideMarkdown } from 'ngx-markdown'; +import { provideNgxSkeletonLoader } from 'ngx-skeleton-loader'; import { NgxStripeModule, STRIPE_PUBLISHABLE_KEY } from 'ngx-stripe'; import { environment } from '../environments/environment'; @@ -50,13 +52,12 @@ export function NgxStripeFactory(): string { GfLogoComponent, GfNotificationModule, GfSubscriptionInterstitialDialogModule, - MarkdownModule.forRoot(), + IonIcon, MatAutocompleteModule, MatChipsModule, MatNativeDateModule, MatSnackBarModule, MatTooltipModule, - NgxSkeletonLoaderModule, NgxStripeModule.forRoot(environment.stripePublicKey), ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, @@ -68,6 +69,9 @@ export function NgxStripeFactory(): string { httpResponseInterceptorProviders, LanguageService, provideHttpClient(withInterceptorsFromDi()), + provideIonicAngular(), + provideMarkdown(), + provideNgxSkeletonLoader(), { provide: DateAdapter, useClass: CustomDateAdapter, diff --git a/apps/client/src/app/components/access-table/access-table.component.html b/apps/client/src/app/components/access-table/access-table.component.html index 2a20e4631..44aee1644 100644 --- a/apps/client/src/app/components/access-table/access-table.component.html +++ b/apps/client/src/app/components/access-table/access-table.component.html @@ -66,7 +66,7 @@ @if (element.type === 'PUBLIC') { -
    diff --git a/apps/client/src/app/components/access-table/access-table.component.ts b/apps/client/src/app/components/access-table/access-table.component.ts index da8ceb094..c94f86df1 100644 --- a/apps/client/src/app/components/access-table/access-table.component.ts +++ b/apps/client/src/app/components/access-table/access-table.component.ts @@ -1,27 +1,51 @@ import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; -import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; import { Access, User } from '@ghostfolio/common/interfaces'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; -import { Clipboard } from '@angular/cdk/clipboard'; +import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, + CUSTOM_ELEMENTS_SCHEMA, EventEmitter, Input, OnChanges, Output } from '@angular/core'; -import { MatTableDataSource } from '@angular/material/table'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + ellipsisHorizontal, + linkOutline, + lockClosedOutline, + lockOpenOutline +} from 'ionicons/icons'; +import ms from 'ms'; @Component({ - selector: 'gf-access-table', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + ClipboardModule, + CommonModule, + IonIcon, + MatButtonModule, + MatMenuModule, + MatTableModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-access-table', templateUrl: './access-table.component.html', - styleUrls: ['./access-table.component.scss'], - standalone: false + styleUrls: ['./access-table.component.scss'] }) -export class AccessTableComponent implements OnChanges { +export class GfAccessTableComponent implements OnChanges { @Input() accesses: Access[]; @Input() showActions: boolean; @Input() user: User; @@ -34,8 +58,16 @@ export class AccessTableComponent implements OnChanges { public constructor( private clipboard: Clipboard, - private notificationService: NotificationService - ) {} + private notificationService: NotificationService, + private snackBar: MatSnackBar + ) { + addIcons({ + ellipsisHorizontal, + linkOutline, + lockClosedOutline, + lockOpenOutline + }); + } public ngOnChanges() { this.displayedColumns = ['alias', 'grantee', 'type', 'details']; @@ -50,13 +82,21 @@ export class AccessTableComponent implements OnChanges { } public getPublicUrl(aId: string): string { - const languageCode = this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE; + const languageCode = this.user.settings.language; - return `${this.baseUrl}/${languageCode}/p/${aId}`; + return `${this.baseUrl}/${languageCode}/${publicRoutes.public.path}/${aId}`; } - public onCopyToClipboard(aId: string): void { + public onCopyUrlToClipboard(aId: string): void { this.clipboard.copy(this.getPublicUrl(aId)); + + this.snackBar.open( + '✅ ' + $localize`Link has been copied to the clipboard`, + undefined, + { + duration: ms('3 seconds') + } + ); } public onDeleteAccess(aId: string) { diff --git a/apps/client/src/app/components/access-table/access-table.module.ts b/apps/client/src/app/components/access-table/access-table.module.ts deleted file mode 100644 index 4cbc7b580..000000000 --- a/apps/client/src/app/components/access-table/access-table.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ClipboardModule } from '@angular/cdk/clipboard'; -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatTableModule } from '@angular/material/table'; -import { RouterModule } from '@angular/router'; - -import { AccessTableComponent } from './access-table.component'; - -@NgModule({ - declarations: [AccessTableComponent], - exports: [AccessTableComponent], - imports: [ - ClipboardModule, - CommonModule, - MatButtonModule, - MatMenuModule, - MatTableModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfPortfolioAccessTableModule {} diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index c77d8cb4a..16cd468e8 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -10,6 +10,7 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { OrderWithAccount } from '@ghostfolio/common/types'; import { @@ -26,6 +27,12 @@ import { MatTableDataSource } from '@angular/material/table'; import { Router } from '@angular/router'; import { Big } from 'big.js'; import { format, parseISO } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { + cashOutline, + swapVerticalOutline, + walletOutline +} from 'ionicons/icons'; import { isNumber } from 'lodash'; import { forkJoin, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -85,6 +92,8 @@ export class AccountDetailDialog implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); } }); + + addIcons({ cashOutline, swapVerticalOutline, walletOutline }); } public ngOnInit() { @@ -92,9 +101,12 @@ export class AccountDetailDialog implements OnDestroy, OnInit { } public onCloneActivity(aActivity: Activity) { - this.router.navigate(['/portfolio', 'activities'], { - queryParams: { activityId: aActivity.id, createDialog: true } - }); + this.router.navigate( + internalRoutes.portfolio.subRoutes.activities.routerLink, + { + queryParams: { activityId: aActivity.id, createDialog: true } + } + ); this.dialogRef.close(); } @@ -151,9 +163,12 @@ export class AccountDetailDialog implements OnDestroy, OnInit { } public onUpdateActivity(aActivity: Activity) { - this.router.navigate(['/portfolio', 'activities'], { - queryParams: { activityId: aActivity.id, editDialog: true } - }); + this.router.navigate( + internalRoutes.portfolio.subRoutes.activities.routerLink, + { + queryParams: { activityId: aActivity.id, editDialog: true } + } + ); this.dialogRef.close(); } @@ -167,7 +182,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit { balance, currency, name, - Platform, + platform, transactionCount, value, valueInBaseCurrency @@ -182,7 +197,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit { } this.name = name; - this.platformName = Platform?.name ?? '-'; + this.platformName = platform?.name ?? '-'; this.transactionCount = transactionCount; this.valueInBaseCurrency = valueInBaseCurrency; diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index 8459037f6..45d88fc78 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -69,7 +69,7 @@ @@ -105,7 +105,7 @@ [locale]="user?.settings?.locale" [showActions]=" !data.hasImpersonationId && - data.hasPermissionToCreateOrder && + data.hasPermissionToCreateActivity && user?.settings?.isExperimentalFeatures && !user?.settings?.isRestrictedView " diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts index e404aaad1..46c4cb40f 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts @@ -11,6 +11,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule } from '@angular/material/dialog'; import { MatTabsModule } from '@angular/material/tabs'; +import { IonIcon } from '@ionic/angular/standalone'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { AccountDetailDialog } from './account-detail-dialog.component'; @@ -26,6 +27,7 @@ import { AccountDetailDialog } from './account-detail-dialog.component'; GfHoldingsTableComponent, GfInvestmentChartModule, GfValueComponent, + IonIcon, MatButtonModule, MatDialogModule, MatTabsModule, diff --git a/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts index 9ad6a5ba4..01c84e956 100644 --- a/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts @@ -2,5 +2,5 @@ export interface AccountDetailDialogParams { accountId: string; deviceType: string; hasImpersonationId: boolean; - hasPermissionToCreateOrder: boolean; + hasPermissionToCreateActivity: boolean; } diff --git a/apps/client/src/app/components/accounts-table/accounts-table.component.html b/apps/client/src/app/components/accounts-table/accounts-table.component.html index ecb51fc29..609c76ee1 100644 --- a/apps/client/src/app/components/accounts-table/accounts-table.component.html +++ b/apps/client/src/app/components/accounts-table/accounts-table.component.html @@ -43,11 +43,11 @@ Name - @if (element.Platform?.url) { - } {{ element.name }} @@ -81,7 +81,7 @@ *matHeaderCellDef class="d-none d-lg-table-cell px-1" mat-header-cell - mat-sort-header="Platform.name" + mat-sort-header="platform.name" > Platform @@ -91,14 +91,14 @@ mat-cell >
    - @if (element.Platform?.url) { - } - {{ element.Platform?.name }} + {{ element.platform?.name }}
    + + + Allocation + + + + + + +
    - + diff --git a/apps/client/src/app/components/accounts-table/accounts-table.component.ts b/apps/client/src/app/components/accounts-table/accounts-table.component.ts index a130e7a27..a7ce6e488 100644 --- a/apps/client/src/app/components/accounts-table/accounts-table.component.ts +++ b/apps/client/src/app/components/accounts-table/accounts-table.component.ts @@ -1,7 +1,10 @@ import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { getLocale } from '@ghostfolio/common/helper'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -12,27 +15,52 @@ import { Output, ViewChild } from '@angular/core'; -import { MatSort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; -import { Router } from '@angular/router'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { Account as AccountModel } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { + arrowRedoOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + eyeOffOutline, + trashOutline +} from 'ionicons/icons'; import { get } from 'lodash'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject, Subscription } from 'rxjs'; @Component({ - selector: 'gf-accounts-table', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './accounts-table.component.html', + imports: [ + CommonModule, + GfEntityLogoComponent, + GfValueComponent, + IonIcon, + MatButtonModule, + MatMenuModule, + MatSortModule, + MatTableModule, + NgxSkeletonLoaderModule, + RouterModule + ], + selector: 'gf-accounts-table', styleUrls: ['./accounts-table.component.scss'], - standalone: false + templateUrl: './accounts-table.component.html' }) -export class AccountsTableComponent implements OnChanges, OnDestroy { +export class GfAccountsTableComponent implements OnChanges, OnDestroy { @Input() accounts: AccountModel[]; @Input() baseCurrency: string; @Input() deviceType: string; @Input() hasPermissionToOpenDetails = true; @Input() locale = getLocale(); @Input() showActions: boolean; + @Input() showAllocationInPercentage: boolean; @Input() showBalance = true; @Input() showFooter = true; @Input() showTransactions = true; @@ -58,7 +86,16 @@ export class AccountsTableComponent implements OnChanges, OnDestroy { public constructor( private notificationService: NotificationService, private router: Router - ) {} + ) { + addIcons({ + arrowRedoOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + eyeOffOutline, + trashOutline + }); + } public ngOnChanges() { this.displayedColumns = ['status', 'account', 'platform']; @@ -81,6 +118,10 @@ export class AccountsTableComponent implements OnChanges, OnDestroy { this.displayedColumns.push('valueInBaseCurrency'); } + if (this.showAllocationInPercentage) { + this.displayedColumns.push('allocation'); + } + this.displayedColumns.push('comment'); if (this.showActions) { diff --git a/apps/client/src/app/components/accounts-table/accounts-table.module.ts b/apps/client/src/app/components/accounts-table/accounts-table.module.ts deleted file mode 100644 index 879ca13ea..000000000 --- a/apps/client/src/app/components/accounts-table/accounts-table.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSortModule } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; -import { RouterModule } from '@angular/router'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { AccountsTableComponent } from './accounts-table.component'; - -@NgModule({ - declarations: [AccountsTableComponent], - exports: [AccountsTableComponent], - imports: [ - CommonModule, - GfAssetProfileIconComponent, - GfValueComponent, - MatButtonModule, - MatMenuModule, - MatSortModule, - MatTableModule, - NgxSkeletonLoaderModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAccountsTableModule {} diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts index 17b7f54da..d28749b9c 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts @@ -10,6 +10,7 @@ import { import { getDateWithTimeFormatString } from '@ghostfolio/common/helper'; import { AdminJobs, User } from '@ghostfolio/common/interfaces'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -17,20 +18,54 @@ import { OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { MatTableDataSource } from '@angular/material/table'; +import { + FormBuilder, + FormGroup, + FormsModule, + ReactiveFormsModule +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { IonIcon } from '@ionic/angular/standalone'; import { JobStatus } from 'bull'; +import { addIcons } from 'ionicons'; +import { + alertCircleOutline, + cafeOutline, + checkmarkCircleOutline, + chevronDownCircleOutline, + chevronUpCircleOutline, + ellipsisHorizontal, + ellipsisVertical, + pauseOutline, + playOutline, + removeCircleOutline, + timeOutline +} from 'ionicons/icons'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + FormsModule, + IonIcon, + MatButtonModule, + MatMenuModule, + MatSelectModule, + MatTableModule, + NgxSkeletonLoaderModule, + ReactiveFormsModule + ], selector: 'gf-admin-jobs', styleUrls: ['./admin-jobs.scss'], - templateUrl: './admin-jobs.html', - standalone: false + templateUrl: './admin-jobs.html' }) -export class AdminJobsComponent implements OnDestroy, OnInit { +export class GfAdminJobsComponent implements OnDestroy, OnInit { public DATA_GATHERING_QUEUE_PRIORITY_LOW = DATA_GATHERING_QUEUE_PRIORITY_LOW; public DATA_GATHERING_QUEUE_PRIORITY_HIGH = DATA_GATHERING_QUEUE_PRIORITY_HIGH; @@ -76,6 +111,20 @@ export class AdminJobsComponent implements OnDestroy, OnInit { ); } }); + + addIcons({ + alertCircleOutline, + cafeOutline, + checkmarkCircleOutline, + chevronDownCircleOutline, + chevronUpCircleOutline, + ellipsisHorizontal, + ellipsisVertical, + pauseOutline, + playOutline, + removeCircleOutline, + timeOutline + }); } public ngOnInit() { diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.module.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.module.ts deleted file mode 100644 index cca66a04a..000000000 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSelectModule } from '@angular/material/select'; -import { MatTableModule } from '@angular/material/table'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { AdminJobsComponent } from './admin-jobs.component'; - -@NgModule({ - declarations: [AdminJobsComponent], - imports: [ - CommonModule, - FormsModule, - MatButtonModule, - MatMenuModule, - MatSelectModule, - MatTableModule, - NgxSkeletonLoaderModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAdminJobsModule {} diff --git a/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts b/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts index 30ef457d2..6a809a10f 100644 --- a/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts +++ b/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts @@ -1,3 +1,4 @@ +import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -14,9 +15,13 @@ import { } from '@ghostfolio/common/interfaces'; import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; import { translate } from '@ghostfolio/ui/i18n'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { SelectionModel } from '@angular/cdk/collections'; +import { CommonModule } from '@angular/common'; import { AfterViewInit, ChangeDetectionStrategy, @@ -26,48 +31,82 @@ import { OnInit, ViewChild } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; -import { MatSort, Sort, SortDirection } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; -import { ActivatedRoute, Router } from '@angular/router'; +import { MatMenuModule } from '@angular/material/menu'; +import { + MatPaginator, + MatPaginatorModule, + PageEvent +} from '@angular/material/paginator'; +import { + MatSort, + MatSortModule, + Sort, + SortDirection +} from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { AssetSubClass, DataSource, SymbolProfile } from '@prisma/client'; import { isUUID } from 'class-validator'; +import { addIcons } from 'ionicons'; +import { + addOutline, + banOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + ellipsisVertical, + trashOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators'; import { AdminMarketDataService } from './admin-market-data.service'; -import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component'; +import { GfAssetProfileDialogComponent } from './asset-profile-dialog/asset-profile-dialog.component'; import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces'; -import { CreateAssetProfileDialog } from './create-asset-profile-dialog/create-asset-profile-dialog.component'; +import { GfCreateAssetProfileDialogComponent } from './create-asset-profile-dialog/create-asset-profile-dialog.component'; import { CreateAssetProfileDialogParams } from './create-asset-profile-dialog/interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'has-fab' }, + imports: [ + CommonModule, + GfActivitiesFilterComponent, + GfPremiumIndicatorComponent, + GfSymbolModule, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCheckboxModule, + MatMenuModule, + MatPaginatorModule, + MatSortModule, + MatTableModule, + NgxSkeletonLoaderModule, + RouterModule + ], + providers: [AdminMarketDataService], selector: 'gf-admin-market-data', styleUrls: ['./admin-market-data.scss'], - templateUrl: './admin-market-data.html', - standalone: false + templateUrl: './admin-market-data.html' }) -export class AdminMarketDataComponent +export class GfAdminMarketDataComponent implements AfterViewInit, OnDestroy, OnInit { @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; public activeFilters: Filter[] = []; - public allFilters: Filter[] = [ - AssetSubClass.BOND, - AssetSubClass.COMMODITY, - AssetSubClass.CRYPTOCURRENCY, - AssetSubClass.ETF, - AssetSubClass.MUTUALFUND, - AssetSubClass.PRECIOUS_METAL, - AssetSubClass.PRIVATE_EQUITY, - AssetSubClass.STOCK - ] + public allFilters: Filter[] = Object.keys(AssetSubClass) + .filter((assetSubClass) => { + return assetSubClass !== 'CASH'; + }) .map((assetSubClass) => { return { id: assetSubClass.toString(), @@ -137,6 +176,7 @@ export class AdminMarketDataComponent ); this.displayedColumns = [ + 'status', 'select', 'nameWithSymbol', 'dataSource', @@ -193,6 +233,16 @@ export class AdminMarketDataComponent this.loadData(); }); + + addIcons({ + addOutline, + banOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + ellipsisVertical, + trashOutline + }); } public ngAfterViewInit() { @@ -373,7 +423,7 @@ export class AdminMarketDataComponent .subscribe((user) => { this.user = user; - const dialogRef = this.dialog.open(AssetProfileDialog, { + const dialogRef = this.dialog.open(GfAssetProfileDialogComponent, { autoFocus: false, data: { dataSource, @@ -389,9 +439,15 @@ export class AdminMarketDataComponent dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.router.navigate(['.'], { relativeTo: this.route }); - }); + .subscribe( + (newAssetProfileIdentifier: AssetProfileIdentifier | undefined) => { + if (newAssetProfileIdentifier) { + this.onOpenAssetProfileDialog(newAssetProfileIdentifier); + } else { + this.router.navigate(['.'], { relativeTo: this.route }); + } + } + ); }); } @@ -402,14 +458,17 @@ export class AdminMarketDataComponent .subscribe((user) => { this.user = user; - const dialogRef = this.dialog.open(CreateAssetProfileDialog, { - autoFocus: false, - data: { - deviceType: this.deviceType, - locale: this.user?.settings?.locale - } as CreateAssetProfileDialogParams, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - }); + const dialogRef = this.dialog.open( + GfCreateAssetProfileDialogComponent, + { + autoFocus: false, + data: { + deviceType: this.deviceType, + locale: this.user?.settings?.locale + } as CreateAssetProfileDialogParams, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + } + ); dialogRef .afterClosed() diff --git a/apps/client/src/app/components/admin-market-data/admin-market-data.html b/apps/client/src/app/components/admin-market-data/admin-market-data.html index de5707d02..bfa6d550e 100644 --- a/apps/client/src/app/components/admin-market-data/admin-market-data.html +++ b/apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -20,6 +20,34 @@ matSortDirection="asc" [dataSource]="dataSource" > + + + + @if (!element.isActive) { +
    + +
    + } + + +
    + @@ -27,7 +55,8 @@ adminMarketDataService.hasPermissionToDeleteAssetProfile({ activitiesCount: element.activitiesCount, isBenchmark: element.isBenchmark, - symbol: element.symbol + symbol: element.symbol, + watchedByCount: element.watchedByCount }) ) { - + + + + + } @else { +
    + Symbol +
    +
    + Data Source +
    + +
    +
    + }
    CurrencyAsset Class
    @@ -144,8 +220,8 @@ Asset Sub Class @@ -183,185 +259,304 @@
    Sectors
    Countries
    } } -
    - - Name - - -
    - @if (assetProfile?.dataSource === 'MANUAL') { +
    - Currency - + Name +
    - } -
    - - Asset Class - - - @for (assetClass of assetClasses; track assetClass) { - {{ - assetClass.label - }} - } - - -
    -
    - - Asset Sub Class - - - @for (assetSubClass of assetSubClasses; track assetSubClass) { - {{ - assetSubClass.label - }} - } - - -
    -
    -
    - Benchmark + @if (assetProfile?.dataSource === 'MANUAL') { +
    + + Currency + + +
    + } +
    + + Asset Class + + + @for ( + assetClassOption of assetClassOptions; + track assetClassOption.id + ) { + {{ + assetClassOption.label + }} + } + +
    -
    -
    - - Symbol Mapping - - -
    - @if (assetProfile?.dataSource === 'MANUAL') { -
    - - Scraper Configuration -
    - - -
    +
    + + Asset Sub Class + + + @for ( + assetSubClassOption of assetSubClassOptions; + track assetSubClassOption.id + ) { + {{ + assetSubClassOption.label + }} + } +
    -
    +
    +
    + Benchmark +
    +
    +
    - Sectors + Symbol Mapping
    + @if (assetProfile?.dataSource === 'MANUAL') { +
    + + + + Scraper Configuration + +
    +
    + + Default Market Price + + +
    +
    + + HTTP Request Headers + + +
    +
    + + Locale + + +
    +
    + + Mode + + @for (modeValue of modeValues; track modeValue) { + {{ + modeValue.viewValue + }} + } + + +
    +
    + + + Selector* + + + +
    +
    + + + Url* + + + +
    +
    + +
    +
    +
    +
    +
    + } + @if (assetProfile?.dataSource === 'MANUAL') { +
    + + Sectors + + +
    +
    + + Countries + + +
    + }
    + + Url + + @if (assetProfileForm.get('url').value) { + + } + +
    +
    - Countries + Note
    - } -
    - - Url - - @if (assetProfileForm.get('url').value) { - - } - -
    -
    - - Note - - -
    +
    -
    +
    +
    + + Data Gathering + +
    - +
    diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts deleted file mode 100644 index d5e14ecb5..000000000 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { AdminMarketDataService } from '@ghostfolio/client/components/admin-market-data/admin-market-data.service'; -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector'; -import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor'; -import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; -import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { TextFieldModule } from '@angular/cdk/text-field'; -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatInputModule } from '@angular/material/input'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSelectModule } from '@angular/material/select'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; - -import { AssetProfileDialog } from './asset-profile-dialog.component'; - -@NgModule({ - declarations: [AssetProfileDialog], - imports: [ - CommonModule, - FormsModule, - GfAssetProfileIconComponent, - GfCurrencySelectorComponent, - GfHistoricalMarketDataEditorComponent, - GfLineChartComponent, - GfPortfolioProportionChartComponent, - GfValueComponent, - MatButtonModule, - MatCheckboxModule, - MatDialogModule, - MatInputModule, - MatMenuModule, - MatSelectModule, - MatSnackBarModule, - ReactiveFormsModule, - TextFieldModule - ], - providers: [AdminMarketDataService], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAssetProfileDialogModule {} diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/interfaces/interfaces.ts index 6a966b427..0de94c1cb 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/interfaces/interfaces.ts @@ -1,6 +1,11 @@ import { ColorScheme } from '@ghostfolio/common/types'; -import { DataSource } from '@prisma/client'; +import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; + +export interface AssetClassSelectorOption { + id: AssetClass | AssetSubClass; + label: string; +} export interface AssetProfileDialogParams { colorScheme: ColorScheme; diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts index fa5e33f10..5be0fd478 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts @@ -1,6 +1,10 @@ import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; -import { PROPERTY_CURRENCIES } from '@ghostfolio/common/config'; +import { + ghostfolioPrefix, + PROPERTY_CURRENCIES +} from '@ghostfolio/common/config'; +import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; import { ChangeDetectionStrategy, @@ -14,11 +18,18 @@ import { FormBuilder, FormControl, FormGroup, + FormsModule, + ReactiveFormsModule, ValidationErrors, + ValidatorFn, Validators } from '@angular/forms'; -import { MatDialogRef } from '@angular/material/dialog'; -import { uniq } from 'lodash'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatRadioModule } from '@angular/material/radio'; +import { isISO4217CurrencyCode } from 'class-validator'; import { Subject, takeUntil } from 'rxjs'; import { CreateAssetProfileDialogMode } from './interfaces/interfaces'; @@ -26,12 +37,21 @@ import { CreateAssetProfileDialogMode } from './interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, + imports: [ + FormsModule, + GfSymbolAutocompleteComponent, + MatButtonModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + MatRadioModule, + ReactiveFormsModule + ], selector: 'gf-create-asset-profile-dialog', styleUrls: ['./create-asset-profile-dialog.component.scss'], - templateUrl: 'create-asset-profile-dialog.html', - standalone: false + templateUrl: 'create-asset-profile-dialog.html' }) -export class CreateAssetProfileDialog implements OnInit, OnDestroy { +export class GfCreateAssetProfileDialogComponent implements OnInit, OnDestroy { public createAssetProfileForm: FormGroup; public mode: CreateAssetProfileDialogMode; @@ -42,7 +62,7 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { public readonly adminService: AdminService, private readonly changeDetectorRef: ChangeDetectorRef, private readonly dataService: DataService, - public readonly dialogRef: MatDialogRef, + public readonly dialogRef: MatDialogRef, public readonly formBuilder: FormBuilder ) {} @@ -52,11 +72,11 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { this.createAssetProfileForm = this.formBuilder.group( { addCurrency: new FormControl(null, [ - Validators.maxLength(3), - Validators.minLength(3), + this.iso4217CurrencyCodeValidator() + ]), + addSymbol: new FormControl(`${ghostfolioPrefix}_`, [ Validators.required ]), - addSymbol: new FormControl(null, [Validators.required]), searchSymbol: new FormControl(null, [Validators.required]) }, { @@ -83,11 +103,13 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { symbol: this.createAssetProfileForm.get('searchSymbol').value.symbol }); } else if (this.mode === 'currency') { - const currency = this.createAssetProfileForm - .get('addCurrency') - .value.toUpperCase(); + const currency = ( + this.createAssetProfileForm.get('addCurrency').value as string + ).toUpperCase(); - const currencies = uniq([...this.customCurrencies, currency]); + const currencies = Array.from( + new Set([...this.customCurrencies, currency]) + ).sort(); this.dataService .putAdminSetting(PROPERTY_CURRENCIES, { @@ -109,10 +131,7 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { const addCurrencyFormControl = this.createAssetProfileForm.get('addCurrency'); - if ( - addCurrencyFormControl.hasError('maxlength') || - addCurrencyFormControl.hasError('minlength') - ) { + if (addCurrencyFormControl.hasError('invalidCurrency')) { return true; } @@ -161,4 +180,14 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { this.changeDetectorRef.markForCheck(); }); } + + private iso4217CurrencyCodeValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (!isISO4217CurrencyCode(control.value?.toUpperCase())) { + return { invalidCurrency: true }; + } + + return null; + }; + } } diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts deleted file mode 100644 index 24cc90dbe..000000000 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatRadioModule } from '@angular/material/radio'; - -import { CreateAssetProfileDialog } from './create-asset-profile-dialog.component'; - -@NgModule({ - declarations: [CreateAssetProfileDialog], - imports: [ - CommonModule, - FormsModule, - GfSymbolAutocompleteComponent, - MatDialogModule, - MatButtonModule, - MatFormFieldModule, - MatInputModule, - MatRadioModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfCreateAssetProfileDialogModule {} diff --git a/apps/client/src/app/components/admin-overview/admin-overview.component.ts b/apps/client/src/app/components/admin-overview/admin-overview.component.ts index d217f871d..5d1138be8 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.component.ts +++ b/apps/client/src/app/components/admin-overview/admin-overview.component.ts @@ -6,13 +6,13 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { PROPERTY_COUPONS, - PROPERTY_CURRENCIES, PROPERTY_IS_DATA_GATHERING_ENABLED, PROPERTY_IS_READ_ONLY_MODE, PROPERTY_IS_USER_SIGNUP_ENABLED, PROPERTY_SYSTEM_MESSAGE, ghostfolioPrefix } from '@ghostfolio/common/config'; +import { getDateFnsLocale } from '@ghostfolio/common/helper'; import { Coupon, InfoItem, @@ -20,32 +20,65 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { CommonModule } from '@angular/common'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { MatSlideToggleChange } from '@angular/material/slide-toggle'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSelectModule } from '@angular/material/select'; import { + MatSlideToggleChange, + MatSlideToggleModule +} from '@angular/material/slide-toggle'; +import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { + addMilliseconds, differenceInSeconds, formatDistanceToNowStrict, parseISO } from 'date-fns'; -import { uniq } from 'lodash'; -import { StringValue } from 'ms'; +import { addIcons } from 'ionicons'; +import { + closeCircleOutline, + ellipsisHorizontal, + informationCircleOutline, + syncOutline, + trashOutline +} from 'ionicons/icons'; +import ms, { StringValue } from 'ms'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + CommonModule, + FormsModule, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCardModule, + MatMenuModule, + MatSelectModule, + MatSnackBarModule, + MatSlideToggleModule, + ReactiveFormsModule, + RouterModule + ], selector: 'gf-admin-overview', styleUrls: ['./admin-overview.scss'], - templateUrl: './admin-overview.html', - standalone: false + templateUrl: './admin-overview.html' }) -export class AdminOverviewComponent implements OnDestroy, OnInit { +export class GfAdminOverviewComponent implements OnDestroy, OnInit { public couponDuration: StringValue = '14 days'; public coupons: Coupon[]; - public customCurrencies: string[]; - public exchangeRates: { label1: string; label2: string; value: number }[]; public hasPermissionForSubscription: boolean; public hasPermissionForSystemMessage: boolean; + public hasPermissionToSyncDemoUserAccount: boolean; public hasPermissionToToggleReadOnlyMode: boolean; public info: InfoItem; public isDataGatheringEnabled: boolean; @@ -64,6 +97,7 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, private notificationService: NotificationService, + private snackBar: MatSnackBar, private userService: UserService ) { this.info = this.dataService.fetchInfo(); @@ -84,12 +118,25 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { permissions.enableSystemMessage ); + this.hasPermissionToSyncDemoUserAccount = hasPermission( + this.user.permissions, + permissions.syncDemoUserAccount + ); + this.hasPermissionToToggleReadOnlyMode = hasPermission( this.user.permissions, permissions.toggleReadOnlyMode ); } }); + + addIcons({ + closeCircleOutline, + ellipsisHorizontal, + informationCircleOutline, + syncOutline, + trashOutline + }); } public ngOnInit() { @@ -111,6 +158,15 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { return ''; } + public formatStringValue(aStringValue: StringValue) { + return formatDistanceToNowStrict( + addMilliseconds(new Date(), ms(aStringValue)), + { + locale: getDateFnsLocale(this.user?.settings?.language) + } + ); + } + public onAddCoupon() { const coupons = [ ...this.coupons, @@ -122,24 +178,6 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { this.putAdminSetting({ key: PROPERTY_COUPONS, value: coupons }); } - public onAddCurrency() { - const currency = prompt($localize`Please add a currency:`); - - if (currency) { - if (currency.length === 3) { - const currencies = uniq([ - ...this.customCurrencies, - currency.toUpperCase() - ]); - this.putAdminSetting({ key: PROPERTY_CURRENCIES, value: currencies }); - } else { - this.notificationService.alert({ - title: $localize`${currency} is an invalid currency!` - }); - } - } - } - public onChangeCouponDuration(aCouponDuration: StringValue) { this.couponDuration = aCouponDuration; } @@ -157,19 +195,6 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { }); } - public onDeleteCurrency(aCurrency: string) { - this.notificationService.confirm({ - confirmFn: () => { - const currencies = this.customCurrencies.filter((currency) => { - return currency !== aCurrency; - }); - this.putAdminSetting({ key: PROPERTY_CURRENCIES, value: currencies }); - }, - confirmType: ConfirmationDialogType.Warn, - title: $localize`Do you really want to delete this currency?` - }); - } - public onDeleteSystemMessage() { this.notificationService.confirm({ confirmFn: () => { @@ -241,6 +266,21 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { } } + public onSyncDemoUserAccount() { + this.adminService + .syncDemoUserAccount() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.snackBar.open( + '✅ ' + $localize`Demo user account has been synced.`, + undefined, + { + duration: ms('3 seconds') + } + ); + }); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); @@ -250,25 +290,17 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { this.adminService .fetchAdminData() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe( - ({ exchangeRates, settings, transactionCount, userCount, version }) => { - this.coupons = (settings[PROPERTY_COUPONS] as Coupon[]) ?? []; - this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[]; - this.exchangeRates = exchangeRates; - this.isDataGatheringEnabled = - settings[PROPERTY_IS_DATA_GATHERING_ENABLED] === false - ? false - : true; - this.systemMessage = settings[ - PROPERTY_SYSTEM_MESSAGE - ] as SystemMessage; - this.transactionCount = transactionCount; - this.userCount = userCount; - this.version = version; - - this.changeDetectorRef.markForCheck(); - } - ); + .subscribe(({ settings, transactionCount, userCount, version }) => { + this.coupons = (settings[PROPERTY_COUPONS] as Coupon[]) ?? []; + this.isDataGatheringEnabled = + settings[PROPERTY_IS_DATA_GATHERING_ENABLED] === false ? false : true; + this.systemMessage = settings[PROPERTY_SYSTEM_MESSAGE] as SystemMessage; + this.transactionCount = transactionCount; + this.userCount = userCount; + this.version = version; + + this.changeDetectorRef.markForCheck(); + }); } private generateCouponCode(aLength: number) { diff --git a/apps/client/src/app/components/admin-overview/admin-overview.html b/apps/client/src/app/components/admin-overview/admin-overview.html index ba8545d16..c47387f37 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.html +++ b/apps/client/src/app/components/admin-overview/admin-overview.html @@ -30,83 +30,6 @@ }
    -
    -
    Exchange Rates
    -
    - - @for (exchangeRate of exchangeRates; track exchangeRate) { - - - - - - - - - } -
    - - {{ exchangeRate.label1 }}= - - {{ exchangeRate.label2 }} - - - - - - Edit - - - @if (customCurrencies.includes(exchangeRate.label2)) { -
    - - } -
    -
    -
    - -
    -
    -
    User Signup
    @@ -182,7 +105,9 @@ @for (coupon of coupons; track coupon) { {{ coupon.code }} - {{ coupon.duration }} + + {{ formatStringValue(coupon.duration) }} + +
    + @if (hasPermissionToSyncDemoUserAccount) { + + } + +
    diff --git a/apps/client/src/app/components/admin-overview/admin-overview.module.ts b/apps/client/src/app/components/admin-overview/admin-overview.module.ts deleted file mode 100644 index da49eb858..000000000 --- a/apps/client/src/app/components/admin-overview/admin-overview.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { CacheService } from '@ghostfolio/client/services/cache.service'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSelectModule } from '@angular/material/select'; -import { MatSlideToggleModule } from '@angular/material/slide-toggle'; -import { RouterModule } from '@angular/router'; - -import { AdminOverviewComponent } from './admin-overview.component'; - -@NgModule({ - declarations: [AdminOverviewComponent], - exports: [], - imports: [ - CommonModule, - FormsModule, - GfValueComponent, - MatButtonModule, - MatCardModule, - MatMenuModule, - MatSelectModule, - MatSlideToggleModule, - ReactiveFormsModule, - RouterModule - ], - providers: [CacheService], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAdminOverviewModule {} diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.html b/apps/client/src/app/components/admin-platform/admin-platform.component.html index c71594e45..9e38d5de7 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.html +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1,115 +1,94 @@ -
    -
    -
    - - - - - + +
    - Name - - @if (element.url) { - - } - {{ element.name }} -
    + + + - - - - + + + + - - - - + + + + - - - - + + + + - - -
    + Name + + @if (element.url) { + + } + {{ element.name }} + - Url - - {{ element.url }} - + Url + + {{ element.url }} + - Accounts - - {{ element.accountCount }} - + Accounts + + {{ element.accountCount }} + - - - -
    - -
    -
    + + + +
    + +
    +
    -
    -
    -
    + + + diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.ts b/apps/client/src/app/components/admin-platform/admin-platform.component.ts index 1f84c2b8c..845c7f375 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.ts +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.ts @@ -5,6 +5,7 @@ import { NotificationService } from '@ghostfolio/client/core/notification/notifi import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { ChangeDetectionStrategy, @@ -14,25 +15,42 @@ import { OnInit, ViewChild } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; -import { MatSort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; -import { ActivatedRoute, Router } from '@angular/router'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { Platform } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { + createOutline, + ellipsisHorizontal, + trashOutline +} from 'ionicons/icons'; import { get } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; -import { CreateOrUpdatePlatformDialog } from './create-or-update-platform-dialog/create-or-update-platform-dialog.component'; +import { GfCreateOrUpdatePlatformDialogComponent } from './create-or-update-platform-dialog/create-or-update-platform-dialog.component'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + GfEntityLogoComponent, + IonIcon, + MatButtonModule, + MatMenuModule, + MatSortModule, + MatTableModule, + RouterModule + ], selector: 'gf-admin-platform', styleUrls: ['./admin-platform.component.scss'], - templateUrl: './admin-platform.component.html', - standalone: false + templateUrl: './admin-platform.component.html' }) -export class AdminPlatformComponent implements OnInit, OnDestroy { +export class GfAdminPlatformComponent implements OnInit, OnDestroy { @ViewChild(MatSort) sort: MatSort; public dataSource = new MatTableDataSource(); @@ -70,6 +88,8 @@ export class AdminPlatformComponent implements OnInit, OnDestroy { } } }); + + addIcons({ createOutline, ellipsisHorizontal, trashOutline }); } public ngOnInit() { @@ -133,16 +153,19 @@ export class AdminPlatformComponent implements OnInit, OnDestroy { } private openCreatePlatformDialog() { - const dialogRef = this.dialog.open(CreateOrUpdatePlatformDialog, { - data: { - platform: { - name: null, - url: null - } - }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - }); + const dialogRef = this.dialog.open( + GfCreateOrUpdatePlatformDialogComponent, + { + data: { + platform: { + name: null, + url: null + } + }, + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + } + ); dialogRef .afterClosed() @@ -169,17 +192,20 @@ export class AdminPlatformComponent implements OnInit, OnDestroy { } private openUpdatePlatformDialog({ id, name, url }) { - const dialogRef = this.dialog.open(CreateOrUpdatePlatformDialog, { - data: { - platform: { - id, - name, - url - } - }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - }); + const dialogRef = this.dialog.open( + GfCreateOrUpdatePlatformDialogComponent, + { + data: { + platform: { + id, + name, + url + } + }, + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + } + ); dialogRef .afterClosed() diff --git a/apps/client/src/app/components/admin-platform/admin-platform.module.ts b/apps/client/src/app/components/admin-platform/admin-platform.module.ts deleted file mode 100644 index e98d53988..000000000 --- a/apps/client/src/app/components/admin-platform/admin-platform.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSortModule } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; -import { RouterModule } from '@angular/router'; - -import { AdminPlatformComponent } from './admin-platform.component'; -import { GfCreateOrUpdatePlatformDialogModule } from './create-or-update-platform-dialog/create-or-update-platform-dialog.module'; - -@NgModule({ - declarations: [AdminPlatformComponent], - exports: [AdminPlatformComponent], - imports: [ - CommonModule, - GfAssetProfileIconComponent, - GfCreateOrUpdatePlatformDialogModule, - MatButtonModule, - MatMenuModule, - MatSortModule, - MatTableModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAdminPlatformModule {} diff --git a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts index e29a4e05f..48a6ca432 100644 --- a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts +++ b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts @@ -1,6 +1,7 @@ import { CreatePlatformDto } from '@ghostfolio/api/app/platform/create-platform.dto'; import { UpdatePlatformDto } from '@ghostfolio/api/app/platform/update-platform.dto'; import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { ChangeDetectionStrategy, @@ -8,8 +9,21 @@ import { Inject, OnDestroy } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { + FormBuilder, + FormGroup, + FormsModule, + ReactiveFormsModule, + Validators +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; import { Subject } from 'rxjs'; import { CreateOrUpdatePlatformDialogParams } from './interfaces/interfaces'; @@ -17,24 +31,32 @@ import { CreateOrUpdatePlatformDialogParams } from './interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, + imports: [ + FormsModule, + GfEntityLogoComponent, + MatButtonModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule + ], selector: 'gf-create-or-update-platform-dialog', styleUrls: ['./create-or-update-platform-dialog.scss'], - templateUrl: 'create-or-update-platform-dialog.html', - standalone: false + templateUrl: 'create-or-update-platform-dialog.html' }) -export class CreateOrUpdatePlatformDialog implements OnDestroy { +export class GfCreateOrUpdatePlatformDialogComponent implements OnDestroy { public platformForm: FormGroup; private unsubscribeSubject = new Subject(); public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdatePlatformDialogParams, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private formBuilder: FormBuilder ) { this.platformForm = this.formBuilder.group({ name: [this.data.platform.name, Validators.required], - url: [this.data.platform.url, Validators.required] + url: [this.data.platform.url ?? 'https://', Validators.required] }); } diff --git a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html index bb99ae3a8..343b54cea 100644 --- a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html +++ b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -28,11 +28,11 @@ matInput (keydown.enter)="$event.stopPropagation()" /> - @if (data.platform.url) { - } diff --git a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.module.ts b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.module.ts deleted file mode 100644 index ac97e57cf..000000000 --- a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { CreateOrUpdatePlatformDialog } from './create-or-update-platform-dialog.component'; - -@NgModule({ - declarations: [CreateOrUpdatePlatformDialog], - imports: [ - CommonModule, - GfAssetProfileIconComponent, - FormsModule, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule - ] -}) -export class GfCreateOrUpdatePlatformDialogModule {} diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.html b/apps/client/src/app/components/admin-settings/admin-settings.component.html index f9a6084cc..af64f034b 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.html +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -1,77 +1,193 @@
    -
    +

    Data Providers

    - - -
    -
    - - @if (isGhostfolioApiKeyValid === false) { - NEW - } - Ghostfolio Premium - - - @if (isGhostfolioApiKeyValid === true) { -
    - - Valid until - {{ - ghostfolioApiStatus?.subscription?.expiresAt - | date: defaultDateFormat - }} + + Ghostfolio Premium + + + + Fuel your self-hosted Ghostfolio with a + powerful data provider to access + 80,000+ tickers from over + 50 exchanges worldwide. + + + + Get Access + +
    + or +
    + + Learn more + +
    + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + +
    + +
    + @if (isGhostfolioDataProvider(element)) { + -
    - } + Ghostfolio Premium + + @if (isGhostfolioApiKeyValid === false) { + new + } + + @if (isGhostfolioApiKeyValid === true) { +
    + + Valid until + {{ + ghostfolioApiStatus?.subscription?.expiresAt + | date: defaultDateFormat + }} + +
    + } + } @else { + {{ element.name }} + } +
    -
    +
    + Status + + @if ( + !isGhostfolioDataProvider(element) || + isGhostfolioApiKeyValid === true + ) { + + } + + Asset Profiles + + + + @if ( + isGhostfolioDataProvider(element) && + isGhostfolioApiKeyValid === true + ) { + + + {{ ghostfolioApiStatus.dailyRequests }} + of + {{ ghostfolioApiStatus.dailyRequestsMax }} + daily requests + + } + + @if (isGhostfolioDataProvider(element)) { @if (isGhostfolioApiKeyValid === true) { -
    -
    - {{ ghostfolioApiStatus.dailyRequests }} - of - {{ ghostfolioApiStatus.dailyRequestsMax }} - daily requests -
    - + + - - - -
    + } @else if (isGhostfolioApiKeyValid === false) { } - - - - + } +
    + @if (isLoading) { + + }
    diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.scss b/apps/client/src/app/components/admin-settings/admin-settings.component.scss index 5d4e87f30..1c0a17624 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.scss +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.scss @@ -1,3 +1,37 @@ :host { display: block; + + a, + button { + &.special { + background: linear-gradient(45deg, var(--oc-pink-5), var(--oc-violet-5)); + color: #fff; + } + } + + .mat-mdc-card { + --mat-card-outlined-container-color: whitesmoke; + + .mat-mdc-card-actions { + min-height: 0; + } + } + + .mat-mdc-progress-bar { + --mat-progress-bar-active-indicator-height: 0.5rem; + --mat-progress-bar-track-height: 0.5rem; + border-radius: 0.25rem; + + ::ng-deep { + .mdc-linear-progress__buffer-bar { + background-color: rgb(var(--palette-background-unselected-chip)); + } + } + } +} + +:host-context(.theme-dark) { + .mat-mdc-card { + --mat-card-outlined-container-color: #222222; + } } diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.ts b/apps/client/src/app/components/admin-settings/admin-settings.component.ts index be077c0e6..899aadc6c 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.ts +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.ts @@ -1,18 +1,24 @@ +import { GfAdminPlatformComponent } from '@ghostfolio/client/components/admin-platform/admin-platform.component'; +import { GfAdminTagComponent } from '@ghostfolio/client/components/admin-tag/admin-tag.component'; +import { GfDataProviderStatusComponent } from '@ghostfolio/client/components/data-provider-status/data-provider-status.component'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { - DEFAULT_LANGUAGE_CODE, - PROPERTY_API_KEY_GHOSTFOLIO -} from '@ghostfolio/common/config'; +import { PROPERTY_API_KEY_GHOSTFOLIO } from '@ghostfolio/common/config'; import { getDateFormatString } from '@ghostfolio/common/helper'; import { DataProviderGhostfolioStatusResponse, + DataProviderInfo, User } from '@ghostfolio/common/interfaces'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -20,26 +26,56 @@ import { OnDestroy, OnInit } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { DeviceDetectorService } from 'ngx-device-detector'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { catchError, filter, of, Subject, takeUntil } from 'rxjs'; -import { GfGhostfolioPremiumApiDialogComponent } from './ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component'; - @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + GfAdminPlatformComponent, + GfAdminTagComponent, + GfDataProviderStatusComponent, + GfEntityLogoComponent, + GfPremiumIndicatorComponent, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCardModule, + MatMenuModule, + MatProgressBarModule, + MatTableModule, + NgxSkeletonLoaderModule, + RouterModule + ], selector: 'gf-admin-settings', styleUrls: ['./admin-settings.component.scss'], - templateUrl: './admin-settings.component.html', - standalone: false + templateUrl: './admin-settings.component.html' }) -export class AdminSettingsComponent implements OnDestroy, OnInit { +export class GfAdminSettingsComponent implements OnDestroy, OnInit { + public dataSource = new MatTableDataSource(); public defaultDateFormat: string; + public displayedColumns = [ + 'name', + 'status', + 'assetProfileCount', + 'usage', + 'actions' + ]; public ghostfolioApiStatus: DataProviderGhostfolioStatusResponse; public isGhostfolioApiKeyValid: boolean; + public isLoading = false; public pricingUrl: string; - private deviceType: string; private unsubscribeSubject = new Subject(); private user: User; @@ -47,15 +83,13 @@ export class AdminSettingsComponent implements OnDestroy, OnInit { private adminService: AdminService, private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, - private deviceService: DeviceDetectorService, - private matDialog: MatDialog, private notificationService: NotificationService, private userService: UserService - ) {} + ) { + addIcons({ ellipsisHorizontal, trashOutline }); + } public ngOnInit() { - this.deviceType = this.deviceService.getDeviceInfo().deviceType; - this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { @@ -63,15 +97,12 @@ export class AdminSettingsComponent implements OnDestroy, OnInit { this.user = state.user; this.defaultDateFormat = getDateFormatString( - this.user?.settings?.locale + this.user.settings.locale ); - const languageCode = - this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE; + const languageCode = this.user.settings.language; - this.pricingUrl = - `https://ghostfol.io/${languageCode}/` + - $localize`:snake-case:pricing`; + this.pricingUrl = `https://ghostfol.io/${languageCode}/${publicRoutes.pricing.path}`; this.changeDetectorRef.markForCheck(); } @@ -80,6 +111,10 @@ export class AdminSettingsComponent implements OnDestroy, OnInit { this.initialize(); } + public isGhostfolioDataProvider(provider: DataProviderInfo): boolean { + return provider.dataSource === 'GHOSTFOLIO'; + } + public onRemoveGhostfolioApiKey() { this.notificationService.confirm({ confirmFn: () => { @@ -95,26 +130,22 @@ export class AdminSettingsComponent implements OnDestroy, OnInit { } public onSetGhostfolioApiKey() { - const dialogRef = this.matDialog.open( - GfGhostfolioPremiumApiDialogComponent, - { - autoFocus: false, - data: { - deviceType: this.deviceType, - pricingUrl: this.pricingUrl, - user: this.user - }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); - - dialogRef - .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.initialize(); - }); + this.notificationService.prompt({ + confirmFn: (value) => { + const ghostfolioApiKey = value?.trim(); + + if (ghostfolioApiKey) { + this.dataService + .putAdminSetting(PROPERTY_API_KEY_GHOSTFOLIO, { + value: ghostfolioApiKey + }) + .subscribe(() => { + this.initialize(); + }); + } + }, + title: $localize`Please enter your Ghostfolio API key.` + }); } public ngOnDestroy() { @@ -123,24 +154,51 @@ export class AdminSettingsComponent implements OnDestroy, OnInit { } private initialize() { + this.isLoading = true; + + this.dataSource = new MatTableDataSource(); + this.adminService - .fetchGhostfolioDataProviderStatus() - .pipe( - catchError(() => { + .fetchAdminData() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ dataProviders, settings }) => { + const filteredProviders = dataProviders.filter(({ dataSource }) => { + return dataSource !== 'MANUAL'; + }); + + this.dataSource = new MatTableDataSource(filteredProviders); + + const ghostfolioApiKey = settings[ + PROPERTY_API_KEY_GHOSTFOLIO + ] as string; + + if (ghostfolioApiKey) { + this.adminService + .fetchGhostfolioDataProviderStatus(ghostfolioApiKey) + .pipe( + catchError(() => { + this.isGhostfolioApiKeyValid = false; + + this.changeDetectorRef.markForCheck(); + + return of(null); + }), + filter((status) => { + return status !== null; + }), + takeUntil(this.unsubscribeSubject) + ) + .subscribe((status) => { + this.ghostfolioApiStatus = status; + this.isGhostfolioApiKeyValid = true; + + this.changeDetectorRef.markForCheck(); + }); + } else { this.isGhostfolioApiKeyValid = false; + } - this.changeDetectorRef.markForCheck(); - - return of(null); - }), - filter((status) => { - return status !== null; - }), - takeUntil(this.unsubscribeSubject) - ) - .subscribe((status) => { - this.ghostfolioApiStatus = status; - this.isGhostfolioApiKeyValid = true; + this.isLoading = false; this.changeDetectorRef.markForCheck(); }); diff --git a/apps/client/src/app/components/admin-settings/admin-settings.module.ts b/apps/client/src/app/components/admin-settings/admin-settings.module.ts deleted file mode 100644 index 5a5c39cde..000000000 --- a/apps/client/src/app/components/admin-settings/admin-settings.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { GfAdminPlatformModule } from '@ghostfolio/client/components/admin-platform/admin-platform.module'; -import { GfAdminTagModule } from '@ghostfolio/client/components/admin-tag/admin-tag.module'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { MatMenuModule } from '@angular/material/menu'; -import { RouterModule } from '@angular/router'; - -import { AdminSettingsComponent } from './admin-settings.component'; - -@NgModule({ - declarations: [AdminSettingsComponent], - imports: [ - CommonModule, - GfAdminPlatformModule, - GfAdminTagModule, - GfPremiumIndicatorComponent, - MatButtonModule, - MatCardModule, - MatMenuModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAdminSettingsModule {} diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts deleted file mode 100644 index 8c2907064..000000000 --- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; -import { DataService } from '@ghostfolio/client/services/data.service'; -import { PROPERTY_API_KEY_GHOSTFOLIO } from '@ghostfolio/common/config'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; - -import { CommonModule } from '@angular/common'; -import { Component, Inject } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { - MAT_DIALOG_DATA, - MatDialogModule, - MatDialogRef -} from '@angular/material/dialog'; - -import { GfDialogFooterModule } from '../../dialog-footer/dialog-footer.module'; -import { GfDialogHeaderModule } from '../../dialog-header/dialog-header.module'; -import { GhostfolioPremiumApiDialogParams } from './interfaces/interfaces'; - -@Component({ - imports: [ - CommonModule, - GfDialogFooterModule, - GfDialogHeaderModule, - GfPremiumIndicatorComponent, - MatButtonModule, - MatDialogModule - ], - selector: 'gf-ghostfolio-premium-api-dialog', - styleUrls: ['./ghostfolio-premium-api-dialog.scss'], - templateUrl: './ghostfolio-premium-api-dialog.html' -}) -export class GfGhostfolioPremiumApiDialogComponent { - public constructor( - @Inject(MAT_DIALOG_DATA) public data: GhostfolioPremiumApiDialogParams, - private dataService: DataService, - public dialogRef: MatDialogRef, - private notificationService: NotificationService - ) {} - - public onCancel() { - this.dialogRef.close(); - } - - public onSetGhostfolioApiKey() { - this.notificationService.prompt({ - confirmFn: (value) => { - const ghostfolioApiKey = value?.trim(); - - if (ghostfolioApiKey) { - this.dataService - .putAdminSetting(PROPERTY_API_KEY_GHOSTFOLIO, { - value: ghostfolioApiKey - }) - .subscribe(() => { - this.dialogRef.close(); - }); - } - }, - title: $localize`Please enter your Ghostfolio API key.` - }); - } -} diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html deleted file mode 100644 index ac777ffda..000000000 --- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html +++ /dev/null @@ -1,54 +0,0 @@ - - -
    -

    - The official - Ghostfolio Premium - - - data provider for self-hosters, offering - 100’000+ tickers from over 50 exchanges, - is coming soon! -

    -

    - Want to stay updated? Click below to get notified as soon as it’s available. -

    -
    - Notify me - @if (data.user?.settings?.isExperimentalFeatures) { -
    - or -
    - - } -
    -
    - - diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.scss b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.scss deleted file mode 100644 index dc9093b45..000000000 --- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.scss +++ /dev/null @@ -1,2 +0,0 @@ -:host { -} diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/interfaces/interfaces.ts deleted file mode 100644 index 157a6f414..000000000 --- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/interfaces/interfaces.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { User } from '@ghostfolio/common/interfaces'; - -export interface GhostfolioPremiumApiDialogParams { - deviceType: string; - pricingUrl: string; - user: User; -} diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.html b/apps/client/src/app/components/admin-tag/admin-tag.component.html index f69579ab8..5979d2778 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.html +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -1,108 +1,87 @@ -
    -
    -
    - - - - - - + +
    - Name - - {{ element.name }} -
    + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - -
    + Name + + {{ element.name }} + - User - - {{ element.userId }} - + User + + {{ element.userId }} + - Activities - - {{ element.activityCount }} - + Activities + + {{ element.activityCount }} + - - - -
    - -
    -
    + + + +
    + +
    +
    -
    -
    -
    + + + diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.ts b/apps/client/src/app/components/admin-tag/admin-tag.component.ts index 3c0bdb684..de4c8cedc 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.ts +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.ts @@ -1,8 +1,7 @@ -import { CreateTagDto } from '@ghostfolio/api/app/tag/create-tag.dto'; -import { UpdateTagDto } from '@ghostfolio/api/app/tag/update-tag.dto'; +import { CreateTagDto } from '@ghostfolio/api/app/endpoints/tags/create-tag.dto'; +import { UpdateTagDto } from '@ghostfolio/api/app/endpoints/tags/update-tag.dto'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; -import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -14,25 +13,41 @@ import { OnInit, ViewChild } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; -import { MatSort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; -import { ActivatedRoute, Router } from '@angular/router'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { Tag } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { + createOutline, + ellipsisHorizontal, + trashOutline +} from 'ionicons/icons'; import { get } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; -import { CreateOrUpdateTagDialog } from './create-or-update-tag-dialog/create-or-update-tag-dialog.component'; +import { GfCreateOrUpdateTagDialogComponent } from './create-or-update-tag-dialog/create-or-update-tag-dialog.component'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + IonIcon, + MatButtonModule, + MatMenuModule, + MatSortModule, + MatTableModule, + RouterModule + ], selector: 'gf-admin-tag', styleUrls: ['./admin-tag.component.scss'], - templateUrl: './admin-tag.component.html', - standalone: false + templateUrl: './admin-tag.component.html' }) -export class AdminTagComponent implements OnInit, OnDestroy { +export class GfAdminTagComponent implements OnInit, OnDestroy { @ViewChild(MatSort) sort: MatSort; public dataSource = new MatTableDataSource(); @@ -43,7 +58,6 @@ export class AdminTagComponent implements OnInit, OnDestroy { private unsubscribeSubject = new Subject(); public constructor( - private adminService: AdminService, private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, private deviceService: DeviceDetectorService, @@ -70,6 +84,8 @@ export class AdminTagComponent implements OnInit, OnDestroy { } } }); + + addIcons({ createOutline, ellipsisHorizontal, trashOutline }); } public ngOnInit() { @@ -100,7 +116,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { } private deleteTag(aId: string) { - this.adminService + this.dataService .deleteTag(aId) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ @@ -116,7 +132,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { } private fetchTags() { - this.adminService + this.dataService .fetchTags() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((tags) => { @@ -133,7 +149,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { } private openCreateTagDialog() { - const dialogRef = this.dialog.open(CreateOrUpdateTagDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateTagDialogComponent, { data: { tag: { name: null @@ -148,7 +164,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((tag: CreateTagDto | null) => { if (tag) { - this.adminService + this.dataService .postTag(tag) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ @@ -168,7 +184,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { } private openUpdateTagDialog({ id, name }) { - const dialogRef = this.dialog.open(CreateOrUpdateTagDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateTagDialogComponent, { data: { tag: { id, @@ -184,7 +200,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((tag: UpdateTagDto | null) => { if (tag) { - this.adminService + this.dataService .putTag(tag) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ diff --git a/apps/client/src/app/components/admin-tag/admin-tag.module.ts b/apps/client/src/app/components/admin-tag/admin-tag.module.ts deleted file mode 100644 index aec5ac5a6..000000000 --- a/apps/client/src/app/components/admin-tag/admin-tag.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSortModule } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; -import { RouterModule } from '@angular/router'; - -import { AdminTagComponent } from './admin-tag.component'; -import { GfCreateOrUpdateTagDialogModule } from './create-or-update-tag-dialog/create-or-update-tag-dialog.module'; - -@NgModule({ - declarations: [AdminTagComponent], - exports: [AdminTagComponent], - imports: [ - CommonModule, - GfCreateOrUpdateTagDialogModule, - MatButtonModule, - MatMenuModule, - MatSortModule, - MatTableModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAdminTagModule {} diff --git a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts index 9b7194cc6..336fb9b22 100644 --- a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts +++ b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts @@ -1,5 +1,5 @@ -import { CreateTagDto } from '@ghostfolio/api/app/tag/create-tag.dto'; -import { UpdateTagDto } from '@ghostfolio/api/app/tag/update-tag.dto'; +import { CreateTagDto } from '@ghostfolio/api/app/endpoints/tags/create-tag.dto'; +import { UpdateTagDto } from '@ghostfolio/api/app/endpoints/tags/update-tag.dto'; import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; import { @@ -8,8 +8,20 @@ import { Inject, OnDestroy } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { + FormBuilder, + FormGroup, + FormsModule, + ReactiveFormsModule +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; import { Subject } from 'rxjs'; import { CreateOrUpdateTagDialogParams } from './interfaces/interfaces'; @@ -17,19 +29,26 @@ import { CreateOrUpdateTagDialogParams } from './interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, + imports: [ + FormsModule, + MatButtonModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule + ], selector: 'gf-create-or-update-tag-dialog', styleUrls: ['./create-or-update-tag-dialog.scss'], - templateUrl: 'create-or-update-tag-dialog.html', - standalone: false + templateUrl: 'create-or-update-tag-dialog.html' }) -export class CreateOrUpdateTagDialog implements OnDestroy { +export class GfCreateOrUpdateTagDialogComponent implements OnDestroy { public tagForm: FormGroup; private unsubscribeSubject = new Subject(); public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateTagDialogParams, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private formBuilder: FormBuilder ) { this.tagForm = this.formBuilder.group({ diff --git a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.module.ts b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.module.ts deleted file mode 100644 index d8b12edc2..000000000 --- a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { CreateOrUpdateTagDialog } from './create-or-update-tag-dialog.component'; - -@NgModule({ - declarations: [CreateOrUpdateTagDialog], - imports: [ - CommonModule, - FormsModule, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule - ] -}) -export class GfCreateOrUpdateTagDialogModule {} diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index 50b8cb5f3..84b82d111 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -1,14 +1,16 @@ -import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; -import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; -import { AdminService } from '@ghostfolio/client/services/admin.service'; -import { DataService } from '@ghostfolio/client/services/data.service'; -import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; -import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; -import { getDateFormatString, getEmojiFlag } from '@ghostfolio/common/helper'; +import { + getDateFnsLocale, + getDateFormatString, + getEmojiFlag +} from '@ghostfolio/common/helper'; import { AdminUsers, InfoItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { CommonModule } from '@angular/common'; import { ChangeDetectorRef, Component, @@ -16,23 +18,55 @@ import { OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; -import { MatTableDataSource } from '@angular/material/table'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { + MatPaginator, + MatPaginatorModule, + PageEvent +} from '@angular/material/paginator'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { IonIcon } from '@ionic/angular/standalone'; import { differenceInSeconds, formatDistanceToNowStrict, parseISO } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { + contractOutline, + ellipsisHorizontal, + keyOutline, + trashOutline +} from 'ionicons/icons'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { ConfirmationDialogType } from '../../core/notification/confirmation-dialog/confirmation-dialog.type'; +import { NotificationService } from '../../core/notification/notification.service'; +import { AdminService } from '../../services/admin.service'; +import { DataService } from '../../services/data.service'; +import { ImpersonationStorageService } from '../../services/impersonation-storage.service'; +import { UserService } from '../../services/user/user.service'; + @Component({ + imports: [ + CommonModule, + GfPremiumIndicatorComponent, + GfValueComponent, + IonIcon, + MatButtonModule, + MatMenuModule, + MatPaginatorModule, + MatTableModule, + NgxSkeletonLoaderModule + ], selector: 'gf-admin-users', styleUrls: ['./admin-users.scss'], - templateUrl: './admin-users.html', - standalone: false + templateUrl: './admin-users.html' }) -export class AdminUsersComponent implements OnDestroy, OnInit { +export class GfAdminUsersComponent implements OnDestroy, OnInit { @ViewChild(MatPaginator) paginator: MatPaginator; public dataSource = new MatTableDataSource(); @@ -55,6 +89,7 @@ export class AdminUsersComponent implements OnDestroy, OnInit { private dataService: DataService, private impersonationStorageService: ImpersonationStorageService, private notificationService: NotificationService, + private tokenStorageService: TokenStorageService, private userService: UserService ) { this.info = this.dataService.fetchInfo(); @@ -66,7 +101,6 @@ export class AdminUsersComponent implements OnDestroy, OnInit { if (this.hasPermissionForSubscription) { this.displayedColumns = [ - 'index', 'user', 'country', 'registration', @@ -79,7 +113,6 @@ export class AdminUsersComponent implements OnDestroy, OnInit { ]; } else { this.displayedColumns = [ - 'index', 'user', 'registration', 'accounts', @@ -104,6 +137,8 @@ export class AdminUsersComponent implements OnDestroy, OnInit { ); } }); + + addIcons({ contractOutline, ellipsisHorizontal, keyOutline, trashOutline }); } public ngOnInit() { @@ -113,7 +148,8 @@ export class AdminUsersComponent implements OnDestroy, OnInit { public formatDistanceToNow(aDateString: string) { if (aDateString) { const distanceString = formatDistanceToNowStrict(parseISO(aDateString), { - addSuffix: true + addSuffix: true, + locale: getDateFnsLocale(this.user?.settings?.language) }); return Math.abs(differenceInSeconds(parseISO(aDateString), new Date())) < @@ -140,6 +176,32 @@ export class AdminUsersComponent implements OnDestroy, OnInit { }); } + public onGenerateAccessToken(aUserId: string) { + this.notificationService.confirm({ + confirmFn: () => { + this.dataService + .updateUserAccessToken(aUserId) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ accessToken }) => { + this.notificationService.alert({ + discardFn: () => { + if (aUserId === this.user.id) { + this.tokenStorageService.signOut(); + this.userService.remove(); + + document.location.href = `/${document.documentElement.lang}`; + } + }, + message: accessToken, + title: $localize`Security token` + }); + }); + }, + confirmType: ConfirmationDialogType.Warn, + title: $localize`Do you really want to generate a new security token for this user?` + }); + } + public onImpersonateUser(aId: string) { if (aId) { this.impersonationStorageService.setId(aId); diff --git a/apps/client/src/app/components/admin-users/admin-users.html b/apps/client/src/app/components/admin-users/admin-users.html index ca8ef0558..7a6a6ae87 100644 --- a/apps/client/src/app/components/admin-users/admin-users.html +++ b/apps/client/src/app/components/admin-users/admin-users.html @@ -3,23 +3,6 @@
    - - - - - @@ -309,14 +309,14 @@ @@ -468,7 +468,7 @@ [ngClass]="{ 'cursor-pointer': hasPermissionToOpenDetails && - row.Account?.isExcluded !== true && + row.account?.isExcluded !== true && row.isDraft === false && ['BUY', 'DIVIDEND', 'SELL'].includes(row.type) }" @@ -500,7 +500,10 @@ /> @if ( - dataSource?.data.length === 0 && hasPermissionToCreateActivity && !isLoading + !hasActivities && + dataSource?.data.length === 0 && + hasPermissionToCreateActivity && + !isLoading ) {
    diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index 01b4c6ead..df1211787 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -1,5 +1,4 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; @@ -7,9 +6,6 @@ import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; import { getDateFormatString, getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { OrderWithAccount } from '@ghostfolio/common/types'; -import { GfActivityTypeComponent } from '@ghostfolio/ui/activity-type'; -import { GfNoTransactionsInfoComponent } from '@ghostfolio/ui/no-transactions-info'; -import { GfValueComponent } from '@ghostfolio/ui/value'; import { SelectionModel } from '@angular/cdk/collections'; import { CommonModule } from '@angular/common'; @@ -42,20 +38,41 @@ import { } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { IonIcon } from '@ionic/angular/standalone'; import { isUUID } from 'class-validator'; import { endOfToday, isAfter } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { + alertCircleOutline, + calendarClearOutline, + cloudDownloadOutline, + cloudUploadOutline, + colorWandOutline, + copyOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + ellipsisVertical, + trashOutline +} from 'ionicons/icons'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject, Subscription, takeUntil } from 'rxjs'; +import { GfActivityTypeComponent } from '../activity-type/activity-type.component'; +import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; +import { GfNoTransactionsInfoComponent } from '../no-transactions-info/no-transactions-info.component'; +import { GfValueComponent } from '../value/value.component'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, GfActivityTypeComponent, - GfAssetProfileIconComponent, + GfEntityLogoComponent, GfNoTransactionsInfoComponent, GfSymbolModule, GfValueComponent, + IonIcon, MatButtonModule, MatCheckboxModule, MatMenuModule, @@ -76,6 +93,7 @@ export class GfActivitiesTableComponent @Input() baseCurrency: string; @Input() dataSource: MatTableDataSource; @Input() deviceType: string; + @Input() hasActivities: boolean; @Input() hasPermissionToCreateActivity: boolean; @Input() hasPermissionToDeleteActivity: boolean; @Input() hasPermissionToExportActivities: boolean; @@ -120,7 +138,21 @@ export class GfActivitiesTableComponent private unsubscribeSubject = new Subject(); - public constructor(private notificationService: NotificationService) {} + public constructor(private notificationService: NotificationService) { + addIcons({ + alertCircleOutline, + calendarClearOutline, + cloudDownloadOutline, + cloudUploadOutline, + colorWandOutline, + copyOutline, + createOutline, + documentTextOutline, + ellipsisHorizontal, + ellipsisVertical, + trashOutline + }); + } public ngOnInit() { if (this.showCheckbox) { @@ -194,7 +226,7 @@ export class GfActivitiesTableComponent } } else if ( this.hasPermissionToOpenDetails && - activity.Account?.isExcluded !== true && + activity.account?.isExcluded !== true && activity.isDraft === false && ['BUY', 'DIVIDEND', 'SELL'].includes(activity.type) ) { diff --git a/libs/ui/src/lib/activity-type/activity-type.component.html b/libs/ui/src/lib/activity-type/activity-type.component.html index 78eb2f17b..fe5ecfa01 100644 --- a/libs/ui/src/lib/activity-type/activity-type.component.html +++ b/libs/ui/src/lib/activity-type/activity-type.component.html @@ -5,7 +5,6 @@ dividend: activityType === 'DIVIDEND', fee: activityType === 'FEE', interest: activityType === 'INTEREST', - item: activityType === 'ITEM', liability: activityType === 'LIABILITY', sell: activityType === 'SELL' }" @@ -16,8 +15,6 @@ } @else if (activityType === 'FEE') { - } @else if (activityType === 'ITEM') { - } @else if (activityType === 'LIABILITY') { } @else if (activityType === 'SELL') { diff --git a/libs/ui/src/lib/activity-type/activity-type.component.scss b/libs/ui/src/lib/activity-type/activity-type.component.scss index 49889b665..34b951805 100644 --- a/libs/ui/src/lib/activity-type/activity-type.component.scss +++ b/libs/ui/src/lib/activity-type/activity-type.component.scss @@ -26,10 +26,6 @@ color: var(--cyan); } - &.item { - color: var(--purple); - } - &.liability { color: var(--red); } diff --git a/libs/ui/src/lib/activity-type/activity-type.component.stories.ts b/libs/ui/src/lib/activity-type/activity-type.component.stories.ts new file mode 100644 index 000000000..349cf6a7b --- /dev/null +++ b/libs/ui/src/lib/activity-type/activity-type.component.stories.ts @@ -0,0 +1,30 @@ +import { CommonModule } from '@angular/common'; +import { IonIcon } from '@ionic/angular/standalone'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; + +import { GfActivityTypeComponent } from './activity-type.component'; + +export default { + title: 'Activity Type', + component: GfActivityTypeComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, IonIcon] + }) + ], + argTypes: { + activityType: { + control: 'select', + options: ['BUY', 'DIVIDEND', 'FEE', 'INTEREST', 'LIABILITY', 'SELL'] + } + } +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + activityType: 'BUY' + } +}; diff --git a/libs/ui/src/lib/activity-type/activity-type.component.ts b/libs/ui/src/lib/activity-type/activity-type.component.ts index 27434e015..07e8c7ef4 100644 --- a/libs/ui/src/lib/activity-type/activity-type.component.ts +++ b/libs/ui/src/lib/activity-type/activity-type.component.ts @@ -1,5 +1,3 @@ -import { translate } from '@ghostfolio/ui/i18n'; - import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, @@ -8,11 +6,23 @@ import { Input, OnChanges } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; import { Type as ActivityType } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { + addCircleOutline, + arrowDownCircleOutline, + arrowUpCircleOutline, + cubeOutline, + flameOutline, + hammerOutline +} from 'ionicons/icons'; + +import { translate } from '../i18n'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule], + imports: [CommonModule, IonIcon], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-activity-type', styleUrls: ['./activity-type.component.scss'], @@ -23,6 +33,17 @@ export class GfActivityTypeComponent implements OnChanges { public activityTypeLabel: string; + public constructor() { + addIcons({ + addCircleOutline, + arrowDownCircleOutline, + arrowUpCircleOutline, + cubeOutline, + flameOutline, + hammerOutline + }); + } + public ngOnChanges() { this.activityTypeLabel = translate(this.activityType); } diff --git a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts index a0744db9f..70b466127 100644 --- a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts +++ b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts @@ -1,5 +1,5 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { ISearchResultItem } from '@ghostfolio/ui/assistant/interfaces/interfaces'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { FocusableOption } from '@angular/cdk/a11y'; import { @@ -16,6 +16,12 @@ import { } from '@angular/core'; import { Params, RouterModule } from '@angular/router'; +import { SearchMode } from '../enums/search-mode'; +import { + IAssetSearchResultItem, + ISearchResultItem +} from '../interfaces/interfaces'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [GfSymbolModule, RouterModule], @@ -32,7 +38,6 @@ export class GfAssistantListItemComponent } @Input() item: ISearchResultItem; - @Input() mode: 'assetProfile' | 'holding'; @Output() clicked = new EventEmitter(); @@ -45,23 +50,26 @@ export class GfAssistantListItemComponent public constructor(private changeDetectorRef: ChangeDetectorRef) {} public ngOnChanges() { - const dataSource = this.item?.dataSource; - const symbol = this.item?.symbol; - - if (this.mode === 'assetProfile') { + if (this.item?.mode === SearchMode.ASSET_PROFILE) { this.queryParams = { - dataSource, - symbol, - assetProfileDialog: true + assetProfileDialog: true, + dataSource: this.item?.dataSource, + symbol: this.item?.symbol }; - this.routerLink = ['/admin', 'market-data']; - } else if (this.mode === 'holding') { + + this.routerLink = + internalRoutes.adminControl.subRoutes.marketData.routerLink; + } else if (this.item?.mode === SearchMode.HOLDING) { this.queryParams = { - dataSource, - symbol, - holdingDetailDialog: true + dataSource: this.item?.dataSource, + holdingDetailDialog: true, + symbol: this.item?.symbol }; + this.routerLink = []; + } else if (this.item?.mode === SearchMode.QUICK_LINK) { + this.queryParams = {}; + this.routerLink = this.item.routerLink; } } @@ -71,6 +79,15 @@ export class GfAssistantListItemComponent this.changeDetectorRef.markForCheck(); } + public isAsset(item: ISearchResultItem): item is IAssetSearchResultItem { + return ( + (item.mode === SearchMode.ASSET_PROFILE || + item.mode === SearchMode.HOLDING) && + !!item.dataSource && + !!item.symbol + ); + } + public onClick() { this.clicked.emit(); } diff --git a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.html b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.html index 46c8a4c24..9c55dac54 100644 --- a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.html +++ b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.html @@ -1,17 +1,17 @@ {{ item?.name }} -
    - {{ item?.symbol | gfSymbol }} · {{ item?.currency }} - @if (item?.assetSubClassString) { - · {{ item.assetSubClassString }} - } -
    + >{{ item?.name }} + @if (item && isAsset(item)) { +
    + {{ item?.symbol | gfSymbol }} · {{ item?.currency }} + @if (item?.assetSubClassString) { + · {{ item.assetSubClassString }} + } + + } + diff --git a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.scss b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.scss index 9f677c1a4..7c33c0ff9 100644 --- a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.scss +++ b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.scss @@ -6,6 +6,11 @@ a { color: rgba(var(--light-primary-text)); + font-weight: bold; + + .text-muted { + color: rgba(var(--light-primary-text)) !important; + } } } } @@ -14,6 +19,10 @@ &.has-focus { a { color: rgba(var(--dark-primary-text)); + + .text-muted { + color: rgba(var(--dark-primary-text)) !important; + } } } } diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts index d8c3dcc2e..032b3222d 100644 --- a/libs/ui/src/lib/assistant/assistant.component.ts +++ b/libs/ui/src/lib/assistant/assistant.component.ts @@ -1,14 +1,13 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { Filter, PortfolioPosition, User } from '@ghostfolio/common/interfaces'; +import { InternalRoute } from '@ghostfolio/common/routes/interfaces/internal-route.interface'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { DateRange } from '@ghostfolio/common/types'; -import { translate } from '@ghostfolio/ui/i18n'; import { FocusKeyManager } from '@angular/cdk/a11y'; -import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, @@ -37,19 +36,34 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatMenuTrigger } from '@angular/material/menu'; import { MatSelectModule } from '@angular/material/select'; import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { Account, AssetClass, DataSource } from '@prisma/client'; +import { differenceInYears } from 'date-fns'; +import Fuse from 'fuse.js'; +import { addIcons } from 'ionicons'; +import { + closeCircleOutline, + closeOutline, + searchOutline +} from 'ionicons/icons'; +import { isFunction } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { EMPTY, Observable, Subject, lastValueFrom } from 'rxjs'; +import { EMPTY, Observable, Subject, merge, of } from 'rxjs'; import { catchError, debounceTime, distinctUntilChanged, map, - mergeMap, - takeUntil + scan, + switchMap, + takeUntil, + tap } from 'rxjs/operators'; +import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; +import { translate } from '../i18n'; import { GfAssistantListItemComponent } from './assistant-list-item/assistant-list-item.component'; +import { SearchMode } from './enums/search-mode'; import { IDateRangeOption, ISearchResultItem, @@ -59,11 +73,11 @@ import { @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ - CommonModule, FormsModule, - GfAssetProfileIconComponent, GfAssistantListItemComponent, + GfEntityLogoComponent, GfSymbolModule, + IonIcon, MatButtonModule, MatFormFieldModule, MatSelectModule, @@ -138,13 +152,18 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { tag: new FormControl(undefined) }); public holdings: PortfolioPosition[] = []; - public isLoading = false; + public isLoading = { + assetProfiles: false, + holdings: false, + quickLinks: false + }; public isOpen = false; - public placeholder = $localize`Find holding...`; + public placeholder = $localize`Find holding or page...`; public searchFormControl = new FormControl(''); public searchResults: ISearchResults = { assetProfiles: [], - holdings: [] + holdings: [], + quickLinks: [] }; public tags: Filter[] = []; @@ -163,7 +182,9 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, private formBuilder: FormBuilder - ) {} + ) { + addIcons({ closeCircleOutline, closeOutline, searchOutline }); + } public ngOnInit() { this.assetClasses = Object.keys(AssetClass).map((assetClass) => { @@ -177,39 +198,145 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { this.searchFormControl.valueChanges .pipe( map((searchTerm) => { - this.isLoading = true; + this.isLoading = { + assetProfiles: true, + holdings: true, + quickLinks: true + }; this.searchResults = { assetProfiles: [], - holdings: [] + holdings: [], + quickLinks: [] }; this.changeDetectorRef.markForCheck(); - return searchTerm; + return searchTerm?.trim(); }), debounceTime(300), distinctUntilChanged(), - mergeMap(async (searchTerm) => { - const result = { + switchMap((searchTerm) => { + const results = { assetProfiles: [], - holdings: [] + holdings: [], + quickLinks: [] } as ISearchResults; - try { - if (searchTerm) { - return await this.getSearchResults(searchTerm); - } - } catch {} + if (!searchTerm) { + return of(results).pipe( + tap(() => { + this.isLoading = { + assetProfiles: false, + holdings: false, + quickLinks: false + }; + }) + ); + } + + // Asset profiles + const assetProfiles$: Observable> = this + .hasPermissionToAccessAdminControl + ? this.searchAssetProfiles(searchTerm).pipe( + map((assetProfiles) => ({ + assetProfiles: assetProfiles.slice( + 0, + GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + ) + })), + catchError((error) => { + console.error( + 'Error fetching asset profiles for assistant:', + error + ); + return of({ assetProfiles: [] as ISearchResultItem[] }); + }), + tap(() => { + this.isLoading.assetProfiles = false; + this.changeDetectorRef.markForCheck(); + }) + ) + : of({ assetProfiles: [] as ISearchResultItem[] }).pipe( + tap(() => { + this.isLoading.assetProfiles = false; + this.changeDetectorRef.markForCheck(); + }) + ); + + // Holdings + const holdings$: Observable> = + this.searchHoldings(searchTerm).pipe( + map((holdings) => ({ + holdings: holdings.slice( + 0, + GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + ) + })), + catchError((error) => { + console.error('Error fetching holdings for assistant:', error); + return of({ holdings: [] as ISearchResultItem[] }); + }), + tap(() => { + this.isLoading.holdings = false; + this.changeDetectorRef.markForCheck(); + }) + ); + + // Quick links + const quickLinks$: Observable> = of( + this.searchQuickLinks(searchTerm) + ).pipe( + map((quickLinks) => ({ + quickLinks: quickLinks.slice( + 0, + GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + ) + })), + tap(() => { + this.isLoading.quickLinks = false; + this.changeDetectorRef.markForCheck(); + }) + ); - return result; + // Merge all results + return merge(quickLinks$, assetProfiles$, holdings$).pipe( + scan( + (acc: ISearchResults, curr: Partial) => ({ + ...acc, + ...curr + }), + { + assetProfiles: [], + holdings: [], + quickLinks: [] + } as ISearchResults + ) + ); }), takeUntil(this.unsubscribeSubject) ) - .subscribe((searchResults) => { - this.searchResults = searchResults; - this.isLoading = false; - - this.changeDetectorRef.markForCheck(); + .subscribe({ + next: (searchResults) => { + this.searchResults = searchResults; + this.changeDetectorRef.markForCheck(); + }, + error: (error) => { + console.error('Assistant search stream error:', error); + this.searchResults = { + assetProfiles: [], + holdings: [], + quickLinks: [] + }; + this.changeDetectorRef.markForCheck(); + }, + complete: () => { + this.isLoading = { + assetProfiles: false, + holdings: false, + quickLinks: false + }; + this.changeDetectorRef.markForCheck(); + } }); } @@ -217,7 +344,10 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { this.accounts = this.user?.accounts ?? []; this.dateRangeOptions = [ - { label: $localize`Today`, value: '1d' }, + { + label: $localize`Today`, + value: '1d' + }, { label: $localize`Week to date` + ' (' + $localize`WTD` + ')', value: 'wtd' @@ -229,13 +359,19 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { { label: $localize`Year to date` + ' (' + $localize`YTD` + ')', value: 'ytd' - }, - { - label: '1 ' + $localize`year` + ' (' + $localize`1Y` + ')', - value: '1y' } ]; + if ( + this.user?.dateOfFirstActivity && + differenceInYears(new Date(), this.user.dateOfFirstActivity) >= 1 + ) { + this.dateRangeOptions.push({ + label: '1 ' + $localize`year` + ' (' + $localize`1Y` + ')', + value: '1y' + }); + } + // TODO // if (this.user?.settings?.isExperimentalFeatures) { // this.dateRangeOptions = this.dateRangeOptions.concat( @@ -251,13 +387,20 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { // ); // } - this.dateRangeOptions = this.dateRangeOptions.concat([ - { + if ( + this.user?.dateOfFirstActivity && + differenceInYears(new Date(), this.user.dateOfFirstActivity) >= 5 + ) { + this.dateRangeOptions.push({ label: '5 ' + $localize`years` + ' (' + $localize`5Y` + ')', value: '5y' - }, - { label: $localize`Max`, value: 'max' } - ]); + }); + } + + this.dateRangeOptions.push({ + label: $localize`Max`, + value: 'max' + }); this.dateRangeFormControl.disable({ emitEvent: false }); @@ -307,11 +450,16 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { } public initialize() { - this.isLoading = true; + this.isLoading = { + assetProfiles: true, + holdings: true, + quickLinks: true + }; this.keyManager = new FocusKeyManager(this.assistantListItems).withWrap(); this.searchResults = { assetProfiles: [], - holdings: [] + holdings: [], + quickLinks: [] }; for (const item of this.assistantListItems) { @@ -323,7 +471,11 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { this.searchElement?.nativeElement?.focus(); }); - this.isLoading = false; + this.isLoading = { + assetProfiles: false, + holdings: false, + quickLinks: false + }; this.setIsOpen(true); this.dataService @@ -375,7 +527,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { } public onChangeDateRange(dateRangeString: string) { - this.dateRangeChanged.emit(dateRangeString as DateRange); + this.dateRangeChanged.emit(dateRangeString); } public onCloseAssistant() { @@ -412,36 +564,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { }); } - private async getSearchResults(aSearchTerm: string) { - let assetProfiles: ISearchResultItem[] = []; - let holdings: ISearchResultItem[] = []; - - if (this.hasPermissionToAccessAdminControl) { - try { - assetProfiles = await lastValueFrom( - this.searchAssetProfiles(aSearchTerm) - ); - assetProfiles = assetProfiles.slice( - 0, - GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT - ); - } catch {} - } - - try { - holdings = await lastValueFrom(this.searchHoldings(aSearchTerm)); - holdings = holdings.slice( - 0, - GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT - ); - } catch {} - - return { - assetProfiles, - holdings - }; - } - private searchAssetProfiles( aSearchTerm: string ): Observable { @@ -467,7 +589,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { dataSource, name, symbol, - assetSubClassString: translate(assetSubClass) + assetSubClassString: translate(assetSubClass), + mode: SearchMode.ASSET_PROFILE as const }; } ); @@ -484,8 +607,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { id: aSearchTerm, type: 'SEARCH_QUERY' } - ], - range: '1d' + ] }) .pipe( catchError(() => { @@ -499,7 +621,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { dataSource, name, symbol, - assetSubClassString: translate(assetSubClass) + assetSubClassString: translate(assetSubClass), + mode: SearchMode.HOLDING as const }; } ); @@ -508,6 +631,39 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { ); } + private searchQuickLinks(aSearchTerm: string): ISearchResultItem[] { + const searchTerm = aSearchTerm.toLowerCase(); + + const allRoutes = Object.values(internalRoutes) + .filter(({ excludeFromAssistant }) => { + if (isFunction(excludeFromAssistant)) { + return excludeFromAssistant(this.user); + } + + return !excludeFromAssistant; + }) + .reduce((acc, route) => { + acc.push(route); + if (route.subRoutes) { + acc.push(...Object.values(route.subRoutes)); + } + return acc; + }, [] as InternalRoute[]); + + const fuse = new Fuse(allRoutes, { + keys: ['title'], + threshold: 0.3 + }); + + return fuse.search(searchTerm).map(({ item: { routerLink, title } }) => { + return { + routerLink, + mode: SearchMode.QUICK_LINK as const, + name: title + }; + }); + } + private setFilterFormValues() { const dataSource = this.user?.settings?.[ 'filters.dataSource' diff --git a/libs/ui/src/lib/assistant/assistant.html b/libs/ui/src/lib/assistant/assistant.html index 33b4db3ff..f957d9dcc 100644 --- a/libs/ui/src/lib/assistant/assistant.html +++ b/libs/ui/src/lib/assistant/assistant.html @@ -15,76 +15,126 @@ [formControl]="searchFormControl" [placeholder]="placeholder" /> -
    - / -
    - - + @if (deviceType !== 'mobile' && !searchFormControl.value) { +
    /
    + } + @if (searchFormControl.value) { + + } @else { + + }
    -
    -
    -
    Holdings
    - - - -
    No entries...
    -
    -
    -
    -
    Asset Profiles
    - - - -
    No entries...
    -
    + @if (searchFormControl.value) { +
    + @if ( + !isLoading.assetProfiles && + !isLoading.holdings && + !isLoading.quickLinks && + searchResults.assetProfiles?.length === 0 && + searchResults.holdings?.length === 0 && + searchResults.quickLinks?.length === 0 + ) { +
    No results found...
    + } @else { + @if ( + isLoading.quickLinks || searchResults?.quickLinks?.length !== 0 + ) { +
    +
    + Quick Links +
    + @for ( + searchResultItem of searchResults.quickLinks; + track searchResultItem + ) { + + } + @if (isLoading.quickLinks) { + + } +
    + } + @if (isLoading.holdings || searchResults?.holdings?.length !== 0) { +
    +
    + Holdings +
    + @for ( + searchResultItem of searchResults.holdings; + track searchResultItem + ) { + + } + @if (isLoading.holdings) { + + } +
    + } + @if ( + hasPermissionToAccessAdminControl && + (isLoading.assetProfiles || + searchResults?.assetProfiles?.length !== 0) + ) { +
    +
    + Asset Profiles +
    + @for ( + searchResultItem of searchResults.assetProfiles; + track searchResultItem + ) { + + } + @if (isLoading.assetProfiles) { + + } +
    + } + }
    -
    + }
    @if (!searchFormControl.value) { @@ -110,12 +160,14 @@ @for (account of accounts; track account.id) {
    - {{ account.name }} + @if (account.platform?.url) { + + } + {{ account.name }}
    } diff --git a/libs/ui/src/lib/assistant/assistant.scss b/libs/ui/src/lib/assistant/assistant.scss index 2de06824a..3630978c1 100644 --- a/libs/ui/src/lib/assistant/assistant.scss +++ b/libs/ui/src/lib/assistant/assistant.scss @@ -7,6 +7,24 @@ .result-container { max-height: 15rem; + + .title { + align-items: center; + display: flex; + font-size: 0.75rem; + display: flex; + margin: 0; + position: relative; + white-space: nowrap; + + &::after { + content: ''; + flex-grow: 1; + height: 1px; + background: rgba(var(--dark-dividers)); + margin-left: 0.25rem; + } + } } .search-container { @@ -31,6 +49,14 @@ border-color: rgba(var(--light-dividers)); } + .result-container { + .title { + &::after { + background: rgba(var(--light-dividers)); + } + } + } + .search-container { border-color: rgba(var(--light-dividers)); diff --git a/libs/ui/src/lib/assistant/enums/search-mode.ts b/libs/ui/src/lib/assistant/enums/search-mode.ts new file mode 100644 index 000000000..f85ad47e9 --- /dev/null +++ b/libs/ui/src/lib/assistant/enums/search-mode.ts @@ -0,0 +1,5 @@ +export enum SearchMode { + ASSET_PROFILE = 'assetProfile', + HOLDING = 'holding', + QUICK_LINK = 'quickLink' +} diff --git a/libs/ui/src/lib/assistant/interfaces/interfaces.ts b/libs/ui/src/lib/assistant/interfaces/interfaces.ts index 3481b37cf..ce8b644be 100644 --- a/libs/ui/src/lib/assistant/interfaces/interfaces.ts +++ b/libs/ui/src/lib/assistant/interfaces/interfaces.ts @@ -1,18 +1,32 @@ import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { DateRange } from '@ghostfolio/common/types'; +import { SearchMode } from '../enums/search-mode'; + +export interface IAssetSearchResultItem extends AssetProfileIdentifier { + assetSubClassString: string; + currency: string; + mode: SearchMode.ASSET_PROFILE | SearchMode.HOLDING; + name: string; +} + export interface IDateRangeOption { label: string; value: DateRange; } -export interface ISearchResultItem extends AssetProfileIdentifier { - assetSubClassString: string; - currency: string; +export interface IQuickLinkSearchResultItem { + mode: SearchMode.QUICK_LINK; name: string; + routerLink: string[]; } +export type ISearchResultItem = + | IAssetSearchResultItem + | IQuickLinkSearchResultItem; + export interface ISearchResults { assetProfiles: ISearchResultItem[]; holdings: ISearchResultItem[]; + quickLinks: ISearchResultItem[]; } diff --git a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts index 38c6252a8..45f116358 100644 --- a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts +++ b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts @@ -6,9 +6,7 @@ import { AdminMarketDataDetails, LineChartItem } from '@ghostfolio/common/interfaces'; -import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; -import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, @@ -27,16 +25,18 @@ import { format } from 'date-fns'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { GfLineChartComponent } from '../../line-chart/line-chart.component'; +import { GfValueComponent } from '../../value/value.component'; import { BenchmarkDetailDialogParams } from './interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'd-flex flex-column h-100' }, imports: [ - CommonModule, GfDialogFooterModule, GfDialogHeaderModule, GfLineChartComponent, + GfValueComponent, MatDialogModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -47,6 +47,7 @@ import { BenchmarkDetailDialogParams } from './interfaces/interfaces'; export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit { public assetProfile: AdminMarketDataDetails['assetProfile']; public historicalDataItems: LineChartItem[]; + public value: number; private unsubscribeSubject = new Subject(); @@ -67,9 +68,18 @@ export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit { .subscribe(({ assetProfile, marketData }) => { this.assetProfile = assetProfile; - this.historicalDataItems = marketData.map(({ date, marketPrice }) => { - return { date: format(date, DATE_FORMAT), value: marketPrice }; - }); + this.historicalDataItems = marketData.map( + ({ date, marketPrice }, index) => { + if (marketData.length - 1 === index) { + this.value = marketPrice; + } + + return { + date: format(date, DATE_FORMAT), + value: marketPrice + }; + } + ); this.changeDetectorRef.markForCheck(); }); diff --git a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html index 23196f162..5c862d961 100644 --- a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html +++ b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html @@ -8,17 +8,28 @@
    +
    +
    + +
    +
    +
    diff --git a/libs/ui/src/lib/benchmark/benchmark.component.html b/libs/ui/src/lib/benchmark/benchmark.component.html index 8867e1c9e..8df8417f1 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.html +++ b/libs/ui/src/lib/benchmark/benchmark.component.html @@ -1,127 +1,192 @@ -
    - # - - {{ i + 1 }} - {{ (element.id | slice: 0 : 5) + '...' }} - @if (element?.subscription?.type === 'Premium') { + @if (element.subscription?.expiresAt) { } @@ -142,7 +126,7 @@ @@ -239,8 +223,17 @@ Impersonate User -
    } + +
    - @if (user.subscription.offer === 'default') { - Upgrade Plan - } @else if ( - user.subscription.offer === 'renewal' || - user.subscription.offer === 'renewal-early-bird-2023' || - user.subscription.offer === 'renewal-early-bird-2024' - ) { + @if (user.subscription.offer.isRenewal) { Renew Plan + } @else { + Upgrade Plan } OverviewPortfolio Accounts My Ghostfolio @if (hasPermissionToAccessAdminControl) { @@ -274,8 +281,11 @@ class="d-flex d-sm-none" i18n mat-menu-item - [ngClass]="{ 'font-weight-bold': currentRoute === 'admin' }" - [routerLink]="['/admin']" + [ngClass]="{ + 'font-weight-bold': + currentRoute === internalRoutes.adminControl.path + }" + [routerLink]="routerLinkAdminControl" >Admin Control } @@ -316,7 +326,7 @@ >About Ghostfolio
    - +
    diff --git a/apps/client/src/app/components/header/header.component.scss b/apps/client/src/app/components/header/header.component.scss index 3527413f2..9a8d85863 100644 --- a/apps/client/src/app/components/header/header.component.scss +++ b/apps/client/src/app/components/header/header.component.scss @@ -7,7 +7,11 @@ .logo-container { &.filled { - background-color: rgba(var(--palette-foreground-base), 0.02); + background: linear-gradient( + to bottom, + transparent, + rgba(var(--palette-foreground-base), 0.02) + ); } @media (min-width: 576px) { @@ -57,7 +61,11 @@ .logo-container { &.filled { - background-color: rgba(var(--palette-foreground-base-dark), 0.02); + background: linear-gradient( + to bottom, + transparent, + rgba(var(--palette-foreground-base-dark), 0.02) + ); } } } diff --git a/apps/client/src/app/components/header/header.component.ts b/apps/client/src/app/components/header/header.component.ts index 728320aef..f1a6a22b6 100644 --- a/apps/client/src/app/components/header/header.component.ts +++ b/apps/client/src/app/components/header/header.component.ts @@ -12,6 +12,7 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.s import { UserService } from '@ghostfolio/client/services/user/user.service'; import { Filter, InfoItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { DateRange } from '@ghostfolio/common/types'; import { GfAssistantComponent } from '@ghostfolio/ui/assistant/assistant.component'; @@ -28,6 +29,16 @@ import { import { MatDialog } from '@angular/material/dialog'; import { MatMenuTrigger } from '@angular/material/menu'; import { Router } from '@angular/router'; +import { addIcons } from 'ionicons'; +import { + closeOutline, + logoGithub, + menuOutline, + optionsOutline, + personCircleOutline, + radioButtonOffOutline, + radioButtonOnOutline +} from 'ionicons/icons'; import { EMPTY, Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; @@ -71,6 +82,7 @@ export class HeaderComponent implements OnChanges { @ViewChild('assistantTrigger') assistentMenuTriggerElement: MatMenuTrigger; public hasFilters: boolean; + public hasImpersonationId: boolean; public hasPermissionForSocialLogin: boolean; public hasPermissionForSubscription: boolean; public hasPermissionToAccessAdminControl: boolean; @@ -78,18 +90,23 @@ export class HeaderComponent implements OnChanges { public hasPermissionToAccessFearAndGreedIndex: boolean; public hasPermissionToCreateUser: boolean; public impersonationId: string; + public internalRoutes = internalRoutes; public isMenuOpen: boolean; - public routeAbout = $localize`:snake-case:about`; - public routeFeatures = $localize`:snake-case:features`; - public routeMarkets = $localize`:snake-case:markets`; - public routePricing = $localize`:snake-case:pricing`; - public routeResources = $localize`:snake-case:resources`; - public routerLinkAbout = ['/' + $localize`:snake-case:about`]; - public routerLinkFeatures = ['/' + $localize`:snake-case:features`]; - public routerLinkMarkets = ['/' + $localize`:snake-case:markets`]; - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; - public routerLinkRegister = ['/' + $localize`:snake-case:register`]; - public routerLinkResources = ['/' + $localize`:snake-case:resources`]; + public routeAbout = publicRoutes.about.path; + public routeFeatures = publicRoutes.features.path; + public routeMarkets = publicRoutes.markets.path; + public routePricing = publicRoutes.pricing.path; + public routeResources = publicRoutes.resources.path; + public routerLinkAbout = publicRoutes.about.routerLink; + public routerLinkAccount = internalRoutes.account.routerLink; + public routerLinkAccounts = internalRoutes.accounts.routerLink; + public routerLinkAdminControl = internalRoutes.adminControl.routerLink; + public routerLinkFeatures = publicRoutes.features.routerLink; + public routerLinkMarkets = publicRoutes.markets.routerLink; + public routerLinkPortfolio = internalRoutes.portfolio.routerLink; + public routerLinkPricing = publicRoutes.pricing.routerLink; + public routerLinkRegister = publicRoutes.register.routerLink; + public routerLinkResources = publicRoutes.resources.routerLink; private unsubscribeSubject = new Subject(); @@ -108,8 +125,19 @@ export class HeaderComponent implements OnChanges { .onChangeHasImpersonation() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((impersonationId) => { + this.hasImpersonationId = !!impersonationId; this.impersonationId = impersonationId; }); + + addIcons({ + closeOutline, + logoGithub, + menuOutline, + optionsOutline, + personCircleOutline, + radioButtonOffOutline, + radioButtonOnOutline + }); } public ngOnChanges() { diff --git a/apps/client/src/app/components/header/header.module.ts b/apps/client/src/app/components/header/header.module.ts index 402960b74..847a4ef4d 100644 --- a/apps/client/src/app/components/header/header.module.ts +++ b/apps/client/src/app/components/header/header.module.ts @@ -10,6 +10,7 @@ import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; import { MatToolbarModule } from '@angular/material/toolbar'; import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { HeaderComponent } from './header.component'; @@ -21,6 +22,7 @@ import { HeaderComponent } from './header.component'; GfAssistantComponent, GfLogoComponent, GfPremiumIndicatorComponent, + IonIcon, LoginWithAccessTokenDialogModule, MatBadgeModule, MatButtonModule, diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index 94d5bd915..50065e3da 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -1,5 +1,5 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { GfAccountsTableModule } from '@ghostfolio/client/components/accounts-table/accounts-table.module'; +import { GfAccountsTableComponent } from '@ghostfolio/client/components/accounts-table/accounts-table.component'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { DataService } from '@ghostfolio/client/services/data.service'; @@ -13,31 +13,28 @@ import { LineChartItem, User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits'; +import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor'; import { translate } from '@ghostfolio/ui/i18n'; import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector'; import { GfValueComponent } from '@ghostfolio/ui/value'; -import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, - ElementRef, Inject, OnDestroy, - OnInit, - ViewChild + OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { - MatAutocompleteModule, - MatAutocompleteSelectedEvent -} from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatChipsModule } from '@angular/material/chips'; import { @@ -49,12 +46,23 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { SortDirection } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { MatTabsModule } from '@angular/material/tabs'; -import { Router } from '@angular/router'; -import { Account, Tag } from '@prisma/client'; +import { Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { Account, MarketData, Tag } from '@prisma/client'; +import { isUUID } from 'class-validator'; import { format, isSameMonth, isToday, parseISO } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { + createOutline, + flagOutline, + readerOutline, + serverOutline, + swapVerticalOutline, + walletOutline +} from 'ionicons/icons'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Observable, of, Subject } from 'rxjs'; -import { map, startWith, takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { switchMap, takeUntil } from 'rxjs/operators'; import { HoldingDetailDialogParams } from './interfaces/interfaces'; @@ -63,21 +71,24 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; host: { class: 'd-flex flex-column h-100' }, imports: [ CommonModule, - GfAccountsTableModule, + GfAccountsTableComponent, GfActivitiesTableComponent, GfDataProviderCreditsComponent, GfDialogFooterModule, GfDialogHeaderModule, + GfHistoricalMarketDataEditorComponent, GfLineChartComponent, GfPortfolioProportionChartComponent, + GfTagsSelectorComponent, GfValueComponent, - MatAutocompleteModule, + IonIcon, MatButtonModule, MatChipsModule, MatDialogModule, MatFormFieldModule, MatTabsModule, - NgxSkeletonLoaderModule + NgxSkeletonLoaderModule, + RouterModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-holding-detail-dialog', @@ -85,14 +96,13 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; templateUrl: 'holding-detail-dialog.html' }) export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { - @ViewChild('tagInput') tagInput: ElementRef; - public activityForm: FormGroup; public accounts: Account[]; public assetClass: string; public assetSubClass: string; public averagePrice: number; public benchmarkDataItems: LineChartItem[]; + public benchmarkLabel = $localize`Average Unit Price`; public countries: { [code: string]: { name: string; value: number }; }; @@ -102,14 +112,17 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public dividendInBaseCurrencyPrecision = 2; public dividendYieldPercentWithCurrencyEffect: number; public feeInBaseCurrency: number; - public filteredTagsObservable: Observable = of([]); public firstBuyDate: string; + public hasPermissionToCreateOwnTag: boolean; + public hasPermissionToReadMarketDataOfOwnAssetProfile: boolean; public historicalDataItems: LineChartItem[]; - public investment: number; - public investmentPrecision = 2; + public investmentInBaseCurrencyWithCurrencyEffect: number; + public investmentInBaseCurrencyWithCurrencyEffectPrecision = 2; + public isUUID = isUUID; + public marketDataItems: MarketData[] = []; public marketPrice: number; - public maxPrice: number; - public minPrice: number; + public marketPriceMax: number; + public marketPriceMin: number; public netPerformance: number; public netPerformancePrecision = 2; public netPerformancePercent: number; @@ -119,10 +132,11 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public quantity: number; public quantityPrecision = 2; public reportDataGlitchMail: string; + public routerLinkAdminControlMarketData = + internalRoutes.adminControl.subRoutes.marketData.routerLink; public sectors: { [name: string]: { name: string; value: number }; }; - public separatorKeysCodes: number[] = [COMMA, ENTER]; public sortColumn = 'date'; public sortDirection: SortDirection = 'desc'; public SymbolProfile: EnhancedSymbolProfile; @@ -143,7 +157,16 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { private formBuilder: FormBuilder, private router: Router, private userService: UserService - ) {} + ) { + addIcons({ + createOutline, + flagOutline, + readerOutline, + serverOutline, + swapVerticalOutline, + walletOutline + }); + } public ngOnInit() { this.activityForm = this.formBuilder.group({ @@ -158,15 +181,43 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.activityForm .get('tags') .valueChanges.pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((tags) => { - this.dataService - .putHoldingTags({ - tags, - dataSource: this.data.dataSource, - symbol: this.data.symbol - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(); + .subscribe((tags: Tag[]) => { + const newTag = tags.find(({ id }) => { + return id === undefined; + }); + + if (newTag && this.hasPermissionToCreateOwnTag) { + this.dataService + .postTag({ ...newTag, userId: this.user.id }) + .pipe( + switchMap((createdTag) => { + return this.dataService.putHoldingTags({ + dataSource: this.data.dataSource, + symbol: this.data.symbol, + tags: [ + ...tags.filter(({ id }) => { + return id !== undefined; + }), + createdTag + ] + }); + }), + switchMap(() => { + return this.userService.get(true); + }), + takeUntil(this.unsubscribeSubject) + ) + .subscribe(); + } else { + this.dataService + .putHoldingTags({ + tags, + dataSource: this.data.dataSource, + symbol: this.data.symbol + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + } }); this.dataService @@ -208,10 +259,10 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { feeInBaseCurrency, firstBuyDate, historicalData, - investment, + investmentInBaseCurrencyWithCurrencyEffect, marketPrice, - maxPrice, - minPrice, + marketPriceMax, + marketPriceMin, netPerformance, netPerformancePercent, netPerformancePercentWithCurrencyEffect, @@ -241,6 +292,14 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.feeInBaseCurrency = feeInBaseCurrency; this.firstBuyDate = firstBuyDate; + this.hasPermissionToReadMarketDataOfOwnAssetProfile = + hasPermission( + this.user?.permissions, + permissions.readMarketDataOfOwnAssetProfile + ) && + SymbolProfile?.dataSource === 'MANUAL' && + SymbolProfile?.userId === this.user?.id; + this.historicalDataItems = historicalData.map( ({ averagePrice, date, marketPrice }) => { this.benchmarkDataItems.push({ @@ -255,18 +314,20 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { } ); - this.investment = investment; + this.investmentInBaseCurrencyWithCurrencyEffect = + investmentInBaseCurrencyWithCurrencyEffect; if ( this.data.deviceType === 'mobile' && - this.investment >= NUMERICAL_PRECISION_THRESHOLD + this.investmentInBaseCurrencyWithCurrencyEffect >= + NUMERICAL_PRECISION_THRESHOLD ) { - this.investmentPrecision = 0; + this.investmentInBaseCurrencyWithCurrencyEffectPrecision = 0; } this.marketPrice = marketPrice; - this.maxPrice = maxPrice; - this.minPrice = minPrice; + this.marketPriceMax = marketPriceMax; + this.marketPriceMin = marketPriceMin; this.netPerformance = netPerformance; if ( @@ -296,7 +357,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { if (Number.isInteger(this.quantity)) { this.quantityPrecision = 0; - } else if (this.SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') { + } else if (SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') { if (this.quantity < 1) { this.quantityPrecision = 7; } else if (this.quantity < 1000) { @@ -319,17 +380,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.activityForm.setValue({ tags: this.tags }, { emitEvent: false }); - this.filteredTagsObservable = this.activityForm.controls[ - 'tags' - ].valueChanges.pipe( - startWith(this.activityForm.get('tags').value), - map((aTags: Tag[] | null) => { - return aTags - ? this.filterTags(aTags) - : this.tagsAvailable.slice(); - }) - ); - this.transactionCount = transactionCount; this.totalItems = transactionCount; this.value = value; @@ -414,6 +464,10 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { } ); + if (this.hasPermissionToReadMarketDataOfOwnAssetProfile) { + this.fetchMarketData(); + } + this.changeDetectorRef.markForCheck(); } ); @@ -424,6 +478,10 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { if (state?.user) { this.user = state.user; + this.hasPermissionToCreateOwnTag = + hasPermission(this.user.permissions, permissions.createOwnTag) && + this.user?.settings?.isExperimentalFeatures; + this.tagsAvailable = this.user?.tags?.map((tag) => { return { @@ -437,21 +495,13 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }); } - public onAddTag(event: MatAutocompleteSelectedEvent) { - this.activityForm.get('tags').setValue([ - ...(this.activityForm.get('tags').value ?? []), - this.tagsAvailable.find(({ id }) => { - return id === event.option.value; - }) - ]); - - this.tagInput.nativeElement.value = ''; - } - public onCloneActivity(aActivity: Activity) { - this.router.navigate(['/portfolio', 'activities'], { - queryParams: { activityId: aActivity.id, createDialog: true } - }); + this.router.navigate( + internalRoutes.portfolio.subRoutes.activities.routerLink, + { + queryParams: { activityId: aActivity.id, createDialog: true } + } + ); this.dialogRef.close(); } @@ -480,18 +530,23 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }); } - public onRemoveTag(aTag: Tag) { - this.activityForm.get('tags').setValue( - this.activityForm.get('tags').value.filter(({ id }) => { - return id !== aTag.id; - }) - ); + public onMarketDataChanged(withRefresh = false) { + if (withRefresh) { + this.fetchMarketData(); + } + } + + public onTagsChanged(tags: Tag[]) { + this.activityForm.get('tags').setValue(tags); } public onUpdateActivity(aActivity: Activity) { - this.router.navigate(['/portfolio', 'activities'], { - queryParams: { activityId: aActivity.id, editDialog: true } - }); + this.router.navigate( + internalRoutes.portfolio.subRoutes.activities.routerLink, + { + queryParams: { activityId: aActivity.id, editDialog: true } + } + ); this.dialogRef.close(); } @@ -501,13 +556,26 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.unsubscribeSubject.complete(); } - private filterTags(aTags: Tag[]) { - const tagIds = aTags.map(({ id }) => { - return id; - }); + private fetchMarketData() { + this.dataService + .fetchMarketDataBySymbol({ + dataSource: this.data.dataSource, + symbol: this.data.symbol + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ marketData }) => { + this.marketDataItems = marketData; - return this.tagsAvailable.filter(({ id }) => { - return !tagIds.includes(id); - }); + this.historicalDataItems = this.marketDataItems.map( + ({ date, marketPrice }) => { + return { + date: format(date, DATE_FORMAT), + value: marketPrice + }; + } + ); + + this.changeDetectorRef.markForCheck(); + }); } } diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index f92ad54f8..e0673a1f5 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -21,298 +21,316 @@ -
    -
    - - @if ( - SymbolProfile?.currency && - data.baseCurrency !== SymbolProfile?.currency - ) { - Change with currency effect - } @else { - Change - } - -
    -
    - - @if ( - SymbolProfile?.currency && - data.baseCurrency !== SymbolProfile?.currency - ) { - Performance with currency effect - } @else { - Performance - } - -
    -
    - Average Unit Price -
    -
    - Market Price -
    -
    - Minimum Price -
    -
    - Maximum Price -
    -
    - Quantity -
    -
    - Investment -
    - @if (dividendInBaseCurrency && user?.settings?.isExperimentalFeatures) { -
    - Dividend -
    -
    - Dividend Yield -
    - } -
    - Fees -
    -
    - First Activity -
    -
    - - @if (transactionCount === 1) { - Activity - } @else { - Activities - } - -
    -
    -
    - Asset Class -
    -
    - Asset Sub Class -
    - @if ( - SymbolProfile?.countries?.length > 0 || - SymbolProfile?.sectors?.length > 0 - ) { - @if ( - SymbolProfile?.countries?.length === 1 && - SymbolProfile?.sectors?.length === 1 - ) { -
    - Sector -
    - @if (SymbolProfile?.countries?.length === 1) { + + + + +
    Overview
    +
    +
    +
    Country + @if ( + SymbolProfile?.currency && + data.baseCurrency !== SymbolProfile?.currency + ) { + Change with currency effect + } @else { + Change + } + +
    +
    + + @if ( + SymbolProfile?.currency && + data.baseCurrency !== SymbolProfile?.currency + ) { + Performance with currency effect + } @else { + Performance + } + +
    +
    + Average Unit Price +
    +
    + Market Price +
    +
    + Minimum Price +
    +
    + Maximum Price +
    +
    + Quantity +
    +
    + Investment +
    + @if ( + dividendInBaseCurrency && user?.settings?.isExperimentalFeatures + ) { +
    + Dividend +
    +
    + Dividend Yield +
    + } +
    + Fees +
    +
    + First Activity +
    +
    + + @if (transactionCount === 1) { + Activity + } @else { + Activities + } + +
    +
    +
    + Asset Class +
    +
    + Asset Sub Class +
    + @if ( + SymbolProfile?.countries?.length > 0 || + SymbolProfile?.sectors?.length > 0 + ) { + @if ( + SymbolProfile?.countries?.length === 1 && + SymbolProfile?.sectors?.length === 1 + ) { +
    + Sector +
    + @if (SymbolProfile?.countries?.length === 1) { +
    + Country +
    + } + } @else { +
    +
    Sectors
    + +
    +
    +
    Countries
    + +
    + } + } +
    + Symbol +
    +
    + ISIN
    - } - } @else { -
    -
    Sectors
    - -
    -
    -
    Countries
    - -
    - } - } -
    - Symbol -
    -
    - ISIN -
    - @if (dataProviderInfo) { -
    -
    - -
    + @if (dataProviderInfo) { +
    +
    + +
    +
    + } +
    - } -
    - - +
    @@ -332,7 +350,7 @@ [locale]="data.locale" [showActions]=" !data.hasImpersonationId && - data.hasPermissionToCreateOrder && + data.hasPermissionToCreateActivity && user?.settings?.isExperimentalFeatures && !user?.settings?.isRestrictedView " @@ -357,6 +375,7 @@ [deviceType]="data.deviceType" [hasPermissionToOpenDetails]="false" [locale]="user?.settings?.locale" + [showAllocationInPercentage]="user?.settings?.isExperimentalFeatures" [showBalance]="false" [showFooter]="false" [showTransactions]="false" @@ -364,74 +383,69 @@ [showValueInBaseCurrency]="false" /> + @if ( + hasPermissionToReadMarketDataOfOwnAssetProfile && + user?.settings?.isExperimentalFeatures + ) { + + + +
    Market Data
    +
    + +
    + }
    -
    -
    - - Tags - - @for (tag of activityForm.get('tags')?.value; track tag.id) { - - {{ tag.name }} - - - } - - - - @for (tag of filteredTagsObservable | async; track tag.id) { - - {{ tag.name }} - - } - - -
    -
    - - @if (!data.hasPermissionToUpdateOrder && tagsAvailable?.length > 0) { -
    -
    -
    Tags
    - - @for (tag of tags; track tag) { - {{ tag.name }} - } - -
    -
    - } + @if ( - dataSource?.data.length > 0 && - data.hasPermissionToReportDataGlitch === true + data.hasPermissionToAccessAdminControl || + (dataSource?.data.length > 0 && + data.hasPermissionToReportDataGlitch === true) ) {

    - Report Data Glitch + @if (data.hasPermissionToAccessAdminControl) { + Manage Asset Profile... + } + @if ( + dataSource?.data.length > 0 && + data.hasPermissionToReportDataGlitch === true + ) { + Report Data Glitch... + }
    } diff --git a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts index cb98ab3a7..aab854384 100644 --- a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts @@ -8,7 +8,8 @@ export interface HoldingDetailDialogParams { dataSource: DataSource; deviceType: string; hasImpersonationId: boolean; - hasPermissionToCreateOrder: boolean; + hasPermissionToAccessAdminControl: boolean; + hasPermissionToCreateActivity: boolean; hasPermissionToReportDataGlitch: boolean; hasPermissionToUpdateOrder: boolean; locale: string; diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index dd411f6cc..33d9139ea 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -8,37 +8,67 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { HoldingType, HoldingsViewMode } from '@ghostfolio/common/types'; +import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; +import { GfTreemapChartComponent } from '@ghostfolio/ui/treemap-chart'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { FormControl } from '@angular/forms'; -import { Router } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; +import { Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { gridOutline, reorderFourOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + CommonModule, + FormsModule, + GfHoldingsTableComponent, + GfToggleComponent, + GfTreemapChartComponent, + IonIcon, + MatButtonModule, + MatButtonToggleModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-home-holdings', styleUrls: ['./home-holdings.scss'], - templateUrl: './home-holdings.html', - standalone: false + templateUrl: './home-holdings.html' }) -export class HomeHoldingsComponent implements OnDestroy, OnInit { +export class GfHomeHoldingsComponent implements OnDestroy, OnInit { public static DEFAULT_HOLDINGS_VIEW_MODE: HoldingsViewMode = 'TABLE'; public deviceType: string; public hasImpersonationId: boolean; public hasPermissionToAccessHoldingsChart: boolean; - public hasPermissionToCreateOrder: boolean; + public hasPermissionToCreateActivity: boolean; public holdings: PortfolioPosition[]; public holdingType: HoldingType = 'ACTIVE'; public holdingTypeOptions: ToggleOption[] = [ { label: $localize`Active`, value: 'ACTIVE' }, { label: $localize`Closed`, value: 'CLOSED' } ]; + public routerLinkPortfolioActivities = + internalRoutes.portfolio.subRoutes.activities.routerLink; public user: User; public viewModeFormControl = new FormControl( - HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE + GfHomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE ); private unsubscribeSubject = new Subject(); @@ -50,7 +80,9 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { private impersonationStorageService: ImpersonationStorageService, private router: Router, private userService: UserService - ) {} + ) { + addIcons({ gridOutline, reorderFourOutline }); + } public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; @@ -73,7 +105,7 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { permissions.accessHoldingsChart ); - this.hasPermissionToCreateOrder = hasPermission( + this.hasPermissionToCreateActivity = hasPermission( this.user.permissions, permissions.createOrder ); @@ -146,14 +178,14 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { this.viewModeFormControl.setValue( this.deviceType === 'mobile' - ? HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE + ? GfHomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE : this.user?.settings?.holdingsViewMode || - HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE, + GfHomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE, { emitEvent: false } ); } else if (this.holdingType === 'CLOSED') { this.viewModeFormControl.setValue( - HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE, + GfHomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE, { emitEvent: false } ); } diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index abbc93b3d..87d0a514d 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -28,7 +28,7 @@ [defaultValue]="holdingType" [isLoading]="false" [options]="holdingTypeOptions" - (change)="onChangeHoldingType($event.value)" + (valueChange)="onChangeHoldingType($event.value)" />
    @@ -48,18 +48,21 @@ - @if (hasPermissionToCreateOrder && holdings?.length > 0) { + @if ( + !hasImpersonationId && + hasPermissionToCreateActivity && + holdings?.length > 0 + ) { diff --git a/apps/client/src/app/components/home-holdings/home-holdings.module.ts b/apps/client/src/app/components/home-holdings/home-holdings.module.ts deleted file mode 100644 index df951c1a8..000000000 --- a/apps/client/src/app/components/home-holdings/home-holdings.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; -import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; -import { GfTreemapChartComponent } from '@ghostfolio/ui/treemap-chart'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatButtonToggleModule } from '@angular/material/button-toggle'; -import { RouterModule } from '@angular/router'; - -import { HomeHoldingsComponent } from './home-holdings.component'; - -@NgModule({ - declarations: [HomeHoldingsComponent], - imports: [ - CommonModule, - FormsModule, - GfHoldingsTableComponent, - GfToggleModule, - GfTreemapChartComponent, - MatButtonModule, - MatButtonToggleModule, - ReactiveFormsModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfHomeHoldingsModule {} diff --git a/apps/client/src/app/components/home-holdings/home-holdings.scss b/apps/client/src/app/components/home-holdings/home-holdings.scss index d6d129a39..a978004a0 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.scss +++ b/apps/client/src/app/components/home-holdings/home-holdings.scss @@ -3,7 +3,7 @@ .mat-button-toggle-group { .mat-button-toggle-appearance-standard { - --mat-standard-button-toggle-height: 1.5rem; + --mat-button-toggle-height: 1.5rem; } } } diff --git a/apps/client/src/app/components/home-market/home-market.component.ts b/apps/client/src/app/components/home-market/home-market.component.ts index e51bdf1ca..c754935df 100644 --- a/apps/client/src/app/components/home-market/home-market.component.ts +++ b/apps/client/src/app/components/home-market/home-market.component.ts @@ -1,3 +1,4 @@ +import { GfFearAndGreedIndexModule } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; @@ -9,17 +10,30 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; +import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + GfBenchmarkComponent, + GfFearAndGreedIndexModule, + GfLineChartComponent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-home-market', styleUrls: ['./home-market.scss'], - templateUrl: './home-market.html', - standalone: false + templateUrl: './home-market.html' }) export class HomeMarketComponent implements OnDestroy, OnInit { public benchmarks: Benchmark[]; diff --git a/apps/client/src/app/components/home-market/home-market.html b/apps/client/src/app/components/home-market/home-market.html index 2fcdb5716..9ea286301 100644 --- a/apps/client/src/app/components/home-market/home-market.html +++ b/apps/client/src/app/components/home-market/home-market.html @@ -2,13 +2,13 @@

    Markets

    @if (hasPermissionToAccessFearAndGreedIndex) {
    -
    +
    Last {{ numberOfDays }} Days
    -
    +
    + @if (benchmarks?.length > 0) { +
    + + Calculations are based on delayed market data and may not be + displayed in real-time. +
    + }
    diff --git a/apps/client/src/app/components/home-market/home-market.module.ts b/apps/client/src/app/components/home-market/home-market.module.ts deleted file mode 100644 index b8e6582a5..000000000 --- a/apps/client/src/app/components/home-market/home-market.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { GfFearAndGreedIndexModule } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.module'; -import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; -import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; - -import { HomeMarketComponent } from './home-market.component'; - -@NgModule({ - declarations: [HomeMarketComponent], - exports: [HomeMarketComponent], - imports: [ - CommonModule, - GfBenchmarkComponent, - GfFearAndGreedIndexModule, - GfLineChartComponent - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfHomeMarketModule {} diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index b0e7be320..06fccd650 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -1,4 +1,4 @@ -import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; +import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module'; import { LayoutService } from '@ghostfolio/client/core/layout.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -11,31 +11,53 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; +import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { RouterModule } from '@angular/router'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + CommonModule, + GfLineChartComponent, + GfPortfolioPerformanceModule, + MatButtonModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-home-overview', styleUrls: ['./home-overview.scss'], - templateUrl: './home-overview.html', - standalone: false + templateUrl: './home-overview.html' }) -export class HomeOverviewComponent implements OnDestroy, OnInit { - public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; +export class GfHomeOverviewComponent implements OnDestroy, OnInit { public deviceType: string; public errors: AssetProfileIdentifier[]; public hasError: boolean; public hasImpersonationId: boolean; - public hasPermissionToCreateOrder: boolean; + public hasPermissionToCreateActivity: boolean; public historicalDataItems: LineChartItem[]; public isAllTimeHigh: boolean; public isAllTimeLow: boolean; public isLoadingPerformance = true; public performance: PortfolioPerformance; + public performanceLabel = $localize`Performance`; public precision = 2; + public routerLinkAccounts = internalRoutes.accounts.routerLink; + public routerLinkPortfolio = internalRoutes.portfolio.routerLink; + public routerLinkPortfolioActivities = + internalRoutes.portfolio.subRoutes.activities.routerLink; public showDetails = false; public unit: string; public user: User; @@ -56,7 +78,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { if (state?.user) { this.user = state.user; - this.hasPermissionToCreateOrder = hasPermission( + this.hasPermissionToCreateActivity = hasPermission( this.user.permissions, permissions.createOrder ); diff --git a/apps/client/src/app/components/home-overview/home-overview.html b/apps/client/src/app/components/home-overview/home-overview.html index 8cd317428..b36302ded 100644 --- a/apps/client/src/app/components/home-overview/home-overview.html +++ b/apps/client/src/app/components/home-overview/home-overview.html @@ -1,7 +1,11 @@
    - @if (hasPermissionToCreateOrder && historicalDataItems?.length === 0) { + @if ( + !hasImpersonationId && + hasPermissionToCreateActivity && + user?.activitiesCount === 0 + ) {

    Welcome to Ghostfolio

    @@ -11,7 +15,7 @@ class="mb-2" [ngClass]="{ 'text-muted': user?.accounts?.length > 1 }" > - Setup your accounts
    Get a comprehensive financial overview by adding your bank and @@ -20,7 +24,7 @@ >
  • - + Capture your activities
    Record your investment activities to keep your portfolio up to @@ -29,7 +33,7 @@ >
  • - + Monitor and analyze your portfolio
    Track your progress in real-time with comprehensive analysis @@ -40,14 +44,18 @@
    @if (user?.accounts?.length === 1) { - + Setup accounts } @else if (user?.accounts?.length > 1) { Add activity @@ -61,12 +69,12 @@
    (); + + public constructor( + public readonly dialogRef: MatDialogRef, + public readonly formBuilder: FormBuilder + ) {} + + public ngOnInit() { + this.createWatchlistItemForm = this.formBuilder.group( + { + searchSymbol: new FormControl(null, [Validators.required]) + }, + { + validators: this.validator + } + ); + } + + public onCancel() { + this.dialogRef.close(); + } + + public onSubmit() { + this.dialogRef.close({ + dataSource: + this.createWatchlistItemForm.get('searchSymbol').value.dataSource, + symbol: this.createWatchlistItemForm.get('searchSymbol').value.symbol + }); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private validator(control: AbstractControl): ValidationErrors { + const searchSymbolControl = control.get('searchSymbol'); + + if ( + searchSymbolControl.valid && + searchSymbolControl.value.dataSource && + searchSymbolControl.value.symbol + ) { + return { incomplete: false }; + } + + return { incomplete: true }; + } +} diff --git a/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html new file mode 100644 index 000000000..dd59a9309 --- /dev/null +++ b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html @@ -0,0 +1,25 @@ +
    +

    Add asset to watchlist

    +
    + + Name, symbol or ISIN + + +
    +
    + + +
    +
    diff --git a/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/interfaces/interfaces.ts new file mode 100644 index 000000000..c0f74d022 --- /dev/null +++ b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/interfaces/interfaces.ts @@ -0,0 +1,4 @@ +export interface CreateWatchlistItemDialogParams { + deviceType: string; + locale: string; +} diff --git a/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts new file mode 100644 index 000000000..ccb1664f1 --- /dev/null +++ b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts @@ -0,0 +1,189 @@ +import { DataService } from '@ghostfolio/client/services/data.service'; +import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { + AssetProfileIdentifier, + Benchmark, + User +} from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { BenchmarkTrend } from '@ghostfolio/common/types'; +import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { addOutline } from 'ionicons/icons'; +import { DeviceDetectorService } from 'ngx-device-detector'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import { CreateWatchlistItemDialogComponent } from './create-watchlist-item-dialog/create-watchlist-item-dialog.component'; +import { CreateWatchlistItemDialogParams } from './create-watchlist-item-dialog/interfaces/interfaces'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + GfBenchmarkComponent, + GfPremiumIndicatorComponent, + IonIcon, + MatButtonModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-home-watchlist', + styleUrls: ['./home-watchlist.scss'], + templateUrl: './home-watchlist.html' +}) +export class HomeWatchlistComponent implements OnDestroy, OnInit { + public deviceType: string; + public hasImpersonationId: boolean; + public hasPermissionToCreateWatchlistItem: boolean; + public hasPermissionToDeleteWatchlistItem: boolean; + public user: User; + public watchlist: Benchmark[]; + + private unsubscribeSubject = new Subject(); + + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private dataService: DataService, + private deviceService: DeviceDetectorService, + private dialog: MatDialog, + private impersonationStorageService: ImpersonationStorageService, + private route: ActivatedRoute, + private router: Router, + private userService: UserService + ) { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + + this.impersonationStorageService + .onChangeHasImpersonation() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((impersonationId) => { + this.hasImpersonationId = !!impersonationId; + }); + + this.route.queryParams + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((params) => { + if (params['createWatchlistItemDialog']) { + this.openCreateWatchlistItemDialog(); + } + }); + + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.hasPermissionToCreateWatchlistItem = + !this.hasImpersonationId && + hasPermission( + this.user.permissions, + permissions.createWatchlistItem + ); + this.hasPermissionToDeleteWatchlistItem = + !this.hasImpersonationId && + hasPermission( + this.user.permissions, + permissions.deleteWatchlistItem + ); + + this.changeDetectorRef.markForCheck(); + } + }); + + addIcons({ addOutline }); + } + + public ngOnInit() { + this.loadWatchlistData(); + } + + public onWatchlistItemDeleted({ + dataSource, + symbol + }: AssetProfileIdentifier) { + this.dataService + .deleteWatchlistItem({ dataSource, symbol }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe({ + next: () => { + return this.loadWatchlistData(); + } + }); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private loadWatchlistData() { + this.dataService + .fetchWatchlist() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ watchlist }) => { + this.watchlist = watchlist.map( + ({ dataSource, marketCondition, name, performances, symbol }) => ({ + dataSource, + marketCondition, + name, + performances, + symbol, + trend50d: 'UNKNOWN' as BenchmarkTrend, + trend200d: 'UNKNOWN' as BenchmarkTrend + }) + ); + + this.changeDetectorRef.markForCheck(); + }); + } + + private openCreateWatchlistItemDialog() { + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + const dialogRef = this.dialog.open(CreateWatchlistItemDialogComponent, { + autoFocus: false, + data: { + deviceType: this.deviceType, + locale: this.user?.settings?.locale + } as CreateWatchlistItemDialogParams, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); + + dialogRef + .afterClosed() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ dataSource, symbol } = {}) => { + if (dataSource && symbol) { + this.dataService + .postWatchlistItem({ dataSource, symbol }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe({ + next: () => this.loadWatchlistData() + }); + } + + this.router.navigate(['.'], { relativeTo: this.route }); + }); + }); + } +} diff --git a/apps/client/src/app/components/home-watchlist/home-watchlist.html b/apps/client/src/app/components/home-watchlist/home-watchlist.html new file mode 100644 index 000000000..743d86c37 --- /dev/null +++ b/apps/client/src/app/components/home-watchlist/home-watchlist.html @@ -0,0 +1,35 @@ +
    +

    + + Watchlist + @if (user?.subscription?.type === 'Basic') { + + } + +

    +
    +
    + +
    +
    +
    +@if (!hasImpersonationId && hasPermissionToCreateWatchlistItem) { +
    + + + +
    +} diff --git a/apps/client/src/app/components/home-watchlist/home-watchlist.scss b/apps/client/src/app/components/home-watchlist/home-watchlist.scss new file mode 100644 index 000000000..5d4e87f30 --- /dev/null +++ b/apps/client/src/app/components/home-watchlist/home-watchlist.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts index 8ee6f59d8..9ee0adcdc 100644 --- a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts +++ b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts @@ -9,6 +9,8 @@ import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { MatCheckboxChange } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Router } from '@angular/router'; +import { addIcons } from 'ionicons'; +import { eyeOffOutline, eyeOutline } from 'ionicons/icons'; @Component({ selector: 'gf-login-with-access-token-dialog', @@ -27,7 +29,9 @@ export class LoginWithAccessTokenDialog { private router: Router, private settingsStorageService: SettingsStorageService, private tokenStorageService: TokenStorageService - ) {} + ) { + addIcons({ eyeOffOutline, eyeOutline }); + } public onChangeStaySignedIn(aValue: MatCheckboxChange) { this.settingsStorageService.setSetting( diff --git a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.module.ts b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.module.ts index b0f2e75c6..d6035ae52 100644 --- a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.module.ts +++ b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.module.ts @@ -7,6 +7,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; +import { IonIcon } from '@ionic/angular/standalone'; import { GfDialogHeaderModule } from '../dialog-header/dialog-header.module'; import { LoginWithAccessTokenDialog } from './login-with-access-token-dialog.component'; @@ -17,6 +18,7 @@ import { LoginWithAccessTokenDialog } from './login-with-access-token-dialog.com CommonModule, FormsModule, GfDialogHeaderModule, + IonIcon, MatButtonModule, MatCheckboxModule, MatDialogModule, diff --git a/apps/client/src/app/components/markets/markets.component.ts b/apps/client/src/app/components/markets/markets.component.ts new file mode 100644 index 000000000..91c28e1c7 --- /dev/null +++ b/apps/client/src/app/components/markets/markets.component.ts @@ -0,0 +1,127 @@ +import { GfFearAndGreedIndexModule } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.module'; +import { DataService } from '@ghostfolio/client/services/data.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { resetHours } from '@ghostfolio/common/helper'; +import { + Benchmark, + HistoricalDataItem, + MarketDataOfMarketsResponse, + ToggleOption, + User +} from '@ghostfolio/common/interfaces'; +import { FearAndGreedIndexMode } from '@ghostfolio/common/types'; +import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; +import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { DeviceDetectorService } from 'ngx-device-detector'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + GfBenchmarkComponent, + GfFearAndGreedIndexModule, + GfLineChartComponent, + GfToggleComponent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-markets', + styleUrls: ['./markets.scss'], + templateUrl: './markets.html' +}) +export class MarketsComponent implements OnDestroy, OnInit { + public benchmarks: Benchmark[]; + public deviceType: string; + public fearAndGreedIndex: number; + public fearAndGreedIndexData: MarketDataOfMarketsResponse['fearAndGreedIndex']; + public fearLabel = $localize`Fear`; + public greedLabel = $localize`Greed`; + public historicalDataItems: HistoricalDataItem[]; + public fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS'; + public fearAndGreedIndexModeOptions: ToggleOption[] = [ + { label: $localize`Stocks`, value: 'STOCKS' }, + { label: $localize`Cryptocurrencies`, value: 'CRYPTOCURRENCIES' } + ]; + public readonly numberOfDays = 365; + public user: User; + + private unsubscribeSubject = new Subject(); + + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private dataService: DataService, + private deviceService: DeviceDetectorService, + private userService: UserService + ) { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + + this.userService.stateChanged + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((state) => { + if (state?.user) { + this.user = state.user; + + this.changeDetectorRef.markForCheck(); + } + }); + } + + public ngOnInit() { + this.dataService + .fetchMarketDataOfMarkets({ includeHistoricalData: this.numberOfDays }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ fearAndGreedIndex }) => { + this.fearAndGreedIndexData = fearAndGreedIndex; + + this.initialize(); + + this.changeDetectorRef.markForCheck(); + }); + + this.dataService + .fetchBenchmarks() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ benchmarks }) => { + this.benchmarks = benchmarks; + + this.changeDetectorRef.markForCheck(); + }); + } + + public initialize() { + this.fearAndGreedIndex = + this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice; + + this.historicalDataItems = [ + ...(this.fearAndGreedIndexData[this.fearAndGreedIndexMode] + ?.historicalData ?? []), + { + date: resetHours(new Date()).toISOString(), + value: this.fearAndGreedIndex + } + ]; + } + + public onChangeFearAndGreedIndexMode( + aFearAndGreedIndexMode: FearAndGreedIndexMode + ) { + this.fearAndGreedIndexMode = aFearAndGreedIndexMode; + + this.initialize(); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } +} diff --git a/apps/client/src/app/components/markets/markets.html b/apps/client/src/app/components/markets/markets.html new file mode 100644 index 000000000..90ddbba06 --- /dev/null +++ b/apps/client/src/app/components/markets/markets.html @@ -0,0 +1,60 @@ +
    +

    Markets

    +
    +
    + @if (user?.settings?.isExperimentalFeatures) { +
    + +
    + } +
    + Last {{ numberOfDays }} Days +
    + + +
    +
    + +
    +
    + + @if (benchmarks?.length > 0) { +
    + + Calculations are based on delayed market data and may not be + displayed in real-time. +
    + } +
    +
    +
    diff --git a/apps/client/src/app/components/markets/markets.scss b/apps/client/src/app/components/markets/markets.scss new file mode 100644 index 000000000..5b523160d --- /dev/null +++ b/apps/client/src/app/components/markets/markets.scss @@ -0,0 +1,7 @@ +:host { + display: block; + + gf-line-chart { + aspect-ratio: 16 / 9; + } +} diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts index 0c575d985..caef1082f 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts @@ -18,6 +18,8 @@ import { ViewChild } from '@angular/core'; import { CountUp } from 'countup.js'; +import { addIcons } from 'ionicons'; +import { timeOutline } from 'ionicons/icons'; import { isNumber } from 'lodash'; @Component({ @@ -41,7 +43,9 @@ export class PortfolioPerformanceComponent implements OnChanges { @ViewChild('value') value: ElementRef; - public constructor(private notificationService: NotificationService) {} + public constructor(private notificationService: NotificationService) { + addIcons({ timeOutline }); + } public ngOnChanges() { this.precision = this.precision >= 0 ? this.precision : 2; diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts index 5c62cca87..e5b606255 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts @@ -2,6 +2,7 @@ import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { PortfolioPerformanceComponent } from './portfolio-performance.component'; @@ -9,7 +10,7 @@ import { PortfolioPerformanceComponent } from './portfolio-performance.component @NgModule({ declarations: [PortfolioPerformanceComponent], exports: [PortfolioPerformanceComponent], - imports: [CommonModule, GfValueComponent, NgxSkeletonLoaderModule], + imports: [CommonModule, GfValueComponent, IonIcon, NgxSkeletonLoaderModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class GfPortfolioPerformanceModule {} diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index 2a8880225..19f125523 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -7,11 +7,11 @@
    - {{ summary?.ordersCount }} - {summary?.ordersCount, plural, + {{ summary?.activityCount }} + {summary?.activityCount, plural, =1 {activity} other {activities} } @@ -117,8 +117,8 @@ Net Performance (TWR)(ROAI)
    @@ -152,18 +152,6 @@ />
    -
    -
    Valuables
    -
    - -
    -
    Emergency Fund
    {{ data.rule.name }}
    +
    {{ data.rule.categoryName }} › {{ data.rule.name }}
    @if ( diff --git a/apps/client/src/app/components/rule/rule.component.scss b/apps/client/src/app/components/rule/rule.component.scss index 54ddce823..adb081abc 100644 --- a/apps/client/src/app/components/rule/rule.component.scss +++ b/apps/client/src/app/components/rule/rule.component.scss @@ -2,7 +2,7 @@ display: block; .icon-container { - background-color: rgba(var(--dark-primary-text), 0.05); + background-color: rgba(var(--palette-foreground-base), 0.02); border-radius: 0.25rem; height: 2rem; diff --git a/apps/client/src/app/components/rule/rule.component.ts b/apps/client/src/app/components/rule/rule.component.ts index 7c358e1cb..4ea7d0ec6 100644 --- a/apps/client/src/app/components/rule/rule.component.ts +++ b/apps/client/src/app/components/rule/rule.component.ts @@ -14,6 +14,13 @@ import { Output } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; +import { addIcons } from 'ionicons'; +import { + checkmarkCircleOutline, + ellipsisHorizontal, + removeCircleOutline, + warningOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; @@ -41,7 +48,14 @@ export class RuleComponent implements OnInit { public constructor( private deviceService: DeviceDetectorService, private dialog: MatDialog - ) {} + ) { + addIcons({ + checkmarkCircleOutline, + ellipsisHorizontal, + removeCircleOutline, + warningOutline + }); + } public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; diff --git a/apps/client/src/app/components/rule/rule.module.ts b/apps/client/src/app/components/rule/rule.module.ts index d2cba5b25..43c22e55c 100644 --- a/apps/client/src/app/components/rule/rule.module.ts +++ b/apps/client/src/app/components/rule/rule.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; +import { IonIcon } from '@ionic/angular/standalone'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { RuleComponent } from './rule.component'; @@ -11,6 +12,7 @@ import { RuleComponent } from './rule.component'; exports: [RuleComponent], imports: [ CommonModule, + IonIcon, MatButtonModule, MatMenuModule, NgxSkeletonLoaderModule diff --git a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts index d98c54719..48f17b886 100644 --- a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts +++ b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts @@ -1,5 +1,18 @@ -import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + Inject, + OnInit +} from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { addIcons } from 'ionicons'; +import { arrowForwardOutline, checkmarkCircleOutline } from 'ionicons/icons'; +import ms from 'ms'; +import { interval, Subject } from 'rxjs'; +import { take, takeUntil, tap } from 'rxjs/operators'; import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces'; @@ -11,20 +24,49 @@ import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces'; templateUrl: 'subscription-interstitial-dialog.html', standalone: false }) -export class SubscriptionInterstitialDialog { - private readonly VARIANTS_COUNT = 2; +export class SubscriptionInterstitialDialog implements OnInit { + private static readonly SKIP_BUTTON_DELAY_IN_SECONDS = 5; + private static readonly VARIANTS_COUNT = 2; - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; + public remainingSkipButtonDelay = + SubscriptionInterstitialDialog.SKIP_BUTTON_DELAY_IN_SECONDS; + public routerLinkPricing = publicRoutes.pricing.routerLink; public variantIndex: number; + private unsubscribeSubject = new Subject(); + public constructor( + private changeDetectorRef: ChangeDetectorRef, @Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams, public dialogRef: MatDialogRef ) { - this.variantIndex = Math.floor(Math.random() * this.VARIANTS_COUNT); + this.variantIndex = Math.floor( + Math.random() * SubscriptionInterstitialDialog.VARIANTS_COUNT + ); + + addIcons({ arrowForwardOutline, checkmarkCircleOutline }); + } + + public ngOnInit() { + interval(ms('1 second')) + .pipe( + take(SubscriptionInterstitialDialog.SKIP_BUTTON_DELAY_IN_SECONDS), + tap(() => { + this.remainingSkipButtonDelay--; + + this.changeDetectorRef.markForCheck(); + }), + takeUntil(this.unsubscribeSubject) + ) + .subscribe(); } public closeDialog() { this.dialogRef.close({}); } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } } diff --git a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html index b9b96f9a8..92d9da835 100644 --- a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html +++ b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -51,7 +51,16 @@
    - +
    - >(); - - public optionFormControl = new FormControl(undefined); - - public ngOnChanges() { - this.optionFormControl.setValue(this.defaultValue); - } - - public onValueChange() { - this.change.emit({ value: this.optionFormControl.value }); - } -} diff --git a/apps/client/src/app/components/toggle/toggle.module.ts b/apps/client/src/app/components/toggle/toggle.module.ts deleted file mode 100644 index d27ff4a16..000000000 --- a/apps/client/src/app/components/toggle/toggle.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; -import { MatRadioModule } from '@angular/material/radio'; - -import { ToggleComponent } from './toggle.component'; - -@NgModule({ - declarations: [ToggleComponent], - exports: [ToggleComponent], - imports: [CommonModule, MatRadioModule, ReactiveFormsModule] -}) -export class GfToggleModule {} diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index 6f111f456..202e1b8ae 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1,38 +1,69 @@ import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; +import { GfAccessTableComponent } from '@ghostfolio/client/components/access-table/access-table.component'; +import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; +import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { DataService } from '@ghostfolio/client/services/data.service'; +import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { Access, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + CUSTOM_ELEMENTS_SCHEMA, OnDestroy, OnInit } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { ActivatedRoute, Router } from '@angular/router'; +import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { addOutline, eyeOffOutline, eyeOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { EMPTY, Subject } from 'rxjs'; +import { catchError, takeUntil } from 'rxjs/operators'; import { CreateOrUpdateAccessDialog } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; +import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-dialog/create-or-update-access-dialog.module'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'has-fab' }, + imports: [ + GfAccessTableComponent, + GfCreateOrUpdateAccessDialogModule, + GfPremiumIndicatorComponent, + IonIcon, + MatButtonModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-access', styleUrls: ['./user-account-access.scss'], - templateUrl: './user-account-access.html', - standalone: false + templateUrl: './user-account-access.html' }) -export class UserAccountAccessComponent implements OnDestroy, OnInit { +export class GfUserAccountAccessComponent implements OnDestroy, OnInit { public accessesGet: Access[]; public accessesGive: Access[]; public deviceType: string; public hasPermissionToCreateAccess: boolean; public hasPermissionToDeleteAccess: boolean; + public hasPermissionToUpdateOwnAccessToken: boolean; + public isAccessTokenHidden = true; + public updateOwnAccessTokenForm = this.formBuilder.group({ + accessToken: ['', Validators.required] + }); public user: User; private unsubscribeSubject = new Subject(); @@ -42,8 +73,11 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit { private dataService: DataService, private deviceService: DeviceDetectorService, private dialog: MatDialog, + private formBuilder: FormBuilder, + private notificationService: NotificationService, private route: ActivatedRoute, private router: Router, + private tokenStorageService: TokenStorageService, private userService: UserService ) { const { globalPermissions } = this.dataService.fetchInfo(); @@ -69,6 +103,11 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit { permissions.deleteAccess ); + this.hasPermissionToUpdateOwnAccessToken = hasPermission( + this.user.permissions, + permissions.updateOwnAccessToken + ); + this.changeDetectorRef.markForCheck(); } }); @@ -80,6 +119,8 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit { this.openCreateAccessDialog(); } }); + + addIcons({ addOutline, eyeOffOutline, eyeOutline }); } public ngOnInit() { @@ -99,6 +140,41 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit { }); } + public onGenerateAccessToken() { + this.notificationService.confirm({ + confirmFn: () => { + this.dataService + .updateOwnAccessToken({ + accessToken: this.updateOwnAccessTokenForm.get('accessToken').value + }) + .pipe( + catchError(() => { + this.notificationService.alert({ + title: $localize`Oops! Incorrect Security Token.` + }); + + return EMPTY; + }), + takeUntil(this.unsubscribeSubject) + ) + .subscribe(({ accessToken }) => { + this.notificationService.alert({ + discardFn: () => { + this.tokenStorageService.signOut(); + this.userService.remove(); + + document.location.href = `/${document.documentElement.lang}`; + }, + message: accessToken, + title: $localize`Security token` + }); + }); + }, + confirmType: ConfirmationDialogType.Warn, + title: $localize`Do you really want to generate a new security token?` + }); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/components/user-account-access/user-account-access.html b/apps/client/src/app/components/user-account-access/user-account-access.html index efb918984..2979fd6fa 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.html +++ b/apps/client/src/app/components/user-account-access/user-account-access.html @@ -1,3 +1,53 @@ +@if (hasPermissionToUpdateOwnAccessToken) { +
    +

    Security Token

    +
    +
    + + Security Token + + + +
    + +
    +
    +
    +
    +} +
    @if (accessesGet.length > 0) {

    Received Access

    diff --git a/apps/client/src/app/components/user-account-access/user-account-access.module.ts b/apps/client/src/app/components/user-account-access/user-account-access.module.ts deleted file mode 100644 index 93270ee3c..000000000 --- a/apps/client/src/app/components/user-account-access/user-account-access.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { RouterModule } from '@angular/router'; - -import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-dialog/create-or-update-access-dialog.module'; -import { UserAccountAccessComponent } from './user-account-access.component'; - -@NgModule({ - declarations: [UserAccountAccessComponent], - exports: [UserAccountAccessComponent], - imports: [ - CommonModule, - GfCreateOrUpdateAccessDialogModule, - GfPortfolioAccessTableModule, - GfPremiumIndicatorComponent, - MatButtonModule, - MatDialogModule, - RouterModule - ] -}) -export class GfUserAccountAccessModule {} diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts index 6139d173e..f2f63b32b 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts @@ -5,18 +5,21 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { getDateFormatString } from '@ghostfolio/common/helper'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; -import { - MatSnackBar, - MatSnackBarRef, - TextOnlySnackBar -} from '@angular/material/snack-bar'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; import ms, { StringValue } from 'ms'; import { StripeService } from 'ngx-stripe'; import { EMPTY, Subject } from 'rxjs'; @@ -24,12 +27,19 @@ import { catchError, switchMap, takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + GfMembershipCardComponent, + GfPremiumIndicatorComponent, + MatButtonModule, + MatCardModule, + RouterModule + ], selector: 'gf-user-account-membership', styleUrls: ['./user-account-membership.scss'], - templateUrl: './user-account-membership.html', - standalone: false + templateUrl: './user-account-membership.html' }) -export class UserAccountMembershipComponent implements OnDestroy { +export class GfUserAccountMembershipComponent implements OnDestroy { public baseCurrency: string; public coupon: number; public couponId: string; @@ -40,8 +50,7 @@ export class UserAccountMembershipComponent implements OnDestroy { public hasPermissionToUpdateUserSettings: boolean; public price: number; public priceId: string; - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; - public snackBarRef: MatSnackBarRef; + public routerLinkPricing = publicRoutes.pricing.routerLink; public trySubscriptionMail = 'mailto:hi@ghostfol.io?Subject=Ghostfolio Premium Trial&body=Hello%0D%0DI am interested in Ghostfolio Premium. Can you please send me a coupon code to try it for some time?%0D%0DKind regards'; public user: User; @@ -56,8 +65,7 @@ export class UserAccountMembershipComponent implements OnDestroy { private stripeService: StripeService, private userService: UserService ) { - const { baseCurrency, globalPermissions, subscriptionOffers } = - this.dataService.fetchInfo(); + const { baseCurrency, globalPermissions } = this.dataService.fetchInfo(); this.baseCurrency = baseCurrency; @@ -86,18 +94,12 @@ export class UserAccountMembershipComponent implements OnDestroy { permissions.updateUserSettings ); - this.coupon = - subscriptionOffers?.[this.user.subscription.offer]?.coupon; - this.couponId = - subscriptionOffers?.[this.user.subscription.offer]?.couponId; + this.coupon = this.user?.subscription?.offer?.coupon; + this.couponId = this.user?.subscription?.offer?.couponId; this.durationExtension = - subscriptionOffers?.[ - this.user.subscription.offer - ]?.durationExtension; - this.price = - subscriptionOffers?.[this.user.subscription.offer]?.price; - this.priceId = - subscriptionOffers?.[this.user.subscription.offer]?.priceId; + this.user?.subscription?.offer?.durationExtension; + this.price = this.user?.subscription?.offer?.price; + this.priceId = this.user?.subscription?.offer?.priceId; this.changeDetectorRef.markForCheck(); } @@ -186,22 +188,22 @@ export class UserAccountMembershipComponent implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(() => { - this.snackBarRef = this.snackBar.open( + const snackBarRef = this.snackBar.open( '✅ ' + $localize`Coupon code has been redeemed`, $localize`Reload`, { - duration: 3000 + duration: ms('3 seconds') } ); - this.snackBarRef + snackBarRef .afterDismissed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { window.location.reload(); }); - this.snackBarRef + snackBarRef .onAction() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.html b/apps/client/src/app/components/user-account-membership/user-account-membership.html index 64dd2ce8f..eadf85612 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.html +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.html @@ -14,14 +14,10 @@ hasPermissionForSubscription && hasPermissionToUpdateUserSettings ) { @if (price) { diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts deleted file mode 100644 index 90646c09e..000000000 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { RouterModule } from '@angular/router'; - -import { UserAccountMembershipComponent } from './user-account-membership.component'; - -@NgModule({ - declarations: [UserAccountMembershipComponent], - exports: [UserAccountMembershipComponent], - imports: [ - CommonModule, - GfMembershipCardComponent, - GfPremiumIndicatorComponent, - GfValueComponent, - MatButtonModule, - MatCardModule, - RouterModule - ] -}) -export class GfUserAccountMembershipModule {} diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index c6f1d4d70..a36ff3229 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -17,25 +17,55 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + CUSTOM_ELEMENTS_SCHEMA, OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; -import { MatSlideToggleChange } from '@angular/material/slide-toggle'; +import { + FormBuilder, + FormsModule, + ReactiveFormsModule, + Validators +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { + MatSlideToggleChange, + MatSlideToggleModule +} from '@angular/material/slide-toggle'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { format, parseISO } from 'date-fns'; -import { uniq } from 'lodash'; +import { addIcons } from 'ionicons'; +import { eyeOffOutline, eyeOutline } from 'ionicons/icons'; +import ms from 'ms'; import { EMPTY, Subject, throwError } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + FormsModule, + IonIcon, + MatButtonModule, + MatCardModule, + MatFormFieldModule, + MatInputModule, + MatSelectModule, + MatSlideToggleModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-settings', styleUrls: ['./user-account-settings.scss'], - templateUrl: './user-account-settings.html', - standalone: false + templateUrl: './user-account-settings.html' }) -export class UserAccountSettingsComponent implements OnDestroy, OnInit { +export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public appearancePlaceholder = $localize`Auto`; public baseCurrency: string; public currencies: string[] = []; @@ -62,6 +92,7 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit { 'pl', 'pt', 'tr', + 'uk', 'zh' ]; public user: User; @@ -106,11 +137,13 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit { ); this.locales.push(this.user.settings.locale); - this.locales = uniq(this.locales.sort()); + this.locales = Array.from(new Set(this.locales)).sort(); this.changeDetectorRef.markForCheck(); } }); + + addIcons({ eyeOffOutline, eyeOutline }); } public ngOnInit() { @@ -300,7 +333,9 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit { this.snackBar.open( $localize`Oops! There was an error setting up biometric authentication.`, undefined, - { duration: 3000 } + { + duration: ms('3 seconds') + } ); return throwError(() => { diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.html b/apps/client/src/app/components/user-account-settings/user-account-settings.html index 3896bbb46..e6ab544c8 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.html +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2,25 +2,7 @@

    Settings

    -
    -
    -
    Presenter View
    -
    - Protection for sensitive information like absolute performances and - quantity values -
    -
    -
    - -
    -
    -
    +
    @@ -43,6 +25,32 @@
    + @if (user?.settings?.isExperimentalFeatures && !user?.subscription) { +
    +
    + Performance Calculation +
    +
    + + + Return on Average Investment (ROAI) + + +
    +
    + }
    Language
    @@ -78,12 +86,10 @@ >) } - @if (user?.settings?.isExperimentalFeatures) { - Chinese (Community) - } + Chinese (Community) Español (Community)Nederlands (Community) - @if (user?.settings?.isExperimentalFeatures) { - Polski (Community) - } + Polski (Community) Português (Community)Türkçe (Community) + @if (user?.settings?.isExperimentalFeatures) { + Українська (Community) + }
    @@ -168,6 +178,24 @@
    +
    +
    +
    Presenter View
    +
    + Protection for sensitive information like absolute performances and + quantity values +
    +
    +
    + +
    +
    Zen Mode
    diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts deleted file mode 100644 index e0fe2e1e2..000000000 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; -import { MatSlideToggleModule } from '@angular/material/slide-toggle'; -import { RouterModule } from '@angular/router'; - -import { UserAccountSettingsComponent } from './user-account-settings.component'; - -@NgModule({ - declarations: [UserAccountSettingsComponent], - exports: [UserAccountSettingsComponent], - imports: [ - CommonModule, - FormsModule, - GfValueComponent, - MatButtonModule, - MatCardModule, - MatFormFieldModule, - MatInputModule, - MatSelectModule, - MatSlideToggleModule, - ReactiveFormsModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfUserAccountSettingsModule {} diff --git a/apps/client/src/app/components/world-map-chart/world-map-chart.component.html b/apps/client/src/app/components/world-map-chart/world-map-chart.component.html index 5de7ea9d0..87bc08672 100644 --- a/apps/client/src/app/components/world-map-chart/world-map-chart.component.html +++ b/apps/client/src/app/components/world-map-chart/world-map-chart.component.html @@ -8,4 +8,4 @@ /> } -
    +
    diff --git a/apps/client/src/app/core/auth.guard.ts b/apps/client/src/app/core/auth.guard.ts index 7a75728ca..c26419031 100644 --- a/apps/client/src/app/core/auth.guard.ts +++ b/apps/client/src/app/core/auth.guard.ts @@ -1,6 +1,7 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { Injectable } from '@angular/core'; import { @@ -11,24 +12,8 @@ import { import { EMPTY } from 'rxjs'; import { catchError } from 'rxjs/operators'; -import { paths } from './paths'; - @Injectable({ providedIn: 'root' }) export class AuthGuard { - private static PUBLIC_PAGE_ROUTES = [ - `/${paths.about}`, - '/blog', - '/demo', - `/${paths.faq}`, - `/${paths.features}`, - `/${paths.markets}`, - '/open', - '/p', - `/${paths.pricing}`, - `/${paths.register}`, - `/${paths.resources}` - ]; - public constructor( private dataService: DataService, private router: Router, @@ -49,21 +34,25 @@ export class AuthGuard { .pipe( catchError(() => { if (utmSource === 'ios') { - this.router.navigate(['/demo']); + this.router.navigate(publicRoutes.demo.routerLink); resolve(false); } else if (utmSource === 'trusted-web-activity') { - this.router.navigate(['/' + $localize`register`]); + this.router.navigate(publicRoutes.register.routerLink); resolve(false); } else if ( - AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) => { - const [, url] = state.url.split('/'); - return `/${url}` === publicPageRoute; - })?.length > 0 + Object.values(publicRoutes) + .map(({ path }) => { + return `/${path}`; + }) + .some((publicPageRoute) => { + const [, url] = decodeURIComponent(state.url).split('/'); + return `/${url}` === publicPageRoute; + }) ) { resolve(true); return EMPTY; } else if (state.url !== '/start') { - this.router.navigate(['/start']); + this.router.navigate(publicRoutes.start.routerLink); resolve(false); return EMPTY; } @@ -89,26 +78,26 @@ export class AuthGuard { resolve(true); return; } else if ( - state.url.startsWith('/home') && + state.url.startsWith(`/${internalRoutes.home.path}`) && user.settings.viewMode === 'ZEN' ) { - this.router.navigate(['/zen']); + this.router.navigate(internalRoutes.zen.routerLink); resolve(false); return; - } else if (state.url.startsWith('/start')) { + } else if (state.url.startsWith(`/${publicRoutes.start.path}`)) { if (user.settings.viewMode === 'ZEN') { - this.router.navigate(['/zen']); + this.router.navigate(internalRoutes.zen.routerLink); } else { - this.router.navigate(['/home']); + this.router.navigate(internalRoutes.home.routerLink); } resolve(false); return; } else if ( - state.url.startsWith('/zen') && + state.url.startsWith(`/${internalRoutes.zen.path}`) && user.settings.viewMode === 'DEFAULT' ) { - this.router.navigate(['/home']); + this.router.navigate(internalRoutes.home.routerLink); resolve(false); return; } diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 203d3adf5..c2eef4175 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -2,6 +2,7 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { InfoItem } from '@ghostfolio/common/interfaces'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { HTTP_INTERCEPTORS, @@ -19,6 +20,7 @@ import { } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { StatusCodes } from 'http-status-codes'; +import ms from 'ms'; import { Observable, throwError } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; @@ -54,13 +56,19 @@ export class HttpResponseInterceptor implements HttpInterceptor { ' ' + $localize`Please try again later.`, undefined, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); - } else if (!error.url.includes('/auth')) { + } else if ( + !error.url.includes(internalRoutes.auth.routerLink.join('')) + ) { this.snackBarRef = this.snackBar.open( $localize`This action is not allowed.`, undefined, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); } @@ -69,7 +77,7 @@ export class HttpResponseInterceptor implements HttpInterceptor { }); this.snackBarRef.onAction().subscribe(() => { - this.router.navigate(['/' + $localize`pricing`]); + this.router.navigate(publicRoutes.pricing.routerLink); }); } } else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) { @@ -79,7 +87,9 @@ export class HttpResponseInterceptor implements HttpInterceptor { ' ' + $localize`Please try again later.`, $localize`Okay`, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); this.snackBarRef.afterDismissed().subscribe(() => { @@ -101,10 +111,12 @@ export class HttpResponseInterceptor implements HttpInterceptor { }); } } else if (error.status === StatusCodes.UNAUTHORIZED) { - if (this.webAuthnService.isEnabled()) { - this.router.navigate(['/webauthn']); - } else if (!error.url.includes('/data-providers/ghostfolio/status')) { - this.tokenStorageService.signOut(); + if (!error.url.includes('/data-providers/ghostfolio/status')) { + if (this.webAuthnService.isEnabled()) { + this.router.navigate(internalRoutes.webauthn.routerLink); + } else { + this.tokenStorageService.signOut(); + } } } diff --git a/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts b/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts index 8aefe84cf..98b6043eb 100644 --- a/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts +++ b/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts @@ -1,4 +1,3 @@ -import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; @@ -6,7 +5,7 @@ import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { IAlertDialogParams } from './interfaces/interfaces'; @Component({ - imports: [CommonModule, MatButtonModule, MatDialogModule], + imports: [MatButtonModule, MatDialogModule], selector: 'gf-alert-dialog', styleUrls: ['./alert-dialog.scss'], templateUrl: './alert-dialog.html' diff --git a/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts b/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts index 9aced99cc..88e5113d7 100644 --- a/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts +++ b/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts @@ -1,4 +1,3 @@ -import { CommonModule } from '@angular/common'; import { Component, HostListener } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; @@ -7,7 +6,7 @@ import { ConfirmationDialogType } from './confirmation-dialog.type'; import { IConfirmDialogParams } from './interfaces/interfaces'; @Component({ - imports: [CommonModule, MatButtonModule, MatDialogModule], + imports: [MatButtonModule, MatDialogModule], selector: 'gf-confirmation-dialog', styleUrls: ['./confirmation-dialog.scss'], templateUrl: './confirmation-dialog.html' diff --git a/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts b/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts index 4ec634da9..6c8af4197 100644 --- a/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts +++ b/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts @@ -1,4 +1,3 @@ -import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; @@ -8,7 +7,6 @@ import { MatInputModule } from '@angular/material/input'; @Component({ imports: [ - CommonModule, FormsModule, MatButtonModule, MatDialogModule, diff --git a/apps/client/src/app/core/paths.ts b/apps/client/src/app/core/paths.ts deleted file mode 100644 index 801228bba..000000000 --- a/apps/client/src/app/core/paths.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const paths = { - about: $localize`about`, - faq: $localize`faq`, - features: $localize`features`, - license: $localize`license`, - markets: $localize`markets`, - pricing: $localize`pricing`, - privacyPolicy: $localize`privacy-policy`, - register: $localize`register`, - resources: $localize`resources` -}; diff --git a/apps/client/src/app/pages/about/about-page-routing.module.ts b/apps/client/src/app/pages/about/about-page-routing.module.ts deleted file mode 100644 index 060030930..000000000 --- a/apps/client/src/app/pages/about/about-page-routing.module.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; -import { paths } from '@ghostfolio/client/core/paths'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AboutPageComponent } from './about-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - loadChildren: () => - import('./overview/about-overview-page.module').then( - (m) => m.AboutOverviewPageModule - ) - }, - { - path: 'changelog', - loadChildren: () => - import('./changelog/changelog-page.module').then( - (m) => m.ChangelogPageModule - ) - }, - { - path: paths.license, - loadChildren: () => - import('./license/license-page.module').then( - (m) => m.LicensePageModule - ) - }, - { - path: 'oss-friends', - loadChildren: () => - import('./oss-friends/oss-friends-page.module').then( - (m) => m.OpenSourceSoftwareFriendsPageModule - ) - }, - { - path: paths.privacyPolicy, - loadChildren: () => - import('./privacy-policy/privacy-policy-page.module').then( - (m) => m.PrivacyPolicyPageModule - ) - } - ], - component: AboutPageComponent, - path: '', - title: $localize`About` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AboutPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/about-page.component.ts b/apps/client/src/app/pages/about/about-page.component.ts index 399cba238..4fe6a57e3 100644 --- a/apps/client/src/app/pages/about/about-page.component.ts +++ b/apps/client/src/app/pages/about/about-page.component.ts @@ -2,18 +2,38 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + documentTextOutline, + happyOutline, + informationCircleOutline, + ribbonOutline, + shieldCheckmarkOutline, + sparklesOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, + imports: [IonIcon, MatTabsModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-about-page', styleUrls: ['./about-page.scss'], - templateUrl: './about-page.html', - standalone: false + templateUrl: './about-page.html' }) export class AboutPageComponent implements OnDestroy, OnInit { public deviceType: string; @@ -41,29 +61,38 @@ export class AboutPageComponent implements OnDestroy, OnInit { .subscribe((state) => { this.tabs = [ { - iconName: 'reader-outline', - label: $localize`About`, - path: ['/' + $localize`about`] + iconName: 'information-circle-outline', + label: publicRoutes.about.title, + routerLink: publicRoutes.about.routerLink }, { iconName: 'sparkles-outline', - label: $localize`Changelog`, - path: ['/' + $localize`about`, 'changelog'] + label: publicRoutes.about.subRoutes.changelog.title, + routerLink: publicRoutes.about.subRoutes.changelog.routerLink }, { iconName: 'ribbon-outline', - label: $localize`License`, - path: ['/' + $localize`about`, $localize`license`] + label: publicRoutes.about.subRoutes.license.title, + routerLink: publicRoutes.about.subRoutes.license.routerLink, + showCondition: !this.hasPermissionForSubscription } ]; if (state?.user) { this.tabs.push({ iconName: 'shield-checkmark-outline', - label: $localize`Privacy Policy`, - path: ['/' + $localize`about`, $localize`privacy-policy`], + label: publicRoutes.about.subRoutes.privacyPolicy.title, + routerLink: publicRoutes.about.subRoutes.privacyPolicy.routerLink, showCondition: this.hasPermissionForSubscription }); + + this.tabs.push({ + iconName: 'document-text-outline', + label: publicRoutes.about.subRoutes.termsOfService.title, + routerLink: publicRoutes.about.subRoutes.termsOfService.routerLink, + showCondition: this.hasPermissionForSubscription + }); + this.user = state.user; this.changeDetectorRef.markForCheck(); @@ -71,10 +100,19 @@ export class AboutPageComponent implements OnDestroy, OnInit { this.tabs.push({ iconName: 'happy-outline', - label: 'OSS Friends', - path: ['/' + $localize`about`, 'oss-friends'] + label: publicRoutes.about.subRoutes.ossFriends.title, + routerLink: publicRoutes.about.subRoutes.ossFriends.routerLink }); }); + + addIcons({ + documentTextOutline, + happyOutline, + informationCircleOutline, + ribbonOutline, + shieldCheckmarkOutline, + sparklesOutline + }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/about/about-page.html b/apps/client/src/app/pages/about/about-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/about/about-page.html +++ b/apps/client/src/app/pages/about/about-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > + import('./overview/about-overview-page.routes').then((m) => m.routes) + }, + { + path: publicRoutes.about.subRoutes.changelog.path, + loadChildren: () => + import('./changelog/changelog-page.routes').then((m) => m.routes) + }, + { + path: publicRoutes.about.subRoutes.license.path, + loadChildren: () => + import('./license/license-page.routes').then((m) => m.routes) + }, + { + path: publicRoutes.about.subRoutes.ossFriends.path, + loadChildren: () => + import('./oss-friends/oss-friends-page.routes').then((m) => m.routes) + }, + { + path: publicRoutes.about.subRoutes.privacyPolicy.path, + loadChildren: () => + import('./privacy-policy/privacy-policy-page.routes').then( + (m) => m.routes + ) + }, + { + path: publicRoutes.about.subRoutes.termsOfService.path, + loadChildren: () => + import('./terms-of-service/terms-of-service-page.routes').then( + (m) => m.routes + ) + } + ], + component: AboutPageComponent, + path: '', + title: publicRoutes.about.title + } +]; diff --git a/apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts b/apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts deleted file mode 100644 index 2aaef8282..000000000 --- a/apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ChangelogPageComponent } from './changelog-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: ChangelogPageComponent, - path: '', - title: $localize`Changelog` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ChangelogPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/changelog/changelog-page.component.ts b/apps/client/src/app/pages/about/changelog/changelog-page.component.ts index d086b70e3..69b397370 100644 --- a/apps/client/src/app/pages/about/changelog/changelog-page.component.ts +++ b/apps/client/src/app/pages/about/changelog/changelog-page.component.ts @@ -1,15 +1,23 @@ import { Component, OnDestroy } from '@angular/core'; +import { MarkdownModule } from 'ngx-markdown'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; @Component({ + imports: [MarkdownModule, NgxSkeletonLoaderModule], selector: 'gf-changelog-page', styleUrls: ['./changelog-page.scss'], - templateUrl: './changelog-page.html', - standalone: false + templateUrl: './changelog-page.html' }) -export class ChangelogPageComponent implements OnDestroy { +export class GfChangelogPageComponent implements OnDestroy { + public isLoading = true; + private unsubscribeSubject = new Subject(); + public onLoad() { + this.isLoading = false; + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/about/changelog/changelog-page.html b/apps/client/src/app/pages/about/changelog/changelog-page.html index 0a333f073..60b146df5 100644 --- a/apps/client/src/app/pages/about/changelog/changelog-page.html +++ b/apps/client/src/app/pages/about/changelog/changelog-page.html @@ -2,8 +2,51 @@

    Changelog

    + + @if (isLoading) { + + + + + + } +
    - +
    diff --git a/apps/client/src/app/pages/about/changelog/changelog-page.module.ts b/apps/client/src/app/pages/about/changelog/changelog-page.module.ts deleted file mode 100644 index 6c187824f..000000000 --- a/apps/client/src/app/pages/about/changelog/changelog-page.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MarkdownModule } from 'ngx-markdown'; - -import { ChangelogPageRoutingModule } from './changelog-page-routing.module'; -import { ChangelogPageComponent } from './changelog-page.component'; - -@NgModule({ - declarations: [ChangelogPageComponent], - imports: [ - ChangelogPageRoutingModule, - CommonModule, - MarkdownModule.forChild() - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class ChangelogPageModule {} diff --git a/apps/client/src/app/pages/about/changelog/changelog-page.routes.ts b/apps/client/src/app/pages/about/changelog/changelog-page.routes.ts new file mode 100644 index 000000000..523218acc --- /dev/null +++ b/apps/client/src/app/pages/about/changelog/changelog-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfChangelogPageComponent } from './changelog-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfChangelogPageComponent, + path: '', + title: publicRoutes.about.subRoutes.changelog.title + } +]; diff --git a/apps/client/src/app/pages/about/license/license-page-routing.module.ts b/apps/client/src/app/pages/about/license/license-page-routing.module.ts deleted file mode 100644 index 928eeb0f0..000000000 --- a/apps/client/src/app/pages/about/license/license-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { LicensePageComponent } from './license-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: LicensePageComponent, - path: '', - title: $localize`License` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class LicensePageRoutingModule {} diff --git a/apps/client/src/app/pages/about/license/license-page.component.ts b/apps/client/src/app/pages/about/license/license-page.component.ts index deec0de60..0dc5b2f51 100644 --- a/apps/client/src/app/pages/about/license/license-page.component.ts +++ b/apps/client/src/app/pages/about/license/license-page.component.ts @@ -1,13 +1,14 @@ import { Component, OnDestroy } from '@angular/core'; +import { MarkdownModule } from 'ngx-markdown'; import { Subject } from 'rxjs'; @Component({ + imports: [MarkdownModule], selector: 'gf-license-page', styleUrls: ['./license-page.scss'], - templateUrl: './license-page.html', - standalone: false + templateUrl: './license-page.html' }) -export class LicensePageComponent implements OnDestroy { +export class GfLicensePageComponent implements OnDestroy { private unsubscribeSubject = new Subject(); public ngOnDestroy() { diff --git a/apps/client/src/app/pages/about/license/license-page.module.ts b/apps/client/src/app/pages/about/license/license-page.module.ts deleted file mode 100644 index d18b48309..000000000 --- a/apps/client/src/app/pages/about/license/license-page.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MarkdownModule } from 'ngx-markdown'; - -import { LicensePageRoutingModule } from './license-page-routing.module'; -import { LicensePageComponent } from './license-page.component'; - -@NgModule({ - declarations: [LicensePageComponent], - imports: [LicensePageRoutingModule, CommonModule, MarkdownModule.forChild()], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class LicensePageModule {} diff --git a/apps/client/src/app/pages/about/license/license-page.routes.ts b/apps/client/src/app/pages/about/license/license-page.routes.ts new file mode 100644 index 000000000..1684bb0c5 --- /dev/null +++ b/apps/client/src/app/pages/about/license/license-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfLicensePageComponent } from './license-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfLicensePageComponent, + path: '', + title: publicRoutes.about.subRoutes.license.title + } +]; diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page-routing.module.ts b/apps/client/src/app/pages/about/oss-friends/oss-friends-page-routing.module.ts deleted file mode 100644 index 08040419d..000000000 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { OpenSourceSoftwareFriendsPageComponent } from './oss-friends-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: OpenSourceSoftwareFriendsPageComponent, - path: '', - title: 'OSS Friends' - } -]; - -@NgModule({ - exports: [RouterModule], - imports: [RouterModule.forChild(routes)] -}) -export class OpenSourceSoftwareFriendsPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts index 86dcd4ed3..bdbbdf9a7 100644 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts +++ b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts @@ -1,19 +1,28 @@ import { Component, OnDestroy } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { arrowForwardOutline } from 'ionicons/icons'; import { Subject } from 'rxjs'; const ossFriends = require('../../../../assets/oss-friends.json'); @Component({ + imports: [IonIcon, MatButtonModule, MatCardModule], selector: 'gf-oss-friends-page', styleUrls: ['./oss-friends-page.scss'], - templateUrl: './oss-friends-page.html', - standalone: false + templateUrl: './oss-friends-page.html' }) -export class OpenSourceSoftwareFriendsPageComponent implements OnDestroy { +export class GfOpenSourceSoftwareFriendsPageComponent implements OnDestroy { public ossFriends = ossFriends.data; private unsubscribeSubject = new Subject(); + public constructor() { + addIcons({ arrowForwardOutline }); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts deleted file mode 100644 index 95cf9c3c3..000000000 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; - -import { OpenSourceSoftwareFriendsPageRoutingModule } from './oss-friends-page-routing.module'; -import { OpenSourceSoftwareFriendsPageComponent } from './oss-friends-page.component'; - -@NgModule({ - declarations: [OpenSourceSoftwareFriendsPageComponent], - imports: [ - CommonModule, - MatButtonModule, - MatCardModule, - OpenSourceSoftwareFriendsPageRoutingModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class OpenSourceSoftwareFriendsPageModule {} diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.routes.ts b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.routes.ts new file mode 100644 index 000000000..8dbb9d52a --- /dev/null +++ b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfOpenSourceSoftwareFriendsPageComponent } from './oss-friends-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfOpenSourceSoftwareFriendsPageComponent, + path: '', + title: publicRoutes.about.subRoutes.ossFriends.title + } +]; diff --git a/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts b/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts deleted file mode 100644 index 989dddc9d..000000000 --- a/apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AboutOverviewPageComponent } from './about-overview-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: AboutOverviewPageComponent, - path: '', - title: $localize`About` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AboutOverviewPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.component.ts b/apps/client/src/app/pages/about/overview/about-overview-page.component.ts index 9dae545fa..d315f2cbd 100644 --- a/apps/client/src/app/pages/about/overview/about-overview-page.component.ts +++ b/apps/client/src/app/pages/about/overview/about-overview-page.component.ts @@ -2,23 +2,45 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + logoGithub, + logoLinkedin, + logoSlack, + logoX, + mail +} from 'ionicons/icons'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [CommonModule, IonIcon, MatButtonModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-about-overview-page', styleUrls: ['./about-overview-page.scss'], - templateUrl: './about-overview-page.html', - standalone: false + templateUrl: './about-overview-page.html' }) -export class AboutOverviewPageComponent implements OnDestroy, OnInit { +export class GfAboutOverviewPageComponent implements OnDestroy, OnInit { public hasPermissionForStatistics: boolean; public hasPermissionForSubscription: boolean; public isLoggedIn: boolean; - public routerLinkFaq = ['/' + $localize`:snake-case:faq`]; - public routerLinkFeatures = ['/' + $localize`:snake-case:features`]; + public routerLinkBlog = publicRoutes.blog.routerLink; + public routerLinkFaq = publicRoutes.faq.routerLink; + public routerLinkFeatures = publicRoutes.features.routerLink; + public routerLinkOpenStartup = publicRoutes.openStartup.routerLink; public user: User; private unsubscribeSubject = new Subject(); @@ -39,6 +61,8 @@ export class AboutOverviewPageComponent implements OnDestroy, OnInit { globalPermissions, permissions.enableSubscription ); + + addIcons({ logoGithub, logoLinkedin, logoSlack, logoX, mail }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.html b/apps/client/src/app/pages/about/overview/about-overview-page.html index 4d8ba9aa0..ce442fe27 100644 --- a/apps/client/src/app/pages/about/overview/about-overview-page.html +++ b/apps/client/src/app/pages/about/overview/about-overview-page.html @@ -23,7 +23,9 @@ > @if (hasPermissionForStatistics) { and we share aggregated -
    key metrics + key metrics of the platform’s performance } . The project has been initiated by @@ -68,14 +70,25 @@ or start a discussion at GitHub.

    + + + @@ -85,6 +98,7 @@ @@ -93,25 +107,28 @@ } - + - +

    @if (hasPermissionForSubscription) {
    @@ -119,6 +136,7 @@ diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.module.ts b/apps/client/src/app/pages/about/overview/about-overview-page.module.ts deleted file mode 100644 index 594f5b362..000000000 --- a/apps/client/src/app/pages/about/overview/about-overview-page.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { RouterModule } from '@angular/router'; - -import { AboutOverviewPageRoutingModule } from './about-overview-page-routing.module'; -import { AboutOverviewPageComponent } from './about-overview-page.component'; - -@NgModule({ - declarations: [AboutOverviewPageComponent], - imports: [ - AboutOverviewPageRoutingModule, - CommonModule, - MatButtonModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class AboutOverviewPageModule {} diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.routes.ts b/apps/client/src/app/pages/about/overview/about-overview-page.routes.ts new file mode 100644 index 000000000..79047855f --- /dev/null +++ b/apps/client/src/app/pages/about/overview/about-overview-page.routes.ts @@ -0,0 +1,14 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; + +import { Routes } from '@angular/router'; + +import { GfAboutOverviewPageComponent } from './about-overview-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfAboutOverviewPageComponent, + path: '', + title: $localize`About` + } +]; diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts deleted file mode 100644 index eb8dca803..000000000 --- a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { PrivacyPolicyPageComponent } from './privacy-policy-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: PrivacyPolicyPageComponent, - path: '', - title: $localize`Privacy Policy` - } -]; - -@NgModule({ - exports: [RouterModule], - imports: [RouterModule.forChild(routes)] -}) -export class PrivacyPolicyPageRoutingModule {} diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts index f08b4365d..78881cd2c 100644 --- a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts +++ b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts @@ -1,13 +1,14 @@ import { Component, OnDestroy } from '@angular/core'; +import { MarkdownModule } from 'ngx-markdown'; import { Subject } from 'rxjs'; @Component({ + imports: [MarkdownModule], selector: 'gf-privacy-policy-page', styleUrls: ['./privacy-policy-page.scss'], - templateUrl: './privacy-policy-page.html', - standalone: false + templateUrl: './privacy-policy-page.html' }) -export class PrivacyPolicyPageComponent implements OnDestroy { +export class GfPrivacyPolicyPageComponent implements OnDestroy { private unsubscribeSubject = new Subject(); public ngOnDestroy() { diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.module.ts b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.module.ts deleted file mode 100644 index b33aea784..000000000 --- a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MarkdownModule } from 'ngx-markdown'; - -import { PrivacyPolicyPageRoutingModule } from './privacy-policy-page-routing.module'; -import { PrivacyPolicyPageComponent } from './privacy-policy-page.component'; - -@NgModule({ - declarations: [PrivacyPolicyPageComponent], - imports: [ - CommonModule, - MarkdownModule.forChild(), - PrivacyPolicyPageRoutingModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class PrivacyPolicyPageModule {} diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.routes.ts b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.routes.ts new file mode 100644 index 000000000..e87436c17 --- /dev/null +++ b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfPrivacyPolicyPageComponent } from './privacy-policy-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfPrivacyPolicyPageComponent, + path: '', + title: publicRoutes.about.subRoutes.privacyPolicy.title + } +]; diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.scss b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.scss index b90d23078..4bba9df47 100644 --- a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.scss +++ b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.scss @@ -12,6 +12,14 @@ color: rgba(var(--palette-primary-300), 1); } } + + h2 { + font-size: 1.5rem; + } + + h3 { + font-size: 1.25rem; + } } } } diff --git a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts new file mode 100644 index 000000000..dbf07ef19 --- /dev/null +++ b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts @@ -0,0 +1,18 @@ +import { Component, OnDestroy } from '@angular/core'; +import { MarkdownModule } from 'ngx-markdown'; +import { Subject } from 'rxjs'; + +@Component({ + imports: [MarkdownModule], + selector: 'gf-terms-of-service-page', + styleUrls: ['./terms-of-service-page.scss'], + templateUrl: './terms-of-service-page.html' +}) +export class GfTermsOfServicePageComponent implements OnDestroy { + private unsubscribeSubject = new Subject(); + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } +} diff --git a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html new file mode 100644 index 000000000..b178ca138 --- /dev/null +++ b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html @@ -0,0 +1,10 @@ +
    +
    +
    +

    + Terms of Service +

    + +
    +
    +
    diff --git a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.routes.ts b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.routes.ts new file mode 100644 index 000000000..34d7a72d0 --- /dev/null +++ b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfTermsOfServicePageComponent } from './terms-of-service-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfTermsOfServicePageComponent, + path: '', + title: publicRoutes.about.subRoutes.termsOfService.title + } +]; diff --git a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.scss b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.scss new file mode 100644 index 000000000..4bba9df47 --- /dev/null +++ b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.scss @@ -0,0 +1,29 @@ +:host { + color: rgb(var(--dark-primary-text)); + display: block; + + ::ng-deep { + markdown { + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + } + } + + h2 { + font-size: 1.5rem; + } + + h3 { + font-size: 1.25rem; + } + } + } +} + +:host-context(.theme-dark) { + color: rgb(var(--light-primary-text)); +} diff --git a/apps/client/src/app/pages/accounts/accounts-page-routing.module.ts b/apps/client/src/app/pages/accounts/accounts-page-routing.module.ts deleted file mode 100644 index 59c708006..000000000 --- a/apps/client/src/app/pages/accounts/accounts-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AccountsPageComponent } from './accounts-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: AccountsPageComponent, - path: '', - title: $localize`Accounts` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AccountsPageRoutingModule {} diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index 70dfa028e..ff17c861f 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -2,7 +2,9 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto import { TransferBalanceDto } from '@ghostfolio/api/app/account/transfer-balance.dto'; import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto'; import { AccountDetailDialog } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.component'; +import { GfAccountDetailDialogModule } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.module'; import { AccountDetailDialogParams } from '@ghostfolio/client/components/account-detail-dialog/interfaces/interfaces'; +import { GfAccountsTableComponent } from '@ghostfolio/client/components/accounts-table/accounts-table.component'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -11,24 +13,32 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { Account as AccountModel } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { addOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { EMPTY, Subject, Subscription } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; -import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog/create-or-update-account-dialog.component'; -import { TransferBalanceDialog } from './transfer-balance/transfer-balance-dialog.component'; +import { GfCreateOrUpdateAccountDialogComponent } from './create-or-update-account-dialog/create-or-update-account-dialog.component'; +import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-balance-dialog.component'; @Component({ host: { class: 'has-fab page' }, + imports: [ + GfAccountDetailDialogModule, + GfAccountsTableComponent, + MatButtonModule, + RouterModule + ], selector: 'gf-accounts-page', styleUrls: ['./accounts-page.scss'], - templateUrl: './accounts-page.html', - standalone: false + templateUrl: './accounts-page.html' }) -export class AccountsPageComponent implements OnDestroy, OnInit { +export class GfAccountsPageComponent implements OnDestroy, OnInit { public accounts: AccountModel[]; public deviceType: string; public hasImpersonationId: boolean; @@ -77,6 +87,8 @@ export class AccountsPageComponent implements OnDestroy, OnInit { this.openTransferBalanceDialog(); } }); + + addIcons({ addOutline }); } public ngOnInit() { @@ -173,7 +185,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit { name, platformId }: AccountModel) { - const dialogRef = this.dialog.open(CreateOrUpdateAccountDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateAccountDialogComponent, { data: { account: { balance, @@ -227,7 +239,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit { accountId: aAccountId, deviceType: this.deviceType, hasImpersonationId: this.hasImpersonationId, - hasPermissionToCreateOrder: + hasPermissionToCreateActivity: !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createOrder) && !this.user?.settings?.isRestrictedView @@ -247,7 +259,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit { } private openCreateAccountDialog() { - const dialogRef = this.dialog.open(CreateOrUpdateAccountDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateAccountDialogComponent, { data: { account: { balance: 0, @@ -289,7 +301,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit { } private openTransferBalanceDialog() { - const dialogRef = this.dialog.open(TransferBalanceDialog, { + const dialogRef = this.dialog.open(GfTransferBalanceDialogComponent, { data: { accounts: this.accounts }, diff --git a/apps/client/src/app/pages/accounts/accounts-page.module.ts b/apps/client/src/app/pages/accounts/accounts-page.module.ts deleted file mode 100644 index 118aff532..000000000 --- a/apps/client/src/app/pages/accounts/accounts-page.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { GfAccountDetailDialogModule } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.module'; -import { GfAccountsTableModule } from '@ghostfolio/client/components/accounts-table/accounts-table.module'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { RouterModule } from '@angular/router'; - -import { AccountsPageRoutingModule } from './accounts-page-routing.module'; -import { AccountsPageComponent } from './accounts-page.component'; -import { GfCreateOrUpdateAccountDialogModule } from './create-or-update-account-dialog/create-or-update-account-dialog.module'; -import { GfTransferBalanceDialogModule } from './transfer-balance/transfer-balance-dialog.module'; - -@NgModule({ - declarations: [AccountsPageComponent], - imports: [ - AccountsPageRoutingModule, - CommonModule, - GfAccountDetailDialogModule, - GfAccountsTableModule, - GfCreateOrUpdateAccountDialogModule, - GfTransferBalanceDialogModule, - MatButtonModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class AccountsPageModule {} diff --git a/apps/client/src/app/pages/accounts/accounts-page.routes.ts b/apps/client/src/app/pages/accounts/accounts-page.routes.ts new file mode 100644 index 000000000..e4edc39c1 --- /dev/null +++ b/apps/client/src/app/pages/accounts/accounts-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfAccountsPageComponent } from './accounts-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfAccountsPageComponent, + path: '', + title: internalRoutes.accounts.title + } +]; diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index 15f4c35ee..beb815e0c 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -2,7 +2,10 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto'; import { DataService } from '@ghostfolio/client/services/data.service'; import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; +import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; +import { CommonModule, NgClass } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -13,10 +16,20 @@ import { AbstractControl, FormBuilder, FormGroup, + ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; import { Platform } from '@prisma/client'; import { Observable, Subject } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @@ -24,14 +37,26 @@ import { map, startWith } from 'rxjs/operators'; import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, + imports: [ + CommonModule, + GfCurrencySelectorComponent, + GfEntityLogoComponent, + MatAutocompleteModule, + MatButtonModule, + MatCheckboxModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + NgClass, + ReactiveFormsModule + ], selector: 'gf-create-or-update-account-dialog', - changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./create-or-update-account-dialog.scss'], - templateUrl: 'create-or-update-account-dialog.html', - standalone: false + templateUrl: 'create-or-update-account-dialog.html' }) -export class CreateOrUpdateAccountDialog implements OnDestroy { +export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { public accountForm: FormGroup; public currencies: string[] = []; public filteredPlatforms: Observable; @@ -42,7 +67,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateAccountDialogParams, private dataService: DataService, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private formBuilder: FormBuilder ) {} diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html index af97bfce3..a38baa6ec 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -61,7 +61,7 @@ ) { - , + public dialogRef: MatDialogRef, private formBuilder: FormBuilder ) {} diff --git a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html index 69734b8f9..50c96be86 100644 --- a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html +++ b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html @@ -13,11 +13,11 @@ @for (account of accounts; track account) {
    - @if (account.Platform?.url) { - } {{ account.name }} @@ -34,11 +34,11 @@ @for (account of accounts; track account) {
    - @if (account.Platform?.url) { - } {{ account.name }} diff --git a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.module.ts b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.module.ts deleted file mode 100644 index b83ccbb9d..000000000 --- a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.module.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; - -import { TransferBalanceDialog } from './transfer-balance-dialog.component'; - -@NgModule({ - declarations: [TransferBalanceDialog], - imports: [ - CommonModule, - GfAssetProfileIconComponent, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - MatSelectModule, - ReactiveFormsModule - ] -}) -export class GfTransferBalanceDialogModule {} diff --git a/apps/client/src/app/pages/admin/admin-page-routing.module.ts b/apps/client/src/app/pages/admin/admin-page-routing.module.ts deleted file mode 100644 index a6a69641c..000000000 --- a/apps/client/src/app/pages/admin/admin-page-routing.module.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { AdminJobsComponent } from '@ghostfolio/client/components/admin-jobs/admin-jobs.component'; -import { AdminMarketDataComponent } from '@ghostfolio/client/components/admin-market-data/admin-market-data.component'; -import { AdminOverviewComponent } from '@ghostfolio/client/components/admin-overview/admin-overview.component'; -import { AdminSettingsComponent } from '@ghostfolio/client/components/admin-settings/admin-settings.component'; -import { AdminUsersComponent } from '@ghostfolio/client/components/admin-users/admin-users.component'; -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AdminPageComponent } from './admin-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - component: AdminOverviewComponent, - title: $localize`Admin Control` - }, - { - path: 'jobs', - component: AdminJobsComponent, - title: $localize`Job Queue` - }, - { - path: 'market-data', - component: AdminMarketDataComponent, - title: $localize`Market Data` - }, - { - path: 'settings', - component: AdminSettingsComponent, - title: $localize`Settings` - }, - { - path: 'users', - component: AdminUsersComponent, - title: $localize`Users` - } - ], - component: AdminPageComponent, - path: '' - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AdminPageRoutingModule {} diff --git a/apps/client/src/app/pages/admin/admin-page.component.ts b/apps/client/src/app/pages/admin/admin-page.component.ts index 5896a18d7..b9243dcb9 100644 --- a/apps/client/src/app/pages/admin/admin-page.component.ts +++ b/apps/client/src/app/pages/admin/admin-page.component.ts @@ -1,15 +1,27 @@ import { TabConfiguration } from '@ghostfolio/common/interfaces'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnDestroy, OnInit } from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + flashOutline, + peopleOutline, + readerOutline, + serverOutline, + settingsOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, + imports: [IonIcon, MatTabsModule, RouterModule], selector: 'gf-admin-page', styleUrls: ['./admin-page.scss'], - templateUrl: './admin-page.html', - standalone: false + templateUrl: './admin-page.html' }) export class AdminPageComponent implements OnDestroy, OnInit { public deviceType: string; @@ -17,7 +29,15 @@ export class AdminPageComponent implements OnDestroy, OnInit { private unsubscribeSubject = new Subject(); - public constructor(private deviceService: DeviceDetectorService) {} + public constructor(private deviceService: DeviceDetectorService) { + addIcons({ + flashOutline, + peopleOutline, + readerOutline, + serverOutline, + settingsOutline + }); + } public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; @@ -26,27 +46,31 @@ export class AdminPageComponent implements OnDestroy, OnInit { { iconName: 'reader-outline', label: $localize`Overview`, - path: ['/admin'] + routerLink: internalRoutes.adminControl.routerLink }, { iconName: 'settings-outline', - label: $localize`Settings`, - path: ['/admin', 'settings'] + label: + internalRoutes.adminControl.subRoutes.settings.title + + '' + + $localize`new` + + '', + routerLink: internalRoutes.adminControl.subRoutes.settings.routerLink }, { iconName: 'server-outline', - label: $localize`Market Data`, - path: ['/admin', 'market-data'] + label: internalRoutes.adminControl.subRoutes.marketData.title, + routerLink: internalRoutes.adminControl.subRoutes.marketData.routerLink }, { iconName: 'flash-outline', - label: $localize`Job Queue`, - path: ['/admin', 'jobs'] + label: internalRoutes.adminControl.subRoutes.jobs.title, + routerLink: internalRoutes.adminControl.subRoutes.jobs.routerLink }, { iconName: 'people-outline', - label: $localize`Users`, - path: ['/admin', 'users'] + label: internalRoutes.adminControl.subRoutes.users.title, + routerLink: internalRoutes.adminControl.subRoutes.users.routerLink } ]; } diff --git a/apps/client/src/app/pages/admin/admin-page.html b/apps/client/src/app/pages/admin/admin-page.html index a9dbee450..43509a9ad 100644 --- a/apps/client/src/app/pages/admin/admin-page.html +++ b/apps/client/src/app/pages/admin/admin-page.html @@ -16,14 +16,14 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > -
    {{ tab.label }}
    +
    } } diff --git a/apps/client/src/app/pages/admin/admin-page.module.ts b/apps/client/src/app/pages/admin/admin-page.module.ts deleted file mode 100644 index 2b986aa6c..000000000 --- a/apps/client/src/app/pages/admin/admin-page.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { GfAdminJobsModule } from '@ghostfolio/client/components/admin-jobs/admin-jobs.module'; -import { GfAdminMarketDataModule } from '@ghostfolio/client/components/admin-market-data/admin-market-data.module'; -import { GfAdminOverviewModule } from '@ghostfolio/client/components/admin-overview/admin-overview.module'; -import { GfAdminSettingsModule } from '@ghostfolio/client/components/admin-settings/admin-settings.module'; -import { GfAdminUsersModule } from '@ghostfolio/client/components/admin-users/admin-users.module'; -import { CacheService } from '@ghostfolio/client/services/cache.service'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatTabsModule } from '@angular/material/tabs'; - -import { AdminPageRoutingModule } from './admin-page-routing.module'; -import { AdminPageComponent } from './admin-page.component'; - -@NgModule({ - declarations: [AdminPageComponent], - exports: [], - imports: [ - AdminPageRoutingModule, - CommonModule, - GfAdminJobsModule, - GfAdminMarketDataModule, - GfAdminOverviewModule, - GfAdminSettingsModule, - GfAdminUsersModule, - MatTabsModule - ], - providers: [CacheService], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class AdminPageModule {} diff --git a/apps/client/src/app/pages/admin/admin-page.routes.ts b/apps/client/src/app/pages/admin/admin-page.routes.ts new file mode 100644 index 000000000..956e12c9a --- /dev/null +++ b/apps/client/src/app/pages/admin/admin-page.routes.ts @@ -0,0 +1,46 @@ +import { GfAdminJobsComponent } from '@ghostfolio/client/components/admin-jobs/admin-jobs.component'; +import { GfAdminMarketDataComponent } from '@ghostfolio/client/components/admin-market-data/admin-market-data.component'; +import { GfAdminOverviewComponent } from '@ghostfolio/client/components/admin-overview/admin-overview.component'; +import { GfAdminSettingsComponent } from '@ghostfolio/client/components/admin-settings/admin-settings.component'; +import { GfAdminUsersComponent } from '@ghostfolio/client/components/admin-users/admin-users.component'; +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { AdminPageComponent } from './admin-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + children: [ + { + path: '', + component: GfAdminOverviewComponent, + title: internalRoutes.adminControl.title + }, + { + path: internalRoutes.adminControl.subRoutes.jobs.path, + component: GfAdminJobsComponent, + title: internalRoutes.adminControl.subRoutes.jobs.title + }, + { + path: internalRoutes.adminControl.subRoutes.marketData.path, + component: GfAdminMarketDataComponent, + title: internalRoutes.adminControl.subRoutes.marketData.title + }, + { + path: internalRoutes.adminControl.subRoutes.settings.path, + component: GfAdminSettingsComponent, + title: internalRoutes.adminControl.subRoutes.settings.title + }, + { + path: internalRoutes.adminControl.subRoutes.users.path, + component: GfAdminUsersComponent, + title: internalRoutes.adminControl.subRoutes.users.title + } + ], + component: AdminPageComponent, + path: '' + } +]; diff --git a/apps/client/src/app/pages/api/api-page.component.ts b/apps/client/src/app/pages/api/api-page.component.ts index 039bf8691..87fc164af 100644 --- a/apps/client/src/app/pages/api/api-page.component.ts +++ b/apps/client/src/app/pages/api/api-page.component.ts @@ -27,9 +27,10 @@ import { map, Observable, Subject, takeUntil } from 'rxjs'; export class GfApiPageComponent implements OnInit { public dividends$: Observable; public historicalData$: Observable; + public isinLookupItems$: Observable; + public lookupItems$: Observable; public quotes$: Observable; public status$: Observable; - public symbols$: Observable; private apiKey: string; private unsubscribeSubject = new Subject(); @@ -40,10 +41,11 @@ export class GfApiPageComponent implements OnInit { this.apiKey = prompt($localize`Please enter your Ghostfolio API key:`); this.dividends$ = this.fetchDividends({ symbol: 'KO' }); - this.historicalData$ = this.fetchHistoricalData({ symbol: 'AAPL.US' }); - this.quotes$ = this.fetchQuotes({ symbols: ['AAPL.US', 'VOO.US'] }); + this.historicalData$ = this.fetchHistoricalData({ symbol: 'AAPL' }); + this.isinLookupItems$ = this.fetchLookupItems({ query: 'US0378331005' }); + this.lookupItems$ = this.fetchLookupItems({ query: 'apple' }); + this.quotes$ = this.fetchQuotes({ symbols: ['AAPL', 'VOO'] }); this.status$ = this.fetchStatus(); - this.symbols$ = this.fetchSymbols({ query: 'apple' }); } public ngOnDestroy() { @@ -93,32 +95,7 @@ export class GfApiPageComponent implements OnInit { ); } - private fetchQuotes({ symbols }: { symbols: string[] }) { - const params = new HttpParams().set('symbols', symbols.join(',')); - - return this.http - .get('/api/v2/data-providers/ghostfolio/quotes', { - params, - headers: this.getHeaders() - }) - .pipe( - map(({ quotes }) => { - return quotes; - }), - takeUntil(this.unsubscribeSubject) - ); - } - - private fetchStatus() { - return this.http - .get( - '/api/v2/data-providers/ghostfolio/status', - { headers: this.getHeaders() } - ) - .pipe(takeUntil(this.unsubscribeSubject)); - } - - private fetchSymbols({ + private fetchLookupItems({ includeIndices = false, query }: { @@ -144,6 +121,31 @@ export class GfApiPageComponent implements OnInit { ); } + private fetchQuotes({ symbols }: { symbols: string[] }) { + const params = new HttpParams().set('symbols', symbols.join(',')); + + return this.http + .get('/api/v2/data-providers/ghostfolio/quotes', { + params, + headers: this.getHeaders() + }) + .pipe( + map(({ quotes }) => { + return quotes; + }), + takeUntil(this.unsubscribeSubject) + ); + } + + private fetchStatus() { + return this.http + .get( + '/api/v2/data-providers/ghostfolio/status', + { headers: this.getHeaders() } + ) + .pipe(takeUntil(this.unsubscribeSubject)); + } + private getHeaders() { return new HttpHeaders({ [HEADER_KEY_SKIP_INTERCEPTOR]: 'true', diff --git a/apps/client/src/app/pages/api/api-page.html b/apps/client/src/app/pages/api/api-page.html index a1f286c07..d8bfc75d7 100644 --- a/apps/client/src/app/pages/api/api-page.html +++ b/apps/client/src/app/pages/api/api-page.html @@ -3,10 +3,21 @@

    Status

    {{ status$ | async | json }}
    -
    +

    Lookup

    - @if (symbols$) { - @let symbols = symbols$ | async; + @if (lookupItems$) { + @let symbols = lookupItems$ | async; +
      + @for (item of symbols; track item.symbol) { +
    • {{ item.name }} ({{ item.symbol }})
    • + } +
    + } +
    +
    +

    Lookup (ISIN)

    + @if (isinLookupItems$) { + @let symbols = isinLookupItems$ | async;
      @for (item of symbols; track item.symbol) {
    • {{ item.name }} ({{ item.symbol }})
    • diff --git a/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts b/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts index 2e346bf40..597c8d998 100644 --- a/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts +++ b/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -1,3 +1,5 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule } from '@angular/router'; @@ -9,6 +11,7 @@ import { RouterModule } from '@angular/router'; templateUrl: './hallo-ghostfolio-page.html' }) export class HalloGhostfolioPageComponent { - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; - public routerLinkResources = ['/' + $localize`:snake-case:resources`]; + public routerLinkBlog = publicRoutes.blog.routerLink; + public routerLinkPricing = publicRoutes.pricing.routerLink; + public routerLinkResources = publicRoutes.resources.routerLink; } diff --git a/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html b/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html index e0364f747..28e30d16b 100644 --- a/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html +++ b/apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html @@ -201,7 +201,7 @@
    +
    + + +
    +

    Zen Mode

    +

    + Keep calm and activate Zen Mode if the markets are going + crazy.

    @@ -242,11 +259,11 @@

    Multi-Language

    Use Ghostfolio in multiple languages: English, - - - Dutch, French, German, Italian, - - Portuguese, Spanish and Turkish are currently supported. + + Chinese, Dutch, French, German, Italian, Polish, Portuguese, + Spanish and Turkish + + are currently supported.

    diff --git a/apps/client/src/app/pages/home/home-page-routing.module.ts b/apps/client/src/app/pages/home/home-page-routing.module.ts deleted file mode 100644 index f50b55192..000000000 --- a/apps/client/src/app/pages/home/home-page-routing.module.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { HomeHoldingsComponent } from '@ghostfolio/client/components/home-holdings/home-holdings.component'; -import { HomeMarketComponent } from '@ghostfolio/client/components/home-market/home-market.component'; -import { HomeOverviewComponent } from '@ghostfolio/client/components/home-overview/home-overview.component'; -import { HomeSummaryComponent } from '@ghostfolio/client/components/home-summary/home-summary.component'; -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { HomePageComponent } from './home-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - component: HomeOverviewComponent - }, - { - path: 'holdings', - component: HomeHoldingsComponent, - title: $localize`Holdings` - }, - { - path: 'holdings', - component: HomeHoldingsComponent, - title: $localize`Holdings` - }, - { - path: 'summary', - component: HomeSummaryComponent, - title: $localize`Summary` - }, - { - path: 'market', - component: HomeMarketComponent, - title: $localize`Markets` - } - ], - component: HomePageComponent, - path: '' - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class HomePageRoutingModule {} diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts index e307884f8..eb1ad62d9 100644 --- a/apps/client/src/app/pages/home/home-page.component.ts +++ b/apps/client/src/app/pages/home/home-page.component.ts @@ -1,20 +1,40 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + analyticsOutline, + bookmarkOutline, + newspaperOutline, + readerOutline, + walletOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, + imports: [IonIcon, MatTabsModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-home-page', styleUrls: ['./home-page.scss'], - templateUrl: './home-page.html', - standalone: false + templateUrl: './home-page.html' }) -export class HomePageComponent implements OnDestroy, OnInit { +export class GfHomePageComponent implements OnDestroy, OnInit { public deviceType: string; public hasImpersonationId: boolean; public tabs: TabConfiguration[] = []; @@ -32,33 +52,57 @@ export class HomePageComponent implements OnDestroy, OnInit { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { if (state?.user) { + this.user = state.user; + this.tabs = [ { iconName: 'analytics-outline', - label: $localize`Overview`, - path: ['/home'] + label: internalRoutes.home.title, + routerLink: internalRoutes.home.routerLink }, { iconName: 'wallet-outline', - label: $localize`Holdings`, - path: ['/home', 'holdings'] + label: internalRoutes.home.subRoutes.holdings.title, + routerLink: internalRoutes.home.subRoutes.holdings.routerLink }, { iconName: 'reader-outline', - label: $localize`Summary`, - path: ['/home', 'summary'] + label: internalRoutes.home.subRoutes.summary.title, + routerLink: internalRoutes.home.subRoutes.summary.routerLink + }, + { + iconName: 'bookmark-outline', + label: internalRoutes.home.subRoutes.watchlist.title, + routerLink: internalRoutes.home.subRoutes.watchlist.routerLink }, { iconName: 'newspaper-outline', - label: $localize`Markets`, - path: ['/home', 'market'] + label: hasPermission( + this.user?.permissions, + permissions.readMarketDataOfMarkets + ) + ? internalRoutes.home.subRoutes.marketsPremium.title + : internalRoutes.home.subRoutes.markets.title, + routerLink: hasPermission( + this.user?.permissions, + permissions.readMarketDataOfMarkets + ) + ? internalRoutes.home.subRoutes.marketsPremium.routerLink + : internalRoutes.home.subRoutes.markets.routerLink } ]; - this.user = state.user; this.changeDetectorRef.markForCheck(); } }); + + addIcons({ + analyticsOutline, + bookmarkOutline, + newspaperOutline, + readerOutline, + walletOutline + }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/home/home-page.html b/apps/client/src/app/pages/home/home-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/home/home-page.html +++ b/apps/client/src/app/pages/home/home-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" >
  • My Account
  • +
  • Account Cluster Risks
  • +
  • Investment
  • +
  • + Over ${thresholdMax}% of your current investment is at + ${maxAccountName} (${maxInvestmentRatio}%) +
  • +
  • + No accounts have been set up +
  • +
  • + The major part of your current investment is at + ${maxAccountName} (${maxInvestmentRatio}%) and does + not exceed ${thresholdMax}% +
  • +
  • Single Account
  • +
  • + Your net worth is managed by a single account +
  • +
  • + Your net worth is managed by 0 accounts +
  • +
  • + Your net worth is managed by ${accountsLength} accounts +
  • +
  • + Asset Class Cluster Risks +
  • +
  • Equity
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) is below ${thresholdMin}% +
  • +
  • + The equity contribution of your current investment + (${equityValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Fixed Income
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) is below + ${thresholdMin}% +
  • +
  • + The fixed income contribution of your current investment + (${fixedIncomeValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Currency Cluster Risks
  • +
  • + Investment: Base Currency +
  • +
  • + The major part of your current investment is not in your base currency + (${baseCurrencyValueRatio}% in ${baseCurrency}) +
  • +
  • + The major part of your current investment is in your base currency + (${baseCurrencyValueRatio}% in ${baseCurrency}) +
  • +
  • Investment
  • +
  • + Over ${thresholdMax}% of your current investment is in + ${currency} (${maxValueRatio}%) +
  • +
  • + The major part of your current investment is in ${currency} + (${maxValueRatio}%) and does not exceed + ${thresholdMax}% +
  • +
  • + Economic Market Cluster Risks +
  • +
  • + Developed Markets +
  • +
  • + The developed markets contribution of your current investment + (${developedMarketsValueRatio}%) exceeds + ${thresholdMax}% +
  • +
  • + The developed markets contribution of your current investment + (${developedMarketsValueRatio}%) is below + ${thresholdMin}% +
  • +
  • + The developed markets contribution of your current investment + (${developedMarketsValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • + Emerging Markets +
  • +
  • + The emerging markets contribution of your current investment + (${emergingMarketsValueRatio}%) exceeds + ${thresholdMax}% +
  • +
  • + The emerging markets contribution of your current investment + (${emergingMarketsValueRatio}%) is below + ${thresholdMin}% +
  • +
  • + The emerging markets contribution of your current investment + (${emergingMarketsValueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Emergency Fund
  • +
  • Set up
  • +
  • + No emergency fund has been set up +
  • +
  • + An emergency fund has been set up +
  • +
  • Fee Ratio
  • +
  • + The fees do exceed ${thresholdMax}% of your initial investment + (${feeRatio}%) +
  • +
  • + The fees do not exceed ${thresholdMax}% of your initial + investment (${feeRatio}%) +
  • +
  • Fees
  • +
  • + Regional Market Cluster Risks +
  • +
  • Asia-Pacific
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Asia-Pacific market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • + Emerging Markets +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Emerging Markets contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Europe
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Europe market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • Japan
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The Japan market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • +
  • North America
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) exceeds ${thresholdMax}% +
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) is below ${thresholdMin}% +
  • +
  • + The North America market contribution of your current investment + (${valueRatio}%) is within the range of + ${thresholdMin}% and ${thresholdMax}% +
  • Open Source Wealth Management Software
  • diff --git a/apps/client/src/app/pages/landing/landing-page.component.ts b/apps/client/src/app/pages/landing/landing-page.component.ts index 4adcbe00a..0a965b8fa 100644 --- a/apps/client/src/app/pages/landing/landing-page.component.ts +++ b/apps/client/src/app/pages/landing/landing-page.component.ts @@ -1,6 +1,7 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { Statistics } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { format } from 'date-fns'; @@ -24,8 +25,10 @@ export class LandingPageComponent implements OnDestroy, OnInit { public hasPermissionForStatistics: boolean; public hasPermissionForSubscription: boolean; public hasPermissionToCreateUser: boolean; - public routerLinkAbout = ['/' + $localize`:snake-case:about`]; - public routerLinkRegister = ['/' + $localize`:snake-case:register`]; + public routerLinkAbout = publicRoutes.about.routerLink; + public routerLinkDemo = publicRoutes.demo.routerLink; + public routerLinkOpenStartup = publicRoutes.openStartup.routerLink; + public routerLinkRegister = publicRoutes.register.routerLink; public statistics: Statistics; public testimonials = [ { diff --git a/apps/client/src/app/pages/landing/landing-page.html b/apps/client/src/app/pages/landing/landing-page.html index 7ce938227..7202e2910 100644 --- a/apps/client/src/app/pages/landing/landing-page.html +++ b/apps/client/src/app/pages/landing/landing-page.html @@ -2,11 +2,11 @@
    -

    +

    Manage your wealth like a boss

    -

    +

    Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. @@ -46,7 +46,7 @@ @if (hasPermissionToCreateUser) {

    or
    } - Live Demo + Live Demo }
    @@ -60,7 +60,7 @@
    -

    +

    Protect your assets. Refine your personal investment strategy.

    -

    +

    Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked.

    @@ -270,7 +270,7 @@

    Why Ghostfolio?

    -

    +

    Ghostfolio is for you if you are...

      @@ -363,7 +363,7 @@ @if (hasPermissionForSubscription) {
      -

      +

      Members from around the globe are using Ghostfolio Premium

      @@ -431,7 +431,7 @@

      Are you ready?

      -

      +

      Join now @if (hasPermissionForDemo) { or check out the example account @@ -448,7 +448,9 @@ @if (hasPermissionForDemo) {

      or
      - Live Demo + Live Demo }
      diff --git a/apps/client/src/app/pages/markets/markets-page-routing.module.ts b/apps/client/src/app/pages/markets/markets-page-routing.module.ts index 6501d58b9..05ab9b275 100644 --- a/apps/client/src/app/pages/markets/markets-page-routing.module.ts +++ b/apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -1,4 +1,5 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -10,7 +11,7 @@ const routes: Routes = [ canActivate: [AuthGuard], component: MarketsPageComponent, path: '', - title: $localize`Markets` + title: publicRoutes.markets.title } ]; diff --git a/apps/client/src/app/pages/markets/markets-page.module.ts b/apps/client/src/app/pages/markets/markets-page.module.ts index cabb078bc..34938612e 100644 --- a/apps/client/src/app/pages/markets/markets-page.module.ts +++ b/apps/client/src/app/pages/markets/markets-page.module.ts @@ -1,4 +1,4 @@ -import { GfHomeMarketModule } from '@ghostfolio/client/components/home-market/home-market.module'; +import { HomeMarketComponent } from '@ghostfolio/client/components/home-market/home-market.component'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -8,7 +8,7 @@ import { MarketsPageComponent } from './markets-page.component'; @NgModule({ declarations: [MarketsPageComponent], - imports: [CommonModule, GfHomeMarketModule, MarketsPageRoutingModule], + imports: [CommonModule, HomeMarketComponent, MarketsPageRoutingModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class MarketsPageModule {} diff --git a/apps/client/src/app/pages/open/open-page-routing.module.ts b/apps/client/src/app/pages/open/open-page-routing.module.ts index b9db4ab10..c56fe80ba 100644 --- a/apps/client/src/app/pages/open/open-page-routing.module.ts +++ b/apps/client/src/app/pages/open/open-page-routing.module.ts @@ -1,4 +1,5 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -10,7 +11,7 @@ const routes: Routes = [ canActivate: [AuthGuard], component: OpenPageComponent, path: '', - title: 'Open Startup' + title: publicRoutes.openStartup.title } ]; diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts b/apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts deleted file mode 100644 index 00962d563..000000000 --- a/apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ActivitiesPageComponent } from './activities-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: ActivitiesPageComponent, - path: '', - title: $localize`Activities` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ActivitiesPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index 91254e002..26049e069 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -9,30 +9,42 @@ import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; import { downloadAsFile } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { PageEvent } from '@angular/material/paginator'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; import { Sort, SortDirection } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { format, parseISO } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { addOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog/create-or-update-activity-dialog.component'; -import { ImportActivitiesDialog } from './import-activities-dialog/import-activities-dialog.component'; +import { GfCreateOrUpdateActivityDialog } from './create-or-update-activity-dialog/create-or-update-activity-dialog.component'; +import { GfImportActivitiesDialog } from './import-activities-dialog/import-activities-dialog.component'; import { ImportActivitiesDialogParams } from './import-activities-dialog/interfaces/interfaces'; @Component({ host: { class: 'has-fab' }, + imports: [ + GfActivitiesTableComponent, + IonIcon, + MatButtonModule, + MatSnackBarModule, + RouterModule + ], selector: 'gf-activities-page', styleUrls: ['./activities-page.scss'], - templateUrl: './activities-page.html', - standalone: false + templateUrl: './activities-page.html' }) -export class ActivitiesPageComponent implements OnDestroy, OnInit { +export class GfActivitiesPageComponent implements OnDestroy, OnInit { public dataSource: MatTableDataSource; public deviceType: string; public hasImpersonationId: boolean; @@ -86,6 +98,8 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { } } }); + + addIcons({ addOutline }); } public ngOnInit() { @@ -125,7 +139,10 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { this.dataSource = new MatTableDataSource(activities); this.totalItems = count; - if (this.hasPermissionToCreateActivity && this.totalItems <= 0) { + if ( + this.hasPermissionToCreateActivity && + this.user?.activitiesCount === 0 + ) { this.router.navigate([], { queryParams: { createDialog: true } }); } @@ -160,6 +177,11 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { }) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.fetchActivities(); }); } @@ -169,6 +191,11 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { .deleteActivity(aId) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.fetchActivities(); }); } @@ -218,7 +245,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { } public onImport() { - const dialogRef = this.dialog.open(ImportActivitiesDialog, { + const dialogRef = this.dialog.open(GfImportActivitiesDialog, { data: { deviceType: this.deviceType, user: this.user @@ -230,12 +257,17 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.fetchActivities(); }); } public onImportDividends() { - const dialogRef = this.dialog.open(ImportActivitiesDialog, { + const dialogRef = this.dialog.open(GfImportActivitiesDialog, { data: { activityTypes: ['DIVIDEND'], deviceType: this.deviceType, @@ -248,6 +280,11 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.fetchActivities(); }); } @@ -267,7 +304,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { } public openUpdateActivityDialog(activity: Activity) { - const dialogRef = this.dialog.open(CreateOrUpdateActivityDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateActivityDialog, { data: { activity, accounts: this.user?.accounts, @@ -308,7 +345,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { .subscribe((user) => { this.updateUser(user); - const dialogRef = this.dialog.open(CreateOrUpdateActivityDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateActivityDialog, { data: { accounts: this.user?.accounts, activity: { @@ -333,6 +370,11 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { if (transaction) { this.dataService.postOrder(transaction).subscribe({ next: () => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.fetchActivities(); } }); diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.html b/apps/client/src/app/pages/portfolio/activities/activities-page.html index c06f7dd75..80ad71b79 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.html +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -6,6 +6,7 @@ [baseCurrency]="user?.settings?.baseCurrency" [dataSource]="dataSource" [deviceType]="deviceType" + [hasActivities]="user?.activitiesCount > 0" [hasPermissionToCreateActivity]="hasPermissionToCreateActivity" [hasPermissionToDeleteActivity]="hasPermissionToDeleteActivity" [hasPermissionToExportActivities]="!hasImpersonationId" diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts deleted file mode 100644 index c964022be..000000000 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service'; -import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { RouterModule } from '@angular/router'; - -import { ActivitiesPageRoutingModule } from './activities-page-routing.module'; -import { ActivitiesPageComponent } from './activities-page.component'; -import { GfCreateOrUpdateActivityDialogModule } from './create-or-update-activity-dialog/create-or-update-activity-dialog.module'; -import { GfImportActivitiesDialogModule } from './import-activities-dialog/import-activities-dialog.module'; - -@NgModule({ - declarations: [ActivitiesPageComponent], - imports: [ - ActivitiesPageRoutingModule, - CommonModule, - GfActivitiesTableComponent, - GfCreateOrUpdateActivityDialogModule, - GfImportActivitiesDialogModule, - MatButtonModule, - MatSnackBarModule, - RouterModule - ], - providers: [ImportActivitiesService], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class ActivitiesPageModule {} diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.routes.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.routes.ts new file mode 100644 index 000000000..c96c8a558 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfActivitiesPageComponent } from './activities-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfActivitiesPageComponent, + path: '', + title: internalRoutes.portfolio.subRoutes.activities.title + } +]; diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index 506a46a31..656e4a88f 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -1,43 +1,77 @@ import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto'; -import { DataService } from '@ghostfolio/client/services/data.service'; -import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; import { getDateFormatString } from '@ghostfolio/common/helper'; +import { LookupItem } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { translate } from '@ghostfolio/ui/i18n'; +import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; +import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector'; +import { GfValueComponent } from '@ghostfolio/ui/value'; -import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { NgClass } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, - ElementRef, Inject, - OnDestroy, - ViewChild + OnDestroy } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { + FormBuilder, + FormGroup, + ReactiveFormsModule, + Validators +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { IonIcon } from '@ionic/angular/standalone'; import { AssetClass, AssetSubClass, Tag, Type } from '@prisma/client'; import { isAfter, isToday } from 'date-fns'; -import { EMPTY, Observable, Subject, lastValueFrom, of } from 'rxjs'; -import { catchError, delay, map, startWith, takeUntil } from 'rxjs/operators'; +import { addIcons } from 'ionicons'; +import { calendarClearOutline, refreshOutline } from 'ionicons/icons'; +import { EMPTY, Subject } from 'rxjs'; +import { catchError, delay, takeUntil } from 'rxjs/operators'; +import { DataService } from '../../../../services/data.service'; +import { validateObjectForForm } from '../../../../util/form.util'; import { CreateOrUpdateActivityDialogParams } from './interfaces/interfaces'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, + imports: [ + GfEntityLogoComponent, + GfSymbolAutocompleteComponent, + GfTagsSelectorComponent, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCheckboxModule, + MatDatepickerModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + MatSelectModule, + NgClass, + ReactiveFormsModule + ], selector: 'gf-create-or-update-activity-dialog', - changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./create-or-update-activity-dialog.scss'], - templateUrl: 'create-or-update-activity-dialog.html', - standalone: false + templateUrl: 'create-or-update-activity-dialog.html' }) -export class CreateOrUpdateActivityDialog implements OnDestroy { - @ViewChild('symbolAutocomplete') symbolAutocomplete; - @ViewChild('tagInput') tagInput: ElementRef; - +export class GfCreateOrUpdateActivityDialog implements OnDestroy { public activityForm: FormGroup; public assetClasses = Object.keys(AssetClass).map((assetClass) => { return { id: assetClass, label: translate(assetClass) }; @@ -46,14 +80,15 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { return { id: assetSubClass, label: translate(assetSubClass) }; }); public currencies: string[] = []; + public currencyOfAssetProfile: string; public currentMarketPrice = null; public defaultDateFormat: string; - public filteredTagsObservable: Observable = of([]); + public defaultLookupItems: LookupItem[] = []; + public hasPermissionToCreateOwnTag: boolean; public isLoading = false; public isToday = isToday; public mode: 'create' | 'update'; public platforms: { id: string; name: string }[]; - public separatorKeysCodes: number[] = [COMMA, ENTER]; public tagsAvailable: Tag[] = []; public total = 0; public typesTranslationMap = new Map(); @@ -66,14 +101,22 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateActivityDialogParams, private dataService: DataService, private dateAdapter: DateAdapter, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private formBuilder: FormBuilder, - @Inject(MAT_DATE_LOCALE) private locale: string - ) {} + @Inject(MAT_DATE_LOCALE) private locale: string, + private userService: UserService + ) { + addIcons({ calendarClearOutline, refreshOutline }); + } public ngOnInit() { - this.mode = this.data.activity.id ? 'update' : 'create'; + this.currencyOfAssetProfile = this.data.activity?.SymbolProfile?.currency; + this.hasPermissionToCreateOwnTag = + this.data.user?.settings?.isExperimentalFeatures && + hasPermission(this.data.user?.permissions, permissions.createOwnTag); this.locale = this.data.user?.settings?.locale; + this.mode = this.data.activity?.id ? 'update' : 'create'; + this.dateAdapter.setLocale(this.locale); const { currencies, platforms } = this.dataService.fetchInfo(); @@ -82,6 +125,43 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.defaultDateFormat = getDateFormatString(this.locale); this.platforms = platforms; + this.dataService + .fetchPortfolioHoldings() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ holdings }) => { + this.defaultLookupItems = holdings + .filter(({ assetSubClass }) => { + return !['CASH'].includes(assetSubClass); + }) + .sort((a, b) => { + return a.name?.localeCompare(b.name); + }) + .map( + ({ + assetClass, + assetSubClass, + currency, + dataSource, + name, + symbol + }) => { + return { + assetClass, + assetSubClass, + currency, + dataSource, + name, + symbol, + dataProviderInfo: { + isPremium: false + } + }; + } + ); + + this.changeDetectorRef.markForCheck(); + }); + this.tagsAvailable = this.data.user?.tags?.map((tag) => { return { @@ -111,7 +191,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { Validators.required ], currencyOfUnitPrice: [ - this.data.activity?.SymbolProfile?.currency, + this.data.activity?.currency ?? + this.data.activity?.SymbolProfile?.currency, Validators.required ], dataSource: [ @@ -120,11 +201,10 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ], date: [this.data.activity?.date, Validators.required], fee: [this.data.activity?.fee, Validators.required], - feeInCustomCurrency: [this.data.activity?.fee, Validators.required], name: [this.data.activity?.SymbolProfile?.name, Validators.required], quantity: [this.data.activity?.quantity, Validators.required], searchSymbol: [ - !!this.data.activity?.SymbolProfile + this.data.activity?.SymbolProfile ? { dataSource: this.data.activity?.SymbolProfile?.dataSource, symbol: this.data.activity?.SymbolProfile?.symbol @@ -142,10 +222,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ], type: [undefined, Validators.required], // Set after value changes subscription unitPrice: [this.data.activity?.unitPrice, Validators.required], - unitPriceInCustomCurrency: [ - this.data.activity?.unitPrice, - Validators.required - ], updateAccountBalance: [false] }); @@ -157,61 +233,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(async () => { - let exchangeRateOfUnitPrice = 1; - - this.activityForm.get('feeInCustomCurrency').setErrors(null); - this.activityForm.get('unitPriceInCustomCurrency').setErrors(null); - - const currency = this.activityForm.get('currency').value; - const currencyOfUnitPrice = this.activityForm.get( - 'currencyOfUnitPrice' - ).value; - const date = this.activityForm.get('date').value; - if ( - currency && - currencyOfUnitPrice && - currency !== currencyOfUnitPrice && - date - ) { - try { - const { marketPrice } = await lastValueFrom( - this.dataService - .fetchExchangeRateForDate({ - date, - symbol: `${currencyOfUnitPrice}-${currency}` - }) - .pipe(takeUntil(this.unsubscribeSubject)) - ); - - exchangeRateOfUnitPrice = marketPrice; - } catch { - this.activityForm.get('unitPriceInCustomCurrency').setErrors({ - invalid: true - }); - } - } - - const feeInCustomCurrency = - this.activityForm.get('feeInCustomCurrency').value * - exchangeRateOfUnitPrice; - - const unitPriceInCustomCurrency = - this.activityForm.get('unitPriceInCustomCurrency').value * - exchangeRateOfUnitPrice; - - this.activityForm.get('fee').setValue(feeInCustomCurrency, { - emitEvent: false - }); - - this.activityForm.get('unitPrice').setValue(unitPriceInCustomCurrency, { - emitEvent: false - }); - - if ( - this.activityForm.get('type').value === 'BUY' || - this.activityForm.get('type').value === 'FEE' || - this.activityForm.get('type').value === 'ITEM' + ['BUY', 'FEE', 'ITEM'].includes(this.activityForm.get('type').value) ) { this.total = this.activityForm.get('quantity').value * @@ -230,12 +253,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('accountId').valueChanges.subscribe((accountId) => { const type = this.activityForm.get('type').value; - if ( - type === 'FEE' || - type === 'INTEREST' || - type === 'ITEM' || - type === 'LIABILITY' - ) { + if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(type)) { const currency = this.data.accounts.find(({ id }) => { return id === accountId; @@ -274,30 +292,49 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('type').value ) ) { - this.activityForm - .get('dataSource') - .setValue(this.activityForm.get('searchSymbol').value.dataSource); - - this.updateSymbol(); + this.updateAssetProfile(); } this.changeDetectorRef.markForCheck(); }); - this.filteredTagsObservable = this.activityForm.controls[ - 'tags' - ].valueChanges.pipe( - startWith(this.activityForm.get('tags').value), - map((aTags: Tag[] | null) => { - return aTags ? this.filterTags(aTags) : this.tagsAvailable.slice(); - }) - ); + this.activityForm.get('tags').valueChanges.subscribe((tags: Tag[]) => { + const newTag = tags.find(({ id }) => { + return id === undefined; + }); + + if (newTag && this.hasPermissionToCreateOwnTag) { + this.dataService + .postTag({ ...newTag, userId: this.data.user.id }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((tag) => { + this.activityForm.get('tags').setValue( + tags.map((currentTag) => { + if (currentTag.id === undefined) { + return tag; + } + + return currentTag; + }) + ); + + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + }); + } + }); this.activityForm .get('type') .valueChanges.pipe(takeUntil(this.unsubscribeSubject)) .subscribe((type: Type) => { - if (type === 'ITEM') { + if ( + type === 'ITEM' || + (this.activityForm.get('dataSource').value === 'MANUAL' && + type === 'BUY') + ) { this.activityForm .get('accountId') .removeValidators(Validators.required); @@ -315,21 +352,21 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { .get('dataSource') .removeValidators(Validators.required); this.activityForm.get('dataSource').updateValueAndValidity(); - this.activityForm.get('feeInCustomCurrency').reset(); + this.activityForm.get('fee').setValue(0); this.activityForm.get('name').setValidators(Validators.required); this.activityForm.get('name').updateValueAndValidity(); - this.activityForm.get('quantity').setValue(1); + + if (type === 'ITEM') { + this.activityForm.get('quantity').setValue(1); + } + this.activityForm .get('searchSymbol') .removeValidators(Validators.required); this.activityForm.get('searchSymbol').updateValueAndValidity(); this.activityForm.get('updateAccountBalance').disable(); this.activityForm.get('updateAccountBalance').setValue(false); - } else if ( - type === 'FEE' || - type === 'INTEREST' || - type === 'LIABILITY' - ) { + } else if (['FEE', 'INTEREST', 'LIABILITY'].includes(type)) { this.activityForm .get('accountId') .removeValidators(Validators.required); @@ -348,13 +385,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { .removeValidators(Validators.required); this.activityForm.get('dataSource').updateValueAndValidity(); - if ( - (type === 'FEE' && - this.activityForm.get('feeInCustomCurrency').value === 0) || - type === 'INTEREST' || - type === 'LIABILITY' - ) { - this.activityForm.get('feeInCustomCurrency').reset(); + if (['INTEREST', 'LIABILITY'].includes(type)) { + this.activityForm.get('fee').setValue(0); } this.activityForm.get('name').setValidators(Validators.required); @@ -362,7 +394,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { if (type === 'FEE') { this.activityForm.get('quantity').setValue(0); - } else if (type === 'INTEREST' || type === 'LIABILITY') { + } else if (['INTEREST', 'LIABILITY'].includes(type)) { this.activityForm.get('quantity').setValue(1); } @@ -372,7 +404,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('searchSymbol').updateValueAndValidity(); if (type === 'FEE') { - this.activityForm.get('unitPriceInCustomCurrency').setValue(0); + this.activityForm.get('unitPrice').setValue(0); } if ( @@ -428,7 +460,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { public applyCurrentMarketPrice() { this.activityForm.patchValue({ currencyOfUnitPrice: this.activityForm.get('currency').value, - unitPriceInCustomCurrency: this.currentMarketPrice + unitPrice: this.currentMarketPrice }); } @@ -440,29 +472,10 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { return isAfter(aDate, new Date(0)); } - public onAddTag(event: MatAutocompleteSelectedEvent) { - this.activityForm.get('tags').setValue([ - ...(this.activityForm.get('tags').value ?? []), - this.tagsAvailable.find(({ id }) => { - return id === event.option.value; - }) - ]); - - this.tagInput.nativeElement.value = ''; - } - public onCancel() { this.dialogRef.close(); } - public onRemoveTag(aTag: Tag) { - this.activityForm.get('tags').setValue( - this.activityForm.get('tags').value.filter(({ id }) => { - return id !== aTag.id; - }) - ); - } - public async onSubmit() { const activity: CreateOrderDto | UpdateOrderDto = { accountId: this.activityForm.get('accountId').value, @@ -476,7 +489,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { fee: this.activityForm.get('fee').value, quantity: this.activityForm.get('quantity').value, symbol: - this.activityForm.get('searchSymbol')?.value?.symbol ?? + (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes( + this.activityForm.get('type').value + ) + ? undefined + : this.activityForm.get('searchSymbol')?.value?.symbol) ?? this.activityForm.get('name')?.value, tags: this.activityForm.get('tags').value, type: this.activityForm.get('type').value, @@ -485,8 +502,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { try { if (this.mode === 'create') { - (activity as CreateOrderDto).updateAccountBalance = - this.activityForm.get('updateAccountBalance').value; + activity.updateAccountBalance = this.activityForm.get( + 'updateAccountBalance' + ).value; await validateObjectForForm({ classDto: CreateOrderDto, @@ -495,9 +513,15 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { object: activity }); - this.dialogRef.close(activity as CreateOrderDto); + if (activity.type === 'ITEM') { + // Transform deprecated type ITEM + activity.dataSource = 'MANUAL'; + activity.type = 'BUY'; + } + + this.dialogRef.close(activity); } else { - (activity as UpdateOrderDto).id = this.data.activity.id; + (activity as UpdateOrderDto).id = this.data.activity?.id; await validateObjectForForm({ classDto: UpdateOrderDto, @@ -506,6 +530,12 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { object: activity as UpdateOrderDto }); + if (activity.type === 'ITEM') { + // Transform deprecated type ITEM + activity.dataSource = 'MANUAL'; + activity.type = 'BUY'; + } + this.dialogRef.close(activity as UpdateOrderDto); } } catch (error) { @@ -513,28 +543,22 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { } } + public onTagsChanged(tags: Tag[]) { + this.activityForm.get('tags').setValue(tags); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } - private filterTags(aTags: Tag[]) { - const tagIds = aTags.map(({ id }) => { - return id; - }); - - return this.tagsAvailable.filter(({ id }) => { - return !tagIds.includes(id); - }); - } - - private updateSymbol() { + private updateAssetProfile() { this.isLoading = true; this.changeDetectorRef.markForCheck(); this.dataService .fetchSymbolItem({ - dataSource: this.activityForm.get('dataSource').value, + dataSource: this.activityForm.get('searchSymbol').value.dataSource, symbol: this.activityForm.get('searchSymbol').value.symbol }) .pipe( @@ -550,10 +574,13 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(({ currency, dataSource, marketPrice }) => { - this.activityForm.get('currency').setValue(currency); - this.activityForm.get('currencyOfUnitPrice').setValue(currency); - this.activityForm.get('dataSource').setValue(dataSource); + if (this.mode === 'create') { + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); + this.activityForm.get('dataSource').setValue(dataSource); + } + this.currencyOfAssetProfile = currency; this.currentMarketPrice = marketPrice; this.isLoading = false; diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html index 7795688c0..b0185dc72 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -93,11 +93,11 @@ @for (account of data.accounts; track account) {
      - @if (account.Platform?.url) { - } {{ account.name }} @@ -124,6 +124,7 @@ Name, symbol or ISIN @@ -214,11 +215,7 @@ } } - +
      - @if ( - activityForm.get('unitPriceInCustomCurrency').hasError('invalid') - ) { - Oops! Could not get the historical exchange rate - from - {{ - activityForm.get('date')?.value | date: defaultDateFormat - }} - } @if ( + currencyOfAssetProfile === + activityForm.get('currencyOfUnitPrice').value && currentMarketPrice && - (data.activity.type === 'BUY' || data.activity.type === 'SELL') && + ['BUY', 'SELL'].includes(data.activity.type) && isToday(activityForm.get('date')?.value) ) {
      -
      - - - @switch (activityForm.get('type')?.value) { - @case ('DIVIDEND') { - Dividend - } - @case ('FEE') { - Value - } - @case ('INTEREST') { - Value - } - @case ('ITEM') { - Value - } - @case ('LIABILITY') { - Value - } - @default { - Unit Price - } - } - - - {{ - activityForm.get('currency').value - }} - -
      Fee - +
      {{ activityForm.get('currencyOfUnitPrice').value }}
      - @if (activityForm.get('feeInCustomCurrency').hasError('invalid')) { - Oops! Could not get the historical exchange rate - from - {{ - activityForm.get('date')?.value | date: defaultDateFormat - }} - } - -
      -
      - - Fee - - {{ - activityForm.get('currency').value - }}
      @@ -378,39 +314,13 @@
      -
      - - Tags - - @for (tag of activityForm.get('tags')?.value; track tag.id) { - - {{ tag.name }} - - - } - - - - @for (tag of filteredTagsObservable | async; track tag.id) { - - {{ tag.name }} - - } - - +
      +
      @@ -419,7 +329,8 @@ [isCurrency]="true" [locale]="data.user?.settings?.locale" [unit]=" - activityForm.get('currency')?.value ?? data.user?.settings?.baseCurrency + activityForm.get('currencyOfUnitPrice')?.value ?? + data.user?.settings?.baseCurrency " [value]="total" /> diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts deleted file mode 100644 index a4d28d0e0..000000000 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatAutocompleteModule } from '@angular/material/autocomplete'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatDatepickerModule } from '@angular/material/datepicker'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; - -import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog.component'; - -@NgModule({ - declarations: [CreateOrUpdateActivityDialog], - imports: [ - CommonModule, - FormsModule, - GfAssetProfileIconComponent, - GfSymbolAutocompleteComponent, - GfValueComponent, - MatAutocompleteModule, - MatButtonModule, - MatCheckboxModule, - MatChipsModule, - MatDatepickerModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - MatSelectModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfCreateOrUpdateActivityDialogModule {} diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index 2f5ead47a..660e7265e 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -1,8 +1,14 @@ -import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; +import { CreateAccountWithBalancesDto } from '@ghostfolio/api/app/import/create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from '@ghostfolio/api/app/import/create-asset-profile-with-market-data.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; +import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; +import { GfFileDropModule } from '@ghostfolio/client/directives/file-drop/file-drop.module'; +import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service'; import { PortfolioPosition } from '@ghostfolio/common/interfaces'; +import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { StepperOrientation, @@ -15,14 +21,32 @@ import { Inject, OnDestroy } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { + FormBuilder, + FormGroup, + ReactiveFormsModule, + Validators +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef +} from '@angular/material/dialog'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { SortDirection } from '@angular/material/sort'; -import { MatStepper } from '@angular/material/stepper'; +import { MatStepper, MatStepperModule } from '@angular/material/stepper'; import { MatTableDataSource } from '@angular/material/table'; +import { IonIcon } from '@ionic/angular/standalone'; import { AssetClass } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { cloudUploadOutline, warningOutline } from 'ionicons/icons'; import { isArray, sortBy } from 'lodash'; +import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; @@ -31,15 +55,31 @@ import { ImportActivitiesDialogParams } from './interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + GfActivitiesTableComponent, + GfDialogFooterModule, + GfDialogHeaderModule, + GfFileDropModule, + GfSymbolModule, + IonIcon, + MatButtonModule, + MatDialogModule, + MatExpansionModule, + MatFormFieldModule, + MatProgressSpinnerModule, + MatSelectModule, + MatStepperModule, + ReactiveFormsModule + ], selector: 'gf-import-activities-dialog', styleUrls: ['./import-activities-dialog.scss'], - templateUrl: 'import-activities-dialog.html', - standalone: false + templateUrl: 'import-activities-dialog.html' }) -export class ImportActivitiesDialog implements OnDestroy { - public accounts: CreateAccountDto[] = []; +export class GfImportActivitiesDialog implements OnDestroy { + public accounts: CreateAccountWithBalancesDto[] = []; public activities: Activity[] = []; public assetProfileForm: FormGroup; + public assetProfiles: CreateAssetProfileWithMarketDataDto[] = []; public dataSource: MatTableDataSource; public details: any[] = []; public deviceType: string; @@ -64,10 +104,12 @@ export class ImportActivitiesDialog implements OnDestroy { private dataService: DataService, private deviceService: DeviceDetectorService, private formBuilder: FormBuilder, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private importActivitiesService: ImportActivitiesService, private snackBar: MatSnackBar - ) {} + ) { + addIcons({ cloudUploadOutline, warningOutline }); + } public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; @@ -126,14 +168,15 @@ export class ImportActivitiesDialog implements OnDestroy { await this.importActivitiesService.importSelectedActivities({ accounts: this.accounts, - activities: this.selectedActivities + activities: this.selectedActivities, + assetProfiles: this.assetProfiles }); this.snackBar.open( '✅ ' + $localize`Import has been completed`, undefined, { - duration: 3000 + duration: ms('3 seconds') } ); } catch (error) { @@ -142,7 +185,9 @@ export class ImportActivitiesDialog implements OnDestroy { ' ' + $localize`Please try again later.`, $localize`Okay`, - { duration: 3000 } + { + duration: ms('3 seconds') + } ); } finally { this.dialogRef.close(); @@ -244,12 +289,14 @@ export class ImportActivitiesDialog implements OnDestroy { reader.onload = async (readerEvent) => { const fileContent = readerEvent.target.result as string; + const fileExtension = file.name.split('.').pop()?.toLowerCase(); try { - if (file.name.endsWith('.json')) { + if (fileExtension === 'json') { const content = JSON.parse(fileContent); this.accounts = content.accounts; + this.assetProfiles = content.assetProfiles; if (!isArray(content.activities)) { if (isArray(content.orders)) { @@ -280,6 +327,7 @@ export class ImportActivitiesDialog implements OnDestroy { await this.importActivitiesService.importJson({ accounts: content.accounts, activities: content.activities, + assetProfiles: content.assetProfiles, isDryRun: true }); this.activities = activities; @@ -291,7 +339,7 @@ export class ImportActivitiesDialog implements OnDestroy { } return; - } else if (file.name.endsWith('.csv')) { + } else if (fileExtension === 'csv') { const content = fileContent.split('\n').slice(1); try { @@ -326,6 +374,7 @@ export class ImportActivitiesDialog implements OnDestroy { } finally { this.importStep = ImportStep.SELECT_ACTIVITIES; this.snackBar.dismiss(); + this.updateSelection(this.activities); stepper.next(); diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html index 3bffe8aee..9e7f7a923 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -8,13 +8,13 @@
      - + @if (mode === 'DIVIDEND') { Select Holding @@ -90,13 +90,13 @@ >The following file formats are supported: CSV or JSON @@ -107,7 +107,7 @@
      - + @if (mode === 'DIVIDEND') { Select Dividends diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.module.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.module.ts deleted file mode 100644 index 664054a54..000000000 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.module.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; -import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; -import { GfFileDropModule } from '@ghostfolio/client/directives/file-drop/file-drop.module'; -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatExpansionModule } from '@angular/material/expansion'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { MatSelectModule } from '@angular/material/select'; -import { MatStepperModule } from '@angular/material/stepper'; - -import { ImportActivitiesDialog } from './import-activities-dialog.component'; - -@NgModule({ - declarations: [ImportActivitiesDialog], - imports: [ - CommonModule, - FormsModule, - GfActivitiesTableComponent, - GfDialogFooterModule, - GfDialogHeaderModule, - GfFileDropModule, - GfSymbolModule, - MatButtonModule, - MatDialogModule, - MatExpansionModule, - MatFormFieldModule, - MatProgressSpinnerModule, - MatSelectModule, - MatStepperModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfImportActivitiesDialogModule {} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts deleted file mode 100644 index bb5833442..000000000 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AllocationsPageComponent } from './allocations-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: AllocationsPageComponent, - path: '', - title: $localize`Allocations` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AllocationsPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 41961edd3..1b7874542 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -1,5 +1,6 @@ import { AccountDetailDialog } from '@ghostfolio/client/components/account-detail-dialog/account-detail-dialog.component'; import { AccountDetailDialogParams } from '@ghostfolio/client/components/account-detail-dialog/interfaces/interfaces'; +import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -15,23 +16,45 @@ import { import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { Market, MarketAdvanced } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; +import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfTopHoldingsComponent } from '@ghostfolio/ui/top-holdings'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { NgClass } from '@angular/common'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatCardModule } from '@angular/material/card'; import { MatDialog } from '@angular/material/dialog'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; import { ActivatedRoute, Router } from '@angular/router'; -import { Account, AssetClass, DataSource, Platform } from '@prisma/client'; +import { + Account, + AssetClass, + AssetSubClass, + DataSource, + Platform +} from '@prisma/client'; import { isNumber } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + GfPortfolioProportionChartComponent, + GfPremiumIndicatorComponent, + GfTopHoldingsComponent, + GfValueComponent, + GfWorldMapChartModule, + MatCardModule, + MatProgressBarModule, + NgClass + ], selector: 'gf-allocations-page', styleUrls: ['./allocations-page.scss'], - templateUrl: './allocations-page.html', - standalone: false + templateUrl: './allocations-page.html' }) -export class AllocationsPageComponent implements OnDestroy, OnInit { +export class GfAllocationsPageComponent implements OnDestroy, OnInit { public accounts: { [id: string]: Pick & { id: string; @@ -46,6 +69,18 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }; public deviceType: string; public hasImpersonationId: boolean; + public holdings: { + [symbol: string]: Pick< + PortfolioPosition, + | 'assetClass' + | 'assetClassLabel' + | 'assetSubClass' + | 'assetSubClassLabel' + | 'currency' + | 'exchange' + | 'name' + > & { etfProvider: string; value: number }; + }; public isLoading = false; public markets: { [key in Market]: { id: Market; valueInPercentage: number }; @@ -64,18 +99,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }; }; public portfolioDetails: PortfolioDetails; - public positions: { - [symbol: string]: Pick< - PortfolioPosition, - | 'assetClass' - | 'assetClassLabel' - | 'assetSubClass' - | 'assetSubClassLabel' - | 'currency' - | 'exchange' - | 'name' - > & { etfProvider: string; value: number }; - }; public sectors: { [name: string]: { name: string; value: number }; }; @@ -220,6 +243,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { value: 0 } }; + this.holdings = {}; this.marketsAdvanced = { [UNKNOWN_KEY]: { id: UNKNOWN_KEY, @@ -260,11 +284,11 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { this.platforms = {}; this.portfolioDetails = { accounts: {}, + createdAt: undefined, holdings: {}, platforms: {}, summary: undefined }; - this.positions = {}; this.sectors = { [UNKNOWN_KEY]: { name: UNKNOWN_KEY, @@ -301,16 +325,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }; } - this.markets = this.portfolioDetails.markets; - - Object.values(this.portfolioDetails.marketsAdvanced).forEach( - ({ id, valueInBaseCurrency, valueInPercentage }) => { - this.marketsAdvanced[id].value = isNumber(valueInBaseCurrency) - ? valueInBaseCurrency - : valueInPercentage; - } - ); - for (const [symbol, position] of Object.entries( this.portfolioDetails.holdings )) { @@ -322,12 +336,12 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { value = position.valueInBaseCurrency; } - this.positions[symbol] = { + this.holdings[symbol] = { value, - assetClass: position.assetClass, - assetClassLabel: position.assetClassLabel, - assetSubClass: position.assetSubClass, - assetSubClassLabel: position.assetSubClassLabel, + assetClass: position.assetClass || (UNKNOWN_KEY as AssetClass), + assetClassLabel: position.assetClassLabel || UNKNOWN_KEY, + assetSubClass: position.assetSubClass || (UNKNOWN_KEY as AssetSubClass), + assetSubClassLabel: position.assetSubClassLabel || UNKNOWN_KEY, currency: position.currency, etfProvider: this.extractEtfProvider({ assetSubClass: position.assetSubClass, @@ -444,8 +458,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { } } - if (this.positions[symbol].assetSubClass === 'ETF') { - this.totalValueInEtf += this.positions[symbol].value; + if (this.holdings[symbol].assetSubClass === 'ETF') { + this.totalValueInEtf += this.holdings[symbol].value; } this.symbols[prettifySymbol(symbol)] = { @@ -458,6 +472,16 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { }; } + this.markets = this.portfolioDetails.markets; + + Object.values(this.portfolioDetails.marketsAdvanced).forEach( + ({ id, valueInBaseCurrency, valueInPercentage }) => { + this.marketsAdvanced[id].value = isNumber(valueInBaseCurrency) + ? valueInBaseCurrency + : valueInPercentage; + } + ); + for (const [ id, { name, valueInBaseCurrency, valueInPercentage } @@ -540,7 +564,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { accountId: aAccountId, deviceType: this.deviceType, hasImpersonationId: this.hasImpersonationId, - hasPermissionToCreateOrder: + hasPermissionToCreateActivity: !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createOrder) && !this.user?.settings?.isRestrictedView diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html index f2dff76f3..7153e2e53 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html @@ -48,10 +48,10 @@ @@ -70,10 +70,10 @@ @@ -92,10 +92,10 @@ @@ -113,10 +113,10 @@ cursor="pointer" [baseCurrency]="user?.settings?.baseCurrency" [colorScheme]="user?.settings?.colorScheme" + [data]="symbols" [isInPercent]="hasImpersonationId || user.settings.isRestrictedView" [keys]="['symbol']" [locale]="user?.settings?.locale" - [positions]="symbols" [showLabels]="deviceType !== 'mobile'" (proportionChartClicked)="onSymbolChartClicked($event)" /> @@ -137,11 +137,11 @@ @@ -160,10 +160,10 @@ @@ -182,9 +182,9 @@ @@ -271,11 +271,11 @@ @@ -290,10 +290,10 @@ cursor="pointer" [baseCurrency]="user?.settings?.baseCurrency" [colorScheme]="user?.settings?.colorScheme" + [data]="accounts" [isInPercent]="hasImpersonationId || user.settings.isRestrictedView" [keys]="['id']" [locale]="user?.settings?.locale" - [positions]="accounts" (proportionChartClicked)="onAccountChartClicked($event)" /> @@ -313,10 +313,10 @@ diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts deleted file mode 100644 index 263c34e49..000000000 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; -import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { GfTopHoldingsComponent } from '@ghostfolio/ui/top-holdings'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatCardModule } from '@angular/material/card'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; - -import { AllocationsPageRoutingModule } from './allocations-page-routing.module'; -import { AllocationsPageComponent } from './allocations-page.component'; - -@NgModule({ - declarations: [AllocationsPageComponent], - imports: [ - AllocationsPageRoutingModule, - CommonModule, - GfPortfolioProportionChartComponent, - GfPremiumIndicatorComponent, - GfTopHoldingsComponent, - GfValueComponent, - GfWorldMapChartModule, - MatCardModule, - MatDialogModule, - MatProgressBarModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class AllocationsPageModule {} diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts new file mode 100644 index 000000000..355aca4f1 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts @@ -0,0 +1,14 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; + +import { Routes } from '@angular/router'; + +import { GfAllocationsPageComponent } from './allocations-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfAllocationsPageComponent, + path: '', + title: $localize`Allocations` + } +]; diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss b/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss index 28071385c..3b6eb639e 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.scss @@ -31,8 +31,8 @@ } .mat-mdc-progress-bar { - --mdc-linear-progress-active-indicator-height: 0.5rem; - --mdc-linear-progress-track-height: 0.5rem; + --mat-progress-bar-active-indicator-height: 0.5rem; + --mat-progress-bar-track-height: 0.5rem; border-radius: 0.25rem; ::ng-deep { diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts deleted file mode 100644 index fce4bf221..000000000 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AnalysisPageComponent } from './analysis-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: AnalysisPageComponent, - path: '', - title: $localize`Analysis` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class AnalysisPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 0bd4e85e3..0fd9037bf 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -1,4 +1,5 @@ -import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; +import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module'; +import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -11,40 +12,79 @@ import { ToggleOption, User } from '@ghostfolio/common/interfaces'; -import { GroupBy } from '@ghostfolio/common/types'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import type { AiPromptMode, GroupBy } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; +import { GfValueComponent } from '@ghostfolio/ui/value'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { Clipboard } from '@angular/cdk/clipboard'; +import { + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { SymbolProfile } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { copyOutline, ellipsisVertical } from 'ionicons/icons'; import { isNumber, sortBy } from 'lodash'; +import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + GfBenchmarkComparatorModule, + GfInvestmentChartModule, + GfPremiumIndicatorComponent, + GfToggleComponent, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCardModule, + MatMenuModule, + MatProgressSpinnerModule, + NgxSkeletonLoaderModule, + RouterModule + ], selector: 'gf-analysis-page', styleUrls: ['./analysis-page.scss'], - templateUrl: './analysis-page.html', - standalone: false + templateUrl: './analysis-page.html' }) -export class AnalysisPageComponent implements OnDestroy, OnInit { +export class GfAnalysisPageComponent implements OnDestroy, OnInit { + @ViewChild(MatMenuTrigger) actionsMenuButton!: MatMenuTrigger; + public benchmark: Partial; public benchmarkDataItems: HistoricalDataItem[] = []; public benchmarks: Partial[]; public bottom3: PortfolioPosition[]; - public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public dividendsByGroup: InvestmentItem[]; public dividendTimelineDataLabel = $localize`Dividend`; public firstOrderDate: Date; public hasImpersonationId: boolean; + public hasPermissionToReadAiPrompt: boolean; public investments: InvestmentItem[]; public investmentTimelineDataLabel = $localize`Investment`; public investmentsByGroup: InvestmentItem[]; + public isLoadingAnalysisPrompt: boolean; public isLoadingBenchmarkComparator: boolean; public isLoadingDividendTimelineChart: boolean; public isLoadingInvestmentChart: boolean; public isLoadingInvestmentTimelineChart: boolean; + public isLoadingPortfolioPrompt: boolean; public mode: GroupBy = 'month'; public modeOptions: ToggleOption[] = [ { label: $localize`Monthly`, value: 'month' }, @@ -64,13 +104,17 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { public constructor( private changeDetectorRef: ChangeDetectorRef, + private clipboard: Clipboard, private dataService: DataService, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, + private snackBar: MatSnackBar, private userService: UserService ) { const { benchmarks } = this.dataService.fetchInfo(); this.benchmarks = benchmarks; + + addIcons({ copyOutline, ellipsisVertical }); } get savingsRate() { @@ -104,6 +148,11 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { return id === this.user.settings?.benchmark; }); + this.hasPermissionToReadAiPrompt = hasPermission( + this.user.permissions, + permissions.readAiPrompt + ); + this.update(); } }); @@ -130,6 +179,47 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { this.fetchDividendsAndInvestments(); } + public onCopyPromptToClipboard(mode: AiPromptMode) { + if (mode === 'analysis') { + this.isLoadingAnalysisPrompt = true; + } else if (mode === 'portfolio') { + this.isLoadingPortfolioPrompt = true; + } + + this.dataService + .fetchPrompt({ + mode, + filters: this.userService.getFilters() + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ prompt }) => { + this.clipboard.copy(prompt); + + const snackBarRef = this.snackBar.open( + '✅ ' + $localize`AI prompt has been copied to the clipboard`, + $localize`Open Duck.ai` + ' →', + { + duration: ms('7 seconds') + } + ); + + snackBarRef + .onAction() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + window.open('https://duck.ai', '_blank'); + }); + + this.actionsMenuButton.closeMenu(); + + if (mode === 'analysis') { + this.isLoadingAnalysisPrompt = false; + } else if (mode === 'portfolio') { + this.isLoadingPortfolioPrompt = false; + } + }); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); @@ -254,13 +344,20 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { 'netPerformancePercentWithCurrencyEffect' ).reverse(); - this.top3 = holdingsSorted.slice(0, 3); - - if (holdings?.length > 3) { - this.bottom3 = holdingsSorted.slice(-3).reverse(); - } else { - this.bottom3 = []; - } + this.top3 = holdingsSorted + .filter( + ({ netPerformancePercentWithCurrencyEffect }) => + netPerformancePercentWithCurrencyEffect > 0 + ) + .slice(0, 3); + + this.bottom3 = holdingsSorted + .filter( + ({ netPerformancePercentWithCurrencyEffect }) => + netPerformancePercentWithCurrencyEffect < 0 + ) + .slice(-3) + .reverse(); this.changeDetectorRef.markForCheck(); }); @@ -285,6 +382,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { .fetchBenchmarkForUser({ dataSource, symbol, + filters: this.userService.getFilters(), range: this.user?.settings?.dateRange, startDate: this.firstOrderDate }) diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 087b3bd54..d33d5e570 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -1,5 +1,79 @@

      Analysis

      + @if (user?.settings?.isExperimentalFeatures) { +
      +
      +
      + + +
      + + +
      +
      +
      +
      +
      + }
      - +
      -
      - +
      + Top
      -
      - +
      + Bottom
      @if (streaks) { @@ -358,7 +432,7 @@ [defaultValue]="mode" [isLoading]="false" [options]="modeOptions" - (change)="onChangeGroupBy($event.value)" + (valueChange)="onChangeGroupBy($event.value)" />
      diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts deleted file mode 100644 index b33905456..000000000 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module'; -import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; -import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; -import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatCardModule } from '@angular/material/card'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { AnalysisPageRoutingModule } from './analysis-page-routing.module'; -import { AnalysisPageComponent } from './analysis-page.component'; - -@NgModule({ - declarations: [AnalysisPageComponent], - imports: [ - AnalysisPageRoutingModule, - CommonModule, - GfActivitiesFilterComponent, - GfBenchmarkComparatorModule, - GfInvestmentChartModule, - GfPremiumIndicatorComponent, - GfToggleModule, - GfValueComponent, - MatCardModule, - NgxSkeletonLoaderModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class AnalysisPageModule {} diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.routes.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.routes.ts new file mode 100644 index 000000000..91cf4c91b --- /dev/null +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.routes.ts @@ -0,0 +1,15 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { GfAnalysisPageComponent } from './analysis-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfAnalysisPageComponent, + path: '', + title: internalRoutes.portfolio.subRoutes.analysis.title + } +]; diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page-routing.module.ts b/apps/client/src/app/pages/portfolio/fire/fire-page-routing.module.ts deleted file mode 100644 index 96260adda..000000000 --- a/apps/client/src/app/pages/portfolio/fire/fire-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { FirePageComponent } from './fire-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: FirePageComponent, - path: '', - title: 'FIRE' - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class FirePageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index 98a73637f..83650d9ca 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -3,20 +3,31 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/imperso import { UserService } from '@ghostfolio/client/services/user/user.service'; import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { GfFireCalculatorComponent } from '@ghostfolio/ui/fire-calculator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { NgStyle } from '@angular/common'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { Big } from 'big.js'; import { DeviceDetectorService } from 'ngx-device-detector'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ + imports: [ + GfFireCalculatorComponent, + GfPremiumIndicatorComponent, + GfValueComponent, + NgStyle, + NgxSkeletonLoaderModule + ], selector: 'gf-fire-page', styleUrls: ['./fire-page.scss'], - templateUrl: './fire-page.html', - standalone: false + templateUrl: './fire-page.html' }) -export class FirePageComponent implements OnDestroy, OnInit { +export class GfFirePageComponent implements OnDestroy, OnInit { public deviceType: string; public fireWealth: Big; public hasImpersonationId: boolean; diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts deleted file mode 100644 index a606ae1b4..000000000 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { GfFireCalculatorComponent } from '@ghostfolio/ui/fire-calculator'; -import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { FirePageRoutingModule } from './fire-page-routing.module'; -import { FirePageComponent } from './fire-page.component'; - -@NgModule({ - declarations: [FirePageComponent], - imports: [ - CommonModule, - FirePageRoutingModule, - GfFireCalculatorComponent, - GfPremiumIndicatorComponent, - GfValueComponent, - NgxSkeletonLoaderModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class FirePageModule {} diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.routes.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.routes.ts new file mode 100644 index 000000000..1d3926dd1 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.routes.ts @@ -0,0 +1,14 @@ +import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; + +import { Routes } from '@angular/router'; + +import { GfFirePageComponent } from './fire-page.component'; + +export const routes: Routes = [ + { + canActivate: [AuthGuard], + component: GfFirePageComponent, + path: '', + title: 'FIRE' + } +]; diff --git a/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts b/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts deleted file mode 100644 index 20de6f8fa..000000000 --- a/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { PortfolioPageComponent } from './portfolio-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - loadChildren: () => - import('./analysis/analysis-page.module').then( - (m) => m.AnalysisPageModule - ) - }, - { - path: 'activities', - loadChildren: () => - import('./activities/activities-page.module').then( - (m) => m.ActivitiesPageModule - ) - }, - { - path: 'allocations', - loadChildren: () => - import('./allocations/allocations-page.module').then( - (m) => m.AllocationsPageModule - ) - }, - { - path: 'fire', - loadChildren: () => - import('./fire/fire-page.module').then((m) => m.FirePageModule) - }, - { - path: 'x-ray', - loadChildren: () => - import('./x-ray/x-ray-page.module').then((m) => m.XRayPageModule) - } - ], - component: PortfolioPageComponent, - path: '', - title: $localize`Portfolio` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class PortfolioPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts index 3393b7404..387e3fd0f 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts @@ -1,17 +1,28 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { addIcons } from 'ionicons'; +import { + analyticsOutline, + calculatorOutline, + pieChartOutline, + scanOutline, + swapVerticalOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, + imports: [MatTabsModule, RouterModule], selector: 'gf-portfolio-page', styleUrls: ['./portfolio-page.scss'], - templateUrl: './portfolio-page.html', - standalone: false + templateUrl: './portfolio-page.html' }) export class PortfolioPageComponent implements OnDestroy, OnInit { public deviceType: string; @@ -32,28 +43,30 @@ export class PortfolioPageComponent implements OnDestroy, OnInit { this.tabs = [ { iconName: 'analytics-outline', - label: $localize`Analysis`, - path: ['/portfolio'] + label: internalRoutes.portfolio.subRoutes.analysis.title, + routerLink: internalRoutes.portfolio.routerLink }, { iconName: 'swap-vertical-outline', - label: $localize`Activities`, - path: ['/portfolio', 'activities'] + label: internalRoutes.portfolio.subRoutes.activities.title, + routerLink: + internalRoutes.portfolio.subRoutes.activities.routerLink }, { iconName: 'pie-chart-outline', - label: $localize`Allocations`, - path: ['/portfolio', 'allocations'] + label: internalRoutes.portfolio.subRoutes.allocations.title, + routerLink: + internalRoutes.portfolio.subRoutes.allocations.routerLink }, { iconName: 'calculator-outline', - label: 'FIRE ', - path: ['/portfolio', 'fire'] + label: internalRoutes.portfolio.subRoutes.fire.title, + routerLink: internalRoutes.portfolio.subRoutes.fire.routerLink }, { iconName: 'scan-outline', - label: 'X-ray', - path: ['/portfolio', 'x-ray'] + label: internalRoutes.portfolio.subRoutes.xRay.title, + routerLink: internalRoutes.portfolio.subRoutes.xRay.routerLink } ]; this.user = state.user; @@ -61,6 +74,14 @@ export class PortfolioPageComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); } }); + + addIcons({ + analyticsOutline, + calculatorOutline, + pieChartOutline, + scanOutline, + swapVerticalOutline + }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.html b/apps/client/src/app/pages/portfolio/portfolio-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.html +++ b/apps/client/src/app/pages/portfolio/portfolio-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > + import('./analysis/analysis-page.routes').then((m) => m.routes) + }, + { + path: internalRoutes.portfolio.subRoutes.activities.path, + loadChildren: () => + import('./activities/activities-page.routes').then((m) => m.routes) + }, + { + path: internalRoutes.portfolio.subRoutes.allocations.path, + loadChildren: () => + import('./allocations/allocations-page.routes').then((m) => m.routes) + }, + { + path: internalRoutes.portfolio.subRoutes.fire.path, + loadChildren: () => + import('./fire/fire-page.routes').then((m) => m.routes) + }, + { + path: internalRoutes.portfolio.subRoutes.xRay.path, + loadChildren: () => + import('./x-ray/x-ray-page.routes').then((m) => m.routes) + } + ], + component: PortfolioPageComponent, + path: '', + title: internalRoutes.portfolio.title + } +]; diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page-routing.module.ts b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page-routing.module.ts deleted file mode 100644 index 091cbc49f..000000000 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { XRayPageComponent } from './x-ray-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: XRayPageComponent, - path: '', - title: 'X-ray' - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class XRayPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html index ceba5f52c..24ca0f474 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html @@ -7,23 +7,58 @@ risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy.

      -

      +

      @if (isLoading) { - +
      + + +
      } @else { - {{ statistics?.rulesFulfilledCount }} - out of - {{ statistics?.rulesActiveCount }} - rules align with your portfolio. +
      + @if ( + statistics?.rulesActiveCount === 0 || + statistics?.rulesFulfilledCount === 0 + ) { + + } @else if ( + statistics?.rulesFulfilledCount === statistics?.rulesActiveCount + ) { + + } @else { + + } +
      +
      + {{ statistics?.rulesFulfilledCount }} + out of + {{ statistics?.rulesActiveCount }} + rules align with your portfolio. +
      } -

      +
      +
      +

      + Regional Market Cluster Risks + @if (user?.subscription?.type === 'Basic') { + + } +

      + +
      contact us - to use our referral link and get a Ghostfolio Premium membership for - one year. Looking for a student discount? Request it - here - with your university e-mail address. -

      - }

      If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on @@ -179,6 +166,11 @@ [ngClass]="{ active: user?.subscription?.type === 'Premium' }" > + @if (label) { +

      + {{ label }} +
      + } - @if (!user) { + @if (user?.subscription?.type === 'Basic') { +
      +
      +

      + If you plan to open an account at DEGIRO, finpension, + frankly, Interactive Brokers, Swissquote, + VIAC, or Zak, please + contact us + to use our referral link and get a Ghostfolio Premium membership for + one year. Looking for a student discount? Request it + here + with your university e-mail address. +

      +
      +
      + } @else if (!user) {

      - Hello, {{ publicPortfolioDetails?.alias ?? 'someone' }} has shared a + Hello, {{ publicPortfolioDetails?.alias ?? defaultAlias }} has shared a Portfolio with you!

      @@ -72,9 +72,9 @@ @@ -90,10 +90,10 @@ @@ -107,10 +107,10 @@ @@ -126,9 +126,9 @@ @@ -198,10 +198,10 @@
      diff --git a/apps/client/src/app/pages/register/register-page-routing.module.ts b/apps/client/src/app/pages/register/register-page-routing.module.ts index 80ab69b62..157302999 100644 --- a/apps/client/src/app/pages/register/register-page-routing.module.ts +++ b/apps/client/src/app/pages/register/register-page-routing.module.ts @@ -1,4 +1,5 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -10,7 +11,7 @@ const routes: Routes = [ canActivate: [AuthGuard], component: RegisterPageComponent, path: '', - title: $localize`Registration` + title: publicRoutes.register.title } ]; diff --git a/apps/client/src/app/pages/register/register-page.component.ts b/apps/client/src/app/pages/register/register-page.component.ts index 86490688b..11b81c32a 100644 --- a/apps/client/src/app/pages/register/register-page.component.ts +++ b/apps/client/src/app/pages/register/register-page.component.ts @@ -7,11 +7,11 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Router } from '@angular/router'; -import { Role } from '@prisma/client'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { ShowAccessTokenDialogParams } from './show-access-token-dialog/interfaces/interfaces'; import { ShowAccessTokenDialog } from './show-access-token-dialog/show-access-token-dialog.component'; @Component({ @@ -25,6 +25,7 @@ export class RegisterPageComponent implements OnDestroy, OnInit { public demoAuthToken: string; public deviceType: string; public hasPermissionForSocialLogin: boolean; + public hasPermissionForSubscription: boolean; public hasPermissionToCreateUser: boolean; public historicalDataItems: LineChartItem[]; public info: InfoItem; @@ -53,49 +54,42 @@ export class RegisterPageComponent implements OnDestroy, OnInit { globalPermissions, permissions.enableSocialLogin ); + this.hasPermissionForSubscription = hasPermission( + globalPermissions, + permissions.enableSubscription + ); this.hasPermissionToCreateUser = hasPermission( globalPermissions, permissions.createUserAccount ); } - public async createAccount() { - this.dataService - .postUser() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ accessToken, authToken, role }) => { - this.openShowAccessTokenDialog(accessToken, authToken, role); - }); - } - public async onLoginWithInternetIdentity() { try { const { authToken } = await this.internetIdentityService.login(); + this.tokenStorageService.saveToken(authToken); - this.router.navigate(['/']); + + await this.router.navigate(['/']); } catch {} } - public openShowAccessTokenDialog( - accessToken: string, - authToken: string, - role: Role - ) { + public openShowAccessTokenDialog() { const dialogRef = this.dialog.open(ShowAccessTokenDialog, { data: { - accessToken, - authToken, - role - }, + deviceType: this.deviceType, + needsToAcceptTermsOfService: this.hasPermissionForSubscription + } as ShowAccessTokenDialogParams, disableClose: true, - width: '30rem' + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '30rem' }); dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data) => { - if (data?.authToken) { + .subscribe((authToken) => { + if (authToken) { this.tokenStorageService.saveToken(authToken, true); this.router.navigate(['/']); diff --git a/apps/client/src/app/pages/register/register-page.html b/apps/client/src/app/pages/register/register-page.html index 903aedccf..eee49083a 100644 --- a/apps/client/src/app/pages/register/register-page.html +++ b/apps/client/src/app/pages/register/register-page.html @@ -22,7 +22,7 @@ class="d-inline-block" color="primary" mat-flat-button - (click)="createAccount()" + (click)="openShowAccessTokenDialog()" > Create Account diff --git a/apps/client/src/app/pages/register/register-page.module.ts b/apps/client/src/app/pages/register/register-page.module.ts index b6e917e6d..5ce8e3ed9 100644 --- a/apps/client/src/app/pages/register/register-page.module.ts +++ b/apps/client/src/app/pages/register/register-page.module.ts @@ -4,6 +4,7 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; import { RegisterPageRoutingModule } from './register-page-routing.module'; import { RegisterPageComponent } from './register-page.component'; @@ -14,6 +15,7 @@ import { ShowAccessTokenDialogModule } from './show-access-token-dialog/show-acc imports: [ CommonModule, GfLogoComponent, + IonIcon, MatButtonModule, RegisterPageRoutingModule, RouterModule, diff --git a/apps/client/src/app/pages/register/show-access-token-dialog/interfaces/interfaces.ts b/apps/client/src/app/pages/register/show-access-token-dialog/interfaces/interfaces.ts new file mode 100644 index 000000000..c32acac40 --- /dev/null +++ b/apps/client/src/app/pages/register/show-access-token-dialog/interfaces/interfaces.ts @@ -0,0 +1,4 @@ +export interface ShowAccessTokenDialogParams { + deviceType: string; + needsToAcceptTermsOfService: boolean; +} diff --git a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts index 5aacbd457..f154851df 100644 --- a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts +++ b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts @@ -1,19 +1,74 @@ -import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { DataService } from '@ghostfolio/client/services/data.service'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + Inject, + ViewChild +} from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatStepper } from '@angular/material/stepper'; +import { addIcons } from 'ionicons'; +import { + arrowForwardOutline, + checkmarkOutline, + copyOutline +} from 'ionicons/icons'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import { ShowAccessTokenDialogParams } from './interfaces/interfaces'; @Component({ - selector: 'gf-show-access-token-dialog', changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'gf-show-access-token-dialog', + standalone: false, styleUrls: ['./show-access-token-dialog.scss'], - templateUrl: 'show-access-token-dialog.html', - standalone: false + templateUrl: 'show-access-token-dialog.html' }) export class ShowAccessTokenDialog { - public isAgreeButtonDisabled = true; + @ViewChild(MatStepper) stepper!: MatStepper; - public constructor(@Inject(MAT_DIALOG_DATA) public data: any) {} + public accessToken: string; + public authToken: string; + public isCreateAccountButtonDisabled = true; + public isDisclaimerChecked = false; + public role: string; + public routerLinkAboutTermsOfService = + publicRoutes.about.subRoutes.termsOfService.routerLink; + + private unsubscribeSubject = new Subject(); + + public constructor( + private changeDetectorRef: ChangeDetectorRef, + @Inject(MAT_DIALOG_DATA) public data: ShowAccessTokenDialogParams, + private dataService: DataService + ) { + addIcons({ arrowForwardOutline, checkmarkOutline, copyOutline }); + } + + public createAccount() { + this.dataService + .postUser() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ accessToken, authToken, role }) => { + this.accessToken = accessToken; + this.authToken = authToken; + this.role = role; + + this.stepper.next(); + + this.changeDetectorRef.markForCheck(); + }); + } + + public enableCreateAccountButton() { + this.isCreateAccountButtonDisabled = false; + } - public enableAgreeButton() { - this.isAgreeButtonDisabled = false; + public onChangeDislaimerChecked() { + this.isDisclaimerChecked = !this.isDisclaimerChecked; } } diff --git a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html index 0a6a2e5e3..c37abeadd 100644 --- a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html +++ b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1,48 +1,112 @@

      Create Account - @if (data.role === 'ADMIN') { - {{ data.role }} + @if (role === 'ADMIN') { + {{ role }} }

      -
      - -
      - - + + + Security Token +
      + Here is your security token. It is only visible once, please store + and keep it in a safe place. +
      + + Security Token + +
      + +
      +
      +
      +
      + +
      +
      +
      + + + + + +
      diff --git a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.module.ts b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.module.ts index d537fbe7f..0c7a6fc85 100644 --- a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.module.ts +++ b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.module.ts @@ -4,9 +4,12 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; +import { MatStepperModule } from '@angular/material/stepper'; +import { RouterModule } from '@angular/router'; import { ShowAccessTokenDialog } from './show-access-token-dialog.component'; @@ -17,10 +20,13 @@ import { ShowAccessTokenDialog } from './show-access-token-dialog.component'; CommonModule, FormsModule, MatButtonModule, + MatCheckboxModule, MatDialogModule, MatFormFieldModule, MatInputModule, + MatStepperModule, ReactiveFormsModule, + RouterModule, TextFieldModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.scss b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.scss index dc9093b45..0198e38bf 100644 --- a/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.scss +++ b/apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.scss @@ -1,2 +1,16 @@ :host { + --mat-dialog-with-actions-content-padding: 0; + + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + } + } + + .mat-mdc-dialog-actions { + padding: 0 !important; + } } diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts deleted file mode 100644 index 0ca4ecd4f..000000000 --- a/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ResourcesGlossaryPageComponent } from './resources-glossary.component'; - -const routes: Routes = [ - { - component: ResourcesGlossaryPageComponent, - path: '', - title: $localize`Glossary` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ResourcesGlossaryRoutingModule {} diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts index b6749b5cd..96958dd70 100644 --- a/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts @@ -1,22 +1,22 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { InfoItem } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnInit } from '@angular/core'; +import { RouterModule } from '@angular/router'; @Component({ + imports: [RouterModule], selector: 'gf-resources-glossary', styleUrls: ['./resources-glossary.component.scss'], - templateUrl: './resources-glossary.component.html', - standalone: false + templateUrl: './resources-glossary.component.html' }) export class ResourcesGlossaryPageComponent implements OnInit { public hasPermissionForSubscription: boolean; public info: InfoItem; - public routerLinkResourcesPersonalFinanceTools = [ - '/' + $localize`:snake-case:resources`, - 'personal-finance-tools' - ]; + public routerLinkResourcesPersonalFinanceTools = + publicRoutes.resources.subRoutes.personalFinanceTools.routerLink; public constructor(private dataService: DataService) { this.info = this.dataService.fetchInfo(); diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts deleted file mode 100644 index ee01909e9..000000000 --- a/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { ResourcesGlossaryRoutingModule } from './resources-glossary-routing.module'; -import { ResourcesGlossaryPageComponent } from './resources-glossary.component'; - -@NgModule({ - declarations: [ResourcesGlossaryPageComponent], - imports: [CommonModule, ResourcesGlossaryRoutingModule, RouterModule] -}) -export class ResourcesGlossaryPageModule {} diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.routes.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary.routes.ts new file mode 100644 index 000000000..2f864155a --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.routes.ts @@ -0,0 +1,13 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { ResourcesGlossaryPageComponent } from './resources-glossary.component'; + +export const routes: Routes = [ + { + component: ResourcesGlossaryPageComponent, + path: '', + title: publicRoutes.resources.subRoutes.glossary.title + } +]; diff --git a/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts b/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts deleted file mode 100644 index 468881733..000000000 --- a/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ResourcesGuidesComponent } from './resources-guides.component'; - -const routes: Routes = [ - { - component: ResourcesGuidesComponent, - path: '', - title: $localize`Guides` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ResourcesGuidesRoutingModule {} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.component.ts b/apps/client/src/app/pages/resources/guides/resources-guides.component.ts index ddba58e69..52c317cea 100644 --- a/apps/client/src/app/pages/resources/guides/resources-guides.component.ts +++ b/apps/client/src/app/pages/resources/guides/resources-guides.component.ts @@ -1,9 +1,10 @@ import { Component } from '@angular/core'; +import { RouterModule } from '@angular/router'; @Component({ + imports: [RouterModule], selector: 'gf-resources-guides', styleUrls: ['./resources-guides.component.scss'], - templateUrl: './resources-guides.component.html', - standalone: false + templateUrl: './resources-guides.component.html' }) export class ResourcesGuidesComponent {} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.module.ts b/apps/client/src/app/pages/resources/guides/resources-guides.module.ts deleted file mode 100644 index ed6ce1b2d..000000000 --- a/apps/client/src/app/pages/resources/guides/resources-guides.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { ResourcesGuidesRoutingModule } from './resources-guides-routing.module'; -import { ResourcesGuidesComponent } from './resources-guides.component'; - -@NgModule({ - declarations: [ResourcesGuidesComponent], - imports: [CommonModule, ResourcesGuidesRoutingModule, RouterModule] -}) -export class ResourcesGuidesModule {} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.routes.ts b/apps/client/src/app/pages/resources/guides/resources-guides.routes.ts new file mode 100644 index 000000000..f9f65f44a --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides.routes.ts @@ -0,0 +1,13 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { ResourcesGuidesComponent } from './resources-guides.component'; + +export const routes: Routes = [ + { + component: ResourcesGuidesComponent, + path: '', + title: publicRoutes.resources.subRoutes.guides.title + } +]; diff --git a/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts b/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts deleted file mode 100644 index c8cdb1026..000000000 --- a/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ResourcesMarketsComponent } from './resources-markets.component'; - -const routes: Routes = [ - { - component: ResourcesMarketsComponent, - path: '', - title: $localize`Markets` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ResourcesMarketsRoutingModule {} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.component.ts b/apps/client/src/app/pages/resources/markets/resources-markets.component.ts index a188e3a94..79c185959 100644 --- a/apps/client/src/app/pages/resources/markets/resources-markets.component.ts +++ b/apps/client/src/app/pages/resources/markets/resources-markets.component.ts @@ -3,7 +3,6 @@ import { Component } from '@angular/core'; @Component({ selector: 'gf-resources-markets', styleUrls: ['./resources-markets.component.scss'], - templateUrl: './resources-markets.component.html', - standalone: false + templateUrl: './resources-markets.component.html' }) export class ResourcesMarketsComponent {} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.module.ts b/apps/client/src/app/pages/resources/markets/resources-markets.module.ts deleted file mode 100644 index 3ec93bb3b..000000000 --- a/apps/client/src/app/pages/resources/markets/resources-markets.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; - -import { ResourcesMarketsRoutingModule } from './resources-markets-routing.module'; -import { ResourcesMarketsComponent } from './resources-markets.component'; - -@NgModule({ - declarations: [ResourcesMarketsComponent], - imports: [CommonModule, ResourcesMarketsRoutingModule] -}) -export class ResourcesMarketsModule {} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.routes.ts b/apps/client/src/app/pages/resources/markets/resources-markets.routes.ts new file mode 100644 index 000000000..4bcb66789 --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets.routes.ts @@ -0,0 +1,13 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + +import { Routes } from '@angular/router'; + +import { ResourcesMarketsComponent } from './resources-markets.component'; + +export const routes: Routes = [ + { + component: ResourcesMarketsComponent, + path: '', + title: publicRoutes.resources.subRoutes.markets.title + } +]; diff --git a/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts b/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts deleted file mode 100644 index 3fada1fc3..000000000 --- a/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ResourcesOverviewComponent } from './resources-overview.component'; - -const routes: Routes = [ - { - component: ResourcesOverviewComponent, - path: '' - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ResourcesOverviewRoutingModule {} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.html b/apps/client/src/app/pages/resources/overview/resources-overview.component.html index ad424f05c..39d7c1e62 100644 --- a/apps/client/src/app/pages/resources/overview/resources-overview.component.html +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -7,7 +7,7 @@

      {{ item.title }}

      {{ item.description }}

      - Explore {{ item.title }} → + Explore {{ item.title }} →
      }
      diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.ts b/apps/client/src/app/pages/resources/overview/resources-overview.component.ts index f95e78a26..81338200f 100644 --- a/apps/client/src/app/pages/resources/overview/resources-overview.component.ts +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.ts @@ -1,45 +1,39 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + import { Component } from '@angular/core'; +import { RouterModule } from '@angular/router'; @Component({ + imports: [RouterModule], selector: 'gf-resources-overview', styleUrls: ['./resources-overview.component.scss'], - templateUrl: './resources-overview.component.html', - standalone: false + templateUrl: './resources-overview.component.html' }) export class ResourcesOverviewComponent { public overviewItems = [ { - title: 'Frequently Asked Questions (FAQ)', description: 'Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.', - link: ['/' + $localize`:snake-case:faq`] + routerLink: publicRoutes.faq.routerLink, + title: publicRoutes.faq.title }, { - title: 'Guides', description: 'Explore our guides to help you get started with investing and managing your finances.', - link: [ - '/' + $localize`:snake-case:resources`, - $localize`:snake-case:guides` - ] + routerLink: publicRoutes.resources.subRoutes.guides.routerLink, + title: publicRoutes.resources.subRoutes.guides.title }, { - title: 'Markets', description: 'Access various market resources and tools to stay informed about financial markets.', - link: [ - '/' + $localize`:snake-case:resources`, - $localize`:snake-case:markets` - ] + routerLink: publicRoutes.resources.subRoutes.markets.routerLink, + title: publicRoutes.resources.subRoutes.markets.title }, { - title: 'Glossary', description: 'Learn key financial terms and concepts in our comprehensive glossary.', - link: [ - '/' + $localize`:snake-case:resources`, - $localize`:snake-case:glossary` - ] + routerLink: publicRoutes.resources.subRoutes.glossary.routerLink, + title: publicRoutes.resources.subRoutes.glossary.title } ]; } diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.module.ts b/apps/client/src/app/pages/resources/overview/resources-overview.module.ts deleted file mode 100644 index 8057e7d2f..000000000 --- a/apps/client/src/app/pages/resources/overview/resources-overview.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { ResourcesOverviewRoutingModule } from './resources-overview-routing.module'; -import { ResourcesOverviewComponent } from './resources-overview.component'; - -@NgModule({ - declarations: [ResourcesOverviewComponent], - imports: [CommonModule, ResourcesOverviewRoutingModule, RouterModule] -}) -export class ResourcesOverviewModule {} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.routes.ts b/apps/client/src/app/pages/resources/overview/resources-overview.routes.ts new file mode 100644 index 000000000..a6ddbf995 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview.routes.ts @@ -0,0 +1,10 @@ +import { Routes } from '@angular/router'; + +import { ResourcesOverviewComponent } from './resources-overview.component'; + +export const routes: Routes = [ + { + component: ResourcesOverviewComponent, + path: '' + } +]; diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts index c9c0aa044..c4cfd184e 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts +++ b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts @@ -1,25 +1,39 @@ import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnDestroy } from '@angular/core'; +import { MatCardModule } from '@angular/material/card'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { chevronForwardOutline } from 'ionicons/icons'; import { Subject } from 'rxjs'; @Component({ host: { class: 'page' }, + imports: [IonIcon, MatCardModule, RouterModule], selector: 'gf-personal-finance-tools-page', styleUrls: ['./personal-finance-tools-page.scss'], - templateUrl: './personal-finance-tools-page.html', - standalone: false + templateUrl: './personal-finance-tools-page.html' }) export class PersonalFinanceToolsPageComponent implements OnDestroy { - public pathAlternativeTo = $localize`open-source-alternative-to` + '-'; - public pathResources = '/' + $localize`resources`; + public pathAlternativeTo = + publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product + .path + '-'; + public pathResources = publicRoutes.resources.path; + public pathPersonalFinanceTools = + publicRoutes.resources.subRoutes.personalFinanceTools.path; public personalFinanceTools = personalFinanceTools.sort((a, b) => { return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }); }); - public routerLinkAbout = ['/' + $localize`:snake-case:about`]; + public routerLinkAbout = publicRoutes.about.routerLink; private unsubscribeSubject = new Subject(); + public constructor() { + addIcons({ chevronForwardOutline }); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html index f3c128433..3e4784307 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html +++ b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html @@ -32,8 +32,8 @@ personalFinanceTool.name }} - {{ personalFinanceTool.slogan }}" [routerLink]="[ - pathResources, - 'personal-finance-tools', + '/' + pathResources, + pathPersonalFinanceTools, pathAlternativeTo + (personalFinanceTool.alias ?? personalFinanceTool.key) ]" diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.module.ts b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.module.ts deleted file mode 100644 index b8d6c947d..000000000 --- a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatCardModule } from '@angular/material/card'; - -import { PersonalFinanceToolsPageRoutingModule } from './personal-finance-tools-page-routing.module'; -import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component'; - -@NgModule({ - declarations: [PersonalFinanceToolsPageComponent], - imports: [CommonModule, MatCardModule, PersonalFinanceToolsPageRoutingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class PersonalFinanceToolsPageModule {} diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.routes.ts similarity index 60% rename from apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts rename to apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.routes.ts index 01d920460..9081f6b28 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts +++ b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.routes.ts @@ -1,17 +1,17 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component'; -const routes: Routes = [ +export const routes: Routes = [ { canActivate: [AuthGuard], component: PersonalFinanceToolsPageComponent, path: '', - title: $localize`Personal Finance Tools` + title: publicRoutes.resources.subRoutes.personalFinanceTools.title }, ...personalFinanceTools.map(({ alias, key, name }) => { return { @@ -23,14 +23,8 @@ const routes: Routes = [ return GfProductPageComponent; } ), - path: $localize`open-source-alternative-to` + `-${alias ?? key}`, - title: $localize`Open Source Alternative to ${name}` + path: `${publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product.path}-${alias ?? key}`, + title: `${publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product.title} ${name}` }; }) ]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class PersonalFinanceToolsPageRoutingModule {} diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts index 3a0ec4ffb..caf29e7a0 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts +++ b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -1,16 +1,16 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { Product } from '@ghostfolio/common/interfaces'; import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { translate } from '@ghostfolio/ui/i18n'; -import { CommonModule } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { ActivatedRoute, RouterModule } from '@angular/router'; @Component({ host: { class: 'page' }, - imports: [CommonModule, MatButtonModule, RouterModule], + imports: [MatButtonModule, RouterModule], selector: 'gf-product-page', styleUrls: ['./product-page.scss'], templateUrl: './product-page.html' @@ -20,12 +20,10 @@ export class GfProductPageComponent implements OnInit { public price: number; public product1: Product; public product2: Product; - public routerLinkAbout = ['/' + $localize`:snake-case:about`]; - public routerLinkFeatures = ['/' + $localize`:snake-case:features`]; - public routerLinkResourcesPersonalFinanceTools = [ - '/' + $localize`:snake-case:resources`, - 'personal-finance-tools' - ]; + public routerLinkAbout = publicRoutes.about.routerLink; + public routerLinkFeatures = publicRoutes.features.routerLink; + public routerLinkResourcesPersonalFinanceTools = + publicRoutes.resources.subRoutes.personalFinanceTools.routerLink; public tags: string[]; public constructor( @@ -34,9 +32,9 @@ export class GfProductPageComponent implements OnInit { ) {} public ngOnInit() { - const { subscriptionOffers } = this.dataService.fetchInfo(); + const { subscriptionOffer } = this.dataService.fetchInfo(); - this.price = subscriptionOffers?.default?.price; + this.price = subscriptionOffer?.price; this.product1 = { founded: 2021, diff --git a/apps/client/src/app/pages/resources/resources-page-routing.module.ts b/apps/client/src/app/pages/resources/resources-page-routing.module.ts deleted file mode 100644 index bcbe1bad5..000000000 --- a/apps/client/src/app/pages/resources/resources-page-routing.module.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ResourcesPageComponent } from './resources-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: ResourcesPageComponent, - children: [ - { - path: '', - loadChildren: () => - import('./overview/resources-overview.module').then( - (m) => m.ResourcesOverviewModule - ) - }, - { - path: $localize`:snake-case:glossary`, - loadChildren: () => - import('./glossary/resources-glossary.module').then( - (m) => m.ResourcesGlossaryPageModule - ) - }, - { - path: $localize`:snake-case:guides`, - loadChildren: () => - import('./guides/resources-guides.module').then( - (m) => m.ResourcesGuidesModule - ) - }, - { - path: $localize`:snake-case:markets`, - loadChildren: () => - import('./markets/resources-markets.module').then( - (m) => m.ResourcesMarketsModule - ) - }, - ...['personal-finance-tools'].map((path) => ({ - path, - loadChildren: () => - import( - './personal-finance-tools/personal-finance-tools-page.module' - ).then((m) => m.PersonalFinanceToolsPageModule) - })) - ], - path: '', - title: $localize`Resources` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class ResourcesPageRoutingModule {} diff --git a/apps/client/src/app/pages/resources/resources-page.component.ts b/apps/client/src/app/pages/resources/resources-page.component.ts index d0534417d..9db996f57 100644 --- a/apps/client/src/app/pages/resources/resources-page.component.ts +++ b/apps/client/src/app/pages/resources/resources-page.component.ts @@ -1,42 +1,57 @@ +import { TabConfiguration } from '@ghostfolio/common/interfaces'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + import { Component, OnInit } from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + bookOutline, + libraryOutline, + newspaperOutline, + readerOutline +} from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, + imports: [IonIcon, MatTabsModule, RouterModule], selector: 'gf-resources-page', styleUrls: ['./resources-page.scss'], - templateUrl: './resources-page.html', - standalone: false + templateUrl: './resources-page.html' }) export class ResourcesPageComponent implements OnInit { public deviceType: string; - public tabs = [ + public tabs: TabConfiguration[] = [ { - path: '.', + iconName: 'reader-outline', label: $localize`Overview`, - iconName: 'reader-outline' + routerLink: publicRoutes.resources.routerLink }, { - path: 'guides', label: $localize`Guides`, - iconName: 'book-outline' + iconName: 'book-outline', + routerLink: publicRoutes.resources.subRoutes.guides.routerLink }, { - path: 'markets', + iconName: 'newspaper-outline', label: $localize`Markets`, - iconName: 'newspaper-outline' + routerLink: publicRoutes.resources.subRoutes.markets.routerLink }, { - path: 'glossary', + iconName: 'library-outline', label: $localize`Glossary`, - iconName: 'library-outline' + routerLink: publicRoutes.resources.subRoutes.glossary.routerLink } ]; private unsubscribeSubject = new Subject(); - public constructor(private deviceService: DeviceDetectorService) {} + public constructor(private deviceService: DeviceDetectorService) { + addIcons({ bookOutline, libraryOutline, newspaperOutline, readerOutline }); + } public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; diff --git a/apps/client/src/app/pages/resources/resources-page.html b/apps/client/src/app/pages/resources/resources-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/resources/resources-page.html +++ b/apps/client/src/app/pages/resources/resources-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > + import('./overview/resources-overview.routes').then((m) => m.routes) + }, + { + path: publicRoutes.resources.subRoutes.glossary.path, + loadChildren: () => + import('./glossary/resources-glossary.routes').then((m) => m.routes) + }, + { + path: publicRoutes.resources.subRoutes.guides.path, + loadChildren: () => + import('./guides/resources-guides.routes').then((m) => m.routes) + }, + { + path: publicRoutes.resources.subRoutes.markets.path, + loadChildren: () => + import('./markets/resources-markets.routes').then((m) => m.routes) + }, + { + path: publicRoutes.resources.subRoutes.personalFinanceTools.path, + loadChildren: () => + import( + './personal-finance-tools/personal-finance-tools-page.routes' + ).then((m) => m.routes) + } + ], + path: '', + title: publicRoutes.resources.title + } +]; diff --git a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts b/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts deleted file mode 100644 index ae8002d7f..000000000 --- a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { UserAccountAccessComponent } from '@ghostfolio/client/components/user-account-access/user-account-access.component'; -import { UserAccountMembershipComponent } from '@ghostfolio/client/components/user-account-membership/user-account-membership.component'; -import { UserAccountSettingsComponent } from '@ghostfolio/client/components/user-account-settings/user-account-settings.component'; -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { UserAccountPageComponent } from './user-account-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - children: [ - { - path: '', - component: UserAccountSettingsComponent, - title: $localize`Settings` - }, - { - path: 'membership', - component: UserAccountMembershipComponent, - title: $localize`Membership` - }, - { - path: 'access', - component: UserAccountAccessComponent, - title: $localize`Access` - } - ], - component: UserAccountPageComponent, - path: '', - title: $localize`My Ghostfolio` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class UserAccountPageRoutingModule {} diff --git a/apps/client/src/app/pages/user-account/user-account-page.component.ts b/apps/client/src/app/pages/user-account/user-account-page.component.ts index d53465faa..7341660f2 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.component.ts +++ b/apps/client/src/app/pages/user-account/user-account-page.component.ts @@ -1,18 +1,31 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + OnDestroy, + OnInit +} from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { diamondOutline, keyOutline, settingsOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, + imports: [IonIcon, MatTabsModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-user-account-page', styleUrls: ['./user-account-page.scss'], - templateUrl: './user-account-page.html', - standalone: false + templateUrl: './user-account-page.html' }) -export class UserAccountPageComponent implements OnDestroy, OnInit { +export class GfUserAccountPageComponent implements OnDestroy, OnInit { public deviceType: string; public tabs: TabConfiguration[] = []; public user: User; @@ -33,25 +46,28 @@ export class UserAccountPageComponent implements OnDestroy, OnInit { this.tabs = [ { iconName: 'settings-outline', - label: $localize`Settings`, - path: ['/account'] + label: internalRoutes.account.title, + routerLink: internalRoutes.account.routerLink }, { iconName: 'diamond-outline', - label: $localize`Membership`, - path: ['/account/membership'], + label: internalRoutes.account.subRoutes.membership.title, + routerLink: + internalRoutes.account.subRoutes.membership.routerLink, showCondition: !!this.user?.subscription }, { iconName: 'key-outline', - label: $localize`Access`, - path: ['/account', 'access'] + label: internalRoutes.account.subRoutes.access.title, + routerLink: internalRoutes.account.subRoutes.access.routerLink } ]; this.changeDetectorRef.markForCheck(); } }); + + addIcons({ diamondOutline, keyOutline, settingsOutline }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/user-account/user-account-page.html b/apps/client/src/app/pages/user-account/user-account-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.html +++ b/apps/client/src/app/pages/user-account/user-account-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > Oops, authentication has failed. -
      or
      -
      diff --git a/apps/client/src/app/pages/zen/zen-page-routing.module.ts b/apps/client/src/app/pages/zen/zen-page-routing.module.ts index 96eedadde..84099425c 100644 --- a/apps/client/src/app/pages/zen/zen-page-routing.module.ts +++ b/apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -1,6 +1,7 @@ -import { HomeHoldingsComponent } from '@ghostfolio/client/components/home-holdings/home-holdings.component'; -import { HomeOverviewComponent } from '@ghostfolio/client/components/home-overview/home-overview.component'; +import { GfHomeHoldingsComponent } from '@ghostfolio/client/components/home-holdings/home-holdings.component'; +import { GfHomeOverviewComponent } from '@ghostfolio/client/components/home-overview/home-overview.component'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -11,12 +12,19 @@ const routes: Routes = [ { canActivate: [AuthGuard], children: [ - { path: '', component: HomeOverviewComponent }, - { path: 'holdings', component: HomeHoldingsComponent } + { + path: '', + component: GfHomeOverviewComponent + }, + { + path: internalRoutes.zen.subRoutes.holdings.path, + component: GfHomeHoldingsComponent, + title: internalRoutes.home.subRoutes.holdings.title + } ], component: ZenPageComponent, path: '', - title: $localize`Overview` + title: internalRoutes.zen.title } ]; diff --git a/apps/client/src/app/pages/zen/zen-page.component.ts b/apps/client/src/app/pages/zen/zen-page.component.ts index c39cecccd..397a2eb47 100644 --- a/apps/client/src/app/pages/zen/zen-page.component.ts +++ b/apps/client/src/app/pages/zen/zen-page.component.ts @@ -1,7 +1,10 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { addIcons } from 'ionicons'; +import { analyticsOutline, walletOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -32,13 +35,13 @@ export class ZenPageComponent implements OnDestroy, OnInit { this.tabs = [ { iconName: 'analytics-outline', - label: $localize`Overview`, - path: ['/zen'] + label: internalRoutes.zen.title, + routerLink: internalRoutes.zen.routerLink }, { iconName: 'wallet-outline', - label: $localize`Holdings`, - path: ['/zen', 'holdings'] + label: internalRoutes.zen.subRoutes.holdings.title, + routerLink: internalRoutes.zen.subRoutes.holdings.routerLink } ]; this.user = state.user; @@ -46,6 +49,8 @@ export class ZenPageComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); } }); + + addIcons({ analyticsOutline, walletOutline }); } public ngOnInit() { diff --git a/apps/client/src/app/pages/zen/zen-page.html b/apps/client/src/app/pages/zen/zen-page.html index a9dbee450..af3b24b0a 100644 --- a/apps/client/src/app/pages/zen/zen-page.html +++ b/apps/client/src/app/pages/zen/zen-page.html @@ -16,7 +16,7 @@ mat-tab-link routerLinkActive [active]="rla.isActive" - [routerLink]="tab.path" + [routerLink]="tab.routerLink" [routerLinkActiveOptions]="{ exact: true }" > (`/api/v1/tag/${aId}`); - } - public executeJob(aId: string) { return this.http.get(`/api/v1/admin/queue/job/${aId}/execute`); } @@ -123,19 +113,15 @@ export class AdminService { }); } - public fetchGhostfolioDataProviderStatus() { - return this.fetchAdminData().pipe( - switchMap(({ settings }) => { - const headers = new HttpHeaders({ - [HEADER_KEY_SKIP_INTERCEPTOR]: 'true', - [HEADER_KEY_TOKEN]: `Api-Key ${settings[PROPERTY_API_KEY_GHOSTFOLIO]}` - }); - - return this.http.get( - `${environment.production ? 'https://ghostfol.io' : ''}/api/v2/data-providers/ghostfolio/status`, - { headers } - ); - }) + public fetchGhostfolioDataProviderStatus(aApiKey: string) { + const headers = new HttpHeaders({ + [HEADER_KEY_SKIP_INTERCEPTOR]: 'true', + [HEADER_KEY_TOKEN]: `Api-Key ${aApiKey}` + }); + + return this.http.get( + `${environment.production ? 'https://ghostfol.io' : ''}/api/v2/data-providers/ghostfolio/status`, + { headers } ); } @@ -155,10 +141,6 @@ export class AdminService { return this.http.get('/api/v1/platform'); } - public fetchTags() { - return this.http.get('/api/v1/tag'); - } - public fetchUsers({ skip, take = DEFAULT_PAGE_SIZE @@ -196,19 +178,8 @@ export class AdminService { ); } - public gatherSymbol({ - dataSource, - date, - symbol - }: AssetProfileIdentifier & { - date?: Date; - }) { - let url = `/api/v1/admin/gather/${dataSource}/${symbol}`; - - if (date) { - url = `${url}/${format(date, DATE_FORMAT)}`; - } - + public gatherSymbol({ dataSource, symbol }: AssetProfileIdentifier) { + const url = `/api/v1/admin/gather/${dataSource}/${symbol}`; return this.http.post(url, {}); } @@ -226,20 +197,24 @@ export class AdminService { return this.http.get(url); } - public patchAssetProfile({ - assetClass, - assetSubClass, - comment, - countries, - currency, - dataSource, - name, - scraperConfiguration, - sectors, - symbol, - symbolMapping, - url - }: AssetProfileIdentifier & UpdateAssetProfileDto) { + public patchAssetProfile( + { dataSource, symbol }: AssetProfileIdentifier, + { + assetClass, + assetSubClass, + comment, + countries, + currency, + dataSource: newDataSource, + isActive, + name, + scraperConfiguration, + sectors, + symbol: newSymbol, + symbolMapping, + url + }: UpdateAssetProfileDto + ) { return this.http.patch( `/api/v1/admin/profile-data/${dataSource}/${symbol}`, { @@ -248,9 +223,12 @@ export class AdminService { comment, countries, currency, + dataSource: newDataSource, + isActive, name, scraperConfiguration, sectors, + symbol: newSymbol, symbolMapping, url } @@ -261,10 +239,6 @@ export class AdminService { return this.http.post(`/api/v1/platform`, aPlatform); } - public postTag(aTag: CreateTagDto) { - return this.http.post(`/api/v1/tag`, aTag); - } - public putPlatform(aPlatform: UpdatePlatformDto) { return this.http.put( `/api/v1/platform/${aPlatform.id}`, @@ -272,8 +246,8 @@ export class AdminService { ); } - public putTag(aTag: UpdateTagDto) { - return this.http.put(`/api/v1/tag/${aTag.id}`, aTag); + public syncDemoUserAccount() { + return this.http.get(`/api/v1/admin/demo-user/sync`); } public testMarketData({ diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 269a03e31..820ad5e3c 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -4,51 +4,66 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto import { TransferBalanceDto } from '@ghostfolio/api/app/account/transfer-balance.dto'; import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto'; import { UpdateBulkMarketDataDto } from '@ghostfolio/api/app/admin/update-bulk-market-data.dto'; +import { CreateTagDto } from '@ghostfolio/api/app/endpoints/tags/create-tag.dto'; +import { UpdateTagDto } from '@ghostfolio/api/app/endpoints/tags/update-tag.dto'; +import { CreateWatchlistItemDto } from '@ghostfolio/api/app/endpoints/watchlist/create-watchlist-item.dto'; import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activities, Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto'; -import { PortfolioHoldingDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-holding-detail.interface'; import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; import { DeleteOwnUserDto } from '@ghostfolio/api/app/user/delete-own-user.dto'; import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface'; +import { UpdateOwnAccessTokenDto } from '@ghostfolio/api/app/user/update-own-access-token.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { Access, + AccessTokenResponse, AccountBalancesResponse, - Accounts, + AccountsResponse, + AiPromptResponse, ApiKeyResponse, AssetProfileIdentifier, BenchmarkMarketDataDetails, BenchmarkResponse, + DataProviderHealthResponse, Export, Filter, ImportResponse, InfoItem, LookupResponse, MarketDataDetailsResponse, + MarketDataOfMarketsResponse, OAuthResponse, PortfolioDetails, PortfolioDividends, + PortfolioHoldingResponse, PortfolioHoldingsResponse, PortfolioInvestments, PortfolioPerformanceResponse, PortfolioReportResponse, PublicPortfolioResponse, - User + User, + WatchlistResponse } from '@ghostfolio/common/interfaces'; import { filterGlobalPermissions } from '@ghostfolio/common/permissions'; -import { AccountWithValue, DateRange, GroupBy } from '@ghostfolio/common/types'; +import type { + AccountWithValue, + AiPromptMode, + DateRange, + GroupBy +} from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; +import { utc } from '@date-fns/utc'; import { AccountBalance, DataSource, @@ -179,7 +194,7 @@ export class DataService { public fetchAccounts({ filters }: { filters?: Filter[] } = {}) { const params = this.buildFiltersAsQueryParams({ filters }); - return this.http.get('/api/v1/account', { params }); + return this.http.get('/api/v1/account', { params }); } public fetchActivities({ @@ -273,7 +288,7 @@ export class DataService { symbol: string; }) { return this.http.get( - `/api/v1/exchange-rate/${symbol}/${format(date, DATE_FORMAT)}` + `/api/v1/exchange-rate/${symbol}/${format(date, DATE_FORMAT, { in: utc })}` ); } @@ -300,17 +315,25 @@ export class DataService { } public deleteBenchmark({ dataSource, symbol }: AssetProfileIdentifier) { - return this.http.delete(`/api/v1/benchmark/${dataSource}/${symbol}`); + return this.http.delete(`/api/v1/benchmarks/${dataSource}/${symbol}`); } public deleteOwnUser(aData: DeleteOwnUserDto) { return this.http.delete(`/api/v1/user`, { body: aData }); } + public deleteTag(aId: string) { + return this.http.delete(`/api/v1/tags/${aId}`); + } + public deleteUser(aId: string) { return this.http.delete(`/api/v1/user/${aId}`); } + public deleteWatchlistItem({ dataSource, symbol }: AssetProfileIdentifier) { + return this.http.delete(`/api/v1/watchlist/${dataSource}/${symbol}`); + } + public fetchAccesses() { return this.http.get('/api/v1/access'); } @@ -331,30 +354,39 @@ export class DataService { public fetchBenchmarkForUser({ dataSource, + filters, range, startDate, - symbol + symbol, + withExcludedAccounts }: { + filters?: Filter[]; range: DateRange; startDate: Date; + withExcludedAccounts?: boolean; } & AssetProfileIdentifier): Observable { - let params = new HttpParams(); + let params = this.buildFiltersAsQueryParams({ filters }); - if (range) { - params = params.append('range', range); + params = params.append('range', range); + + if (withExcludedAccounts) { + params = params.append('withExcludedAccounts', withExcludedAccounts); } return this.http.get( - `/api/v1/benchmark/${dataSource}/${symbol}/${format( - startDate, - DATE_FORMAT - )}`, + `/api/v1/benchmarks/${dataSource}/${symbol}/${format(startDate, DATE_FORMAT, { in: utc })}`, { params } ); } public fetchBenchmarks() { - return this.http.get('/api/v1/benchmark'); + return this.http.get('/api/v1/benchmarks'); + } + + public fetchDataProviderHealth(dataSource: DataSource) { + return this.http.get( + `/api/v1/health/data-provider/${dataSource}` + ); } public fetchExport({ @@ -383,13 +415,13 @@ export class DataService { symbol: string; }) { return this.http - .get( - `/api/v1/portfolio/position/${dataSource}/${symbol}` + .get( + `/api/v1/portfolio/holding/${dataSource}/${symbol}` ) .pipe( map((data) => { - if (data.orders) { - for (const order of data.orders) { + if (data.activities) { + for (const order of data.activities) { order.createdAt = parseISO(order.createdAt as unknown as string); order.date = parseISO(order.date as unknown as string); } @@ -452,6 +484,34 @@ export class DataService { ); } + public fetchMarketDataOfMarkets({ + includeHistoricalData + }: { + includeHistoricalData?: number; + }): Observable { + let params = new HttpParams(); + + if (includeHistoricalData) { + params = params.append('includeHistoricalData', includeHistoricalData); + } + + return this.http.get('/api/v1/market-data/markets', { params }).pipe( + map((data) => { + for (const item of data.fearAndGreedIndex.CRYPTOCURRENCIES + ?.historicalData ?? []) { + item.date = parseISO(item.date); + } + + for (const item of data.fearAndGreedIndex.STOCKS?.historicalData ?? + []) { + item.date = parseISO(item.date); + } + + return data; + }) + ); + } + public fetchSymbolItem({ dataSource, includeHistoricalData, @@ -513,12 +573,6 @@ export class DataService { }) .pipe( map((response) => { - if (response.summary?.firstOrderDate) { - response.summary.firstOrderDate = parseISO( - response.summary.firstOrderDate - ); - } - if (response.holdings) { for (const symbol of Object.keys(response.holdings)) { response.holdings[symbol].assetClassLabel = translate( @@ -637,6 +691,20 @@ export class DataService { return this.http.get('/api/v1/portfolio/report'); } + public fetchPrompt({ + filters, + mode + }: { + filters?: Filter[]; + mode: AiPromptMode; + }) { + const params = this.buildFiltersAsQueryParams({ filters }); + + return this.http.get(`/api/v1/ai/prompt/${mode}`, { + params + }); + } + public fetchPublicPortfolio(aAccessId: string) { return this.http .get(`/api/v1/public/${aAccessId}/portfolio`) @@ -657,6 +725,14 @@ export class DataService { ); } + public fetchTags() { + return this.http.get('/api/v1/tags'); + } + + public fetchWatchlist() { + return this.http.get('/api/v1/watchlist'); + } + public loginAnonymous(accessToken: string) { return this.http.post('/api/v1/auth/anonymous', { accessToken @@ -683,7 +759,7 @@ export class DataService { } public postBenchmark(benchmark: AssetProfileIdentifier) { - return this.http.post('/api/v1/benchmark', benchmark); + return this.http.post('/api/v1/benchmarks', benchmark); } public postMarketData({ @@ -704,10 +780,18 @@ export class DataService { return this.http.post('/api/v1/order', aOrder); } + public postTag(aTag: CreateTagDto) { + return this.http.post(`/api/v1/tags`, aTag); + } + public postUser() { return this.http.post('/api/v1/user', {}); } + public postWatchlistItem(watchlistItem: CreateWatchlistItemDto) { + return this.http.post('/api/v1/watchlist', watchlistItem); + } + public putAccount(aAccount: UpdateAccountDto) { return this.http.put(`/api/v1/account/${aAccount.id}`, aAccount); } @@ -722,7 +806,7 @@ export class DataService { tags }: { tags: Tag[] } & AssetProfileIdentifier) { return this.http.put( - `/api/v1/portfolio/position/${dataSource}/${symbol}/tags`, + `/api/v1/portfolio/holding/${dataSource}/${symbol}/tags`, { tags } ); } @@ -731,6 +815,10 @@ export class DataService { return this.http.put(`/api/v1/order/${aOrder.id}`, aOrder); } + public putTag(aTag: UpdateTagDto) { + return this.http.put(`/api/v1/tags/${aTag.id}`, aTag); + } + public putUserSetting(aData: UpdateUserSettingDto) { return this.http.put('/api/v1/user/setting', aData); } @@ -753,6 +841,20 @@ export class DataService { }); } + public updateOwnAccessToken(aAccessToken: UpdateOwnAccessTokenDto) { + return this.http.post( + '/api/v1/user/access-token', + aAccessToken + ); + } + + public updateUserAccessToken(aUserId: string) { + return this.http.post( + `/api/v1/user/${aUserId}/access-token`, + {} + ); + } + public updateInfo() { this.http.get('/api/v1/info').subscribe((info) => { const utmSource = window.localStorage.getItem('utm_source') as diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index c1b2209b3..033ae7e24 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -1,4 +1,5 @@ -import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; +import { CreateAccountWithBalancesDto } from '@ghostfolio/api/app/import/create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from '@ghostfolio/api/app/import/create-asset-profile-with-market-data.dto'; import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { parseDate as parseDateHelper } from '@ghostfolio/common/helper'; @@ -73,20 +74,22 @@ export class ImportActivitiesService { public importJson({ accounts, activities, + assetProfiles, isDryRun = false }: { activities: CreateOrderDto[]; - accounts?: CreateAccountDto[]; + accounts?: CreateAccountWithBalancesDto[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; isDryRun?: boolean; }): Promise<{ activities: Activity[]; - accounts?: CreateAccountDto[]; }> { return new Promise((resolve, reject) => { this.postImport( { accounts, - activities + activities, + assetProfiles }, isDryRun ) @@ -106,13 +109,14 @@ export class ImportActivitiesService { public importSelectedActivities({ accounts, - activities + activities, + assetProfiles }: { - accounts: CreateAccountDto[]; + accounts?: CreateAccountWithBalancesDto[]; activities: Activity[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; }): Promise<{ activities: Activity[]; - accounts?: CreateAccountDto[]; }> { const importData: CreateOrderDto[] = []; @@ -120,12 +124,13 @@ export class ImportActivitiesService { importData.push(this.convertToCreateOrderDto(activity)); } - return this.importJson({ accounts, activities: importData }); + return this.importJson({ accounts, assetProfiles, activities: importData }); } private convertToCreateOrderDto({ accountId, comment, + currency, date, fee, quantity, @@ -142,7 +147,7 @@ export class ImportActivitiesService { type, unitPrice, updateAccountBalance, - currency: SymbolProfile.currency, + currency: currency ?? SymbolProfile.currency, dataSource: SymbolProfile.dataSource, date: date.toString(), symbol: SymbolProfile.symbol @@ -342,8 +347,6 @@ export class ImportActivitiesService { return 'FEE'; case 'interest': return 'INTEREST'; - case 'item': - return 'ITEM'; case 'liability': return 'LIABILITY'; case 'sell': @@ -384,7 +387,11 @@ export class ImportActivitiesService { } private postImport( - aImportData: { accounts: CreateAccountDto[]; activities: CreateOrderDto[] }, + aImportData: { + accounts?: CreateAccountWithBalancesDto[]; + activities: CreateOrderDto[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; + }, aIsDryRun = false ) { return this.http.post<{ activities: Activity[] }>( diff --git a/apps/client/src/app/services/user/user.service.ts b/apps/client/src/app/services/user/user.service.ts index aa91a90bd..86b2656d7 100644 --- a/apps/client/src/app/services/user/user.service.ts +++ b/apps/client/src/app/services/user/user.service.ts @@ -1,5 +1,3 @@ -import { SubscriptionInterstitialDialogParams } from '@ghostfolio/client/components/subscription-interstitial-dialog/interfaces/interfaces'; -import { SubscriptionInterstitialDialog } from '@ghostfolio/client/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component'; import { Filter, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; @@ -13,6 +11,8 @@ import { Observable, Subject, of } from 'rxjs'; import { throwError } from 'rxjs'; import { catchError, map, takeUntil } from 'rxjs/operators'; +import { SubscriptionInterstitialDialogParams } from '../../components/subscription-interstitial-dialog/interfaces/interfaces'; +import { SubscriptionInterstitialDialog } from '../../components/subscription-interstitial-dialog/subscription-interstitial-dialog.component'; import { UserStoreActions } from './user-store.actions'; import { UserStoreState } from './user-store.state'; @@ -121,6 +121,7 @@ export class UserService extends ObservableStore { data: { user } as SubscriptionInterstitialDialogParams, + disableClose: true, height: this.deviceType === 'mobile' ? '98vh' : '80vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); diff --git a/apps/client/src/app/services/web-authn.service.ts b/apps/client/src/app/services/web-authn.service.ts index c5e186362..3885b2f94 100644 --- a/apps/client/src/app/services/web-authn.service.ts +++ b/apps/client/src/app/services/web-authn.service.ts @@ -45,7 +45,7 @@ export class WebAuthnService { return of(null); }), switchMap((attOps) => { - return startRegistration(attOps); + return startRegistration({ optionsJSON: attOps }); }), switchMap((credential) => { return this.http.post( @@ -85,16 +85,16 @@ export class WebAuthnService { return this.http .post( - `/api/v1/auth/webauthn/generate-assertion-options`, + '/api/v1/auth/webauthn/generate-authentication-options', { deviceId } ) .pipe( - switchMap((requestOptionsJSON) => { - return startAuthentication(requestOptionsJSON); + switchMap((optionsJSON) => { + return startAuthentication({ optionsJSON }); }), switchMap((credential) => { return this.http.post<{ authToken: string }>( - `/api/v1/auth/webauthn/verify-assertion`, + '/api/v1/auth/webauthn/verify-authentication', { credential, deviceId diff --git a/apps/client/src/assets/oss-friends.json b/apps/client/src/assets/oss-friends.json index c3a127933..33e80b558 100644 --- a/apps/client/src/assets/oss-friends.json +++ b/apps/client/src/assets/oss-friends.json @@ -1,6 +1,11 @@ { - "createdAt": "2024-11-27T00:00:00.000Z", + "createdAt": "2025-07-28T00:00:00.000Z", "data": [ + { + "name": "Activepieces", + "description": "Activepieces is an open source, no-code, AI-first business automation tool. Alternative to Zapier, Make and Workato.", + "href": "https://activepieces.com" + }, { "name": "Aptabase", "description": "Analytics for Apps, open source, simple and privacy-friendly. SDKs for Swift, React Native, Electron, Flutter and many others.", @@ -11,11 +16,6 @@ "description": "Argos provides the developer tools to debug tests and detect visual regressions.", "href": "https://argos-ci.com" }, - { - "name": "BoxyHQ", - "description": "BoxyHQ’s suite of APIs for security and privacy helps engineering teams build and ship compliant cloud applications faster.", - "href": "https://boxyhq.com" - }, { "name": "Cal.com", "description": "Cal.com is a scheduling tool that helps you schedule meetings without the back-and-forth emails.", @@ -26,41 +26,16 @@ "description": "ClassroomIO is a no-code tool that allows you build and scale your own teaching platform with ease.", "href": "https://www.classroomio.com" }, - { - "name": "Crowd.dev", - "description": "Centralize community, product, and customer data to understand which companies are engaging with your open source project.", - "href": "https://www.crowd.dev" - }, - { - "name": "DevHunt", - "description": "Find the best Dev Tools upvoted by the community every week.", - "href": "https://devhunt.org" - }, { "name": "Documenso", "description": "The Open-Source DocuSign Alternative. We aim to earn your trust by enabling you to self-host the platform and examine its inner workings.", "href": "https://documenso.com" }, - { - "name": "dyrector.io", - "description": "dyrector.io is an open-source continuous delivery & deployment platform with version management.", - "href": "https://dyrector.io" - }, - { - "name": "Firecamp", - "description": "vscode for apis, open-source postman/insomnia alternative", - "href": "https://firecamp.io" - }, { "name": "Formbricks", "description": "Open source survey software and Experience Management Platform. Understand your customers, keep full control over your data.", "href": "https://formbricks.com" }, - { - "name": "GitWonk", - "description": "GitWonk is an open-source technical documentation tool, designed and built focusing on the developer experience.", - "href": "https://gitwonk.com" - }, { "name": "Hanko", "description": "Open-source authentication and user management for the passkey era. Integrated in minutes, for web and mobile apps.", @@ -91,11 +66,6 @@ "description": "Open source LLM engineering platform. Debug, analyze and iterate together.", "href": "https://langfuse.com" }, - { - "name": "Lost Pixel", - "description": "Open source visual regression testing alternative to Percy & Chromatic", - "href": "https://lost-pixel.com" - }, { "name": "Mockoon", "description": "Mockoon is the easiest and quickest way to design and run mock REST APIs.", @@ -111,6 +81,11 @@ "description": "Open-source monitoring platform with beautiful status pages", "href": "https://www.openstatus.dev" }, + { + "name": "Papermark", + "description": "Open-Source Docsend Alternative to securely share documents with real-time analytics.", + "href": "https://www.papermark.com" + }, { "name": "Portkey AI", "description": "AI Gateway with integrated Guardrails. Route to 250+ LLMs and 50+ Guardrails with 1-fast API. Supports caching, retries, and edge deployment for low latency.", @@ -141,11 +116,6 @@ "description": "Sniffnet is a network monitoring tool to help you easily keep track of your Internet traffic.", "href": "https://www.sniffnet.net" }, - { - "name": "Spark.NET", - "description": "The .NET Web Framework for Makers. Build production ready, full-stack web applications fast without sweating the small stuff.", - "href": "https://spark-framework.net" - }, { "name": "Tiledesk", "description": "The innovative open-source framework for developing LLM-enabled chatbots, Tiledesk empowers developers to create advanced, conversational AI agents.", @@ -171,16 +141,16 @@ "description": "Typebot gives you powerful blocks to create unique chat experiences. Embed them anywhere on your apps and start collecting results like magic.", "href": "https://typebot.io" }, - { - "name": "UnInbox", - "description": "Modern email for teams and professionals. Bringing the best of email and messaging into a single, modern, and secure platform.", - "href": "https://uninbox.com" - }, { "name": "Unkey", "description": "An API authentication and authorization platform for scaling user facing APIs. Create, verify, and manage low latency API keys in seconds.", "href": "https://unkey.dev" }, + { + "name": "Voltagent", + "description": "Open Source TypeScript framework for building AI agents with enterprise-grade capabilities and seamless integrations.", + "href": "https://voltagent.dev" + }, { "name": "Webiny", "description": "Open-source enterprise-grade serverless CMS. Own your data. Scale effortlessly. Customize everything.", diff --git a/apps/client/src/assets/privacy-policy.md b/apps/client/src/assets/privacy-policy.md index 6170c4757..6eea207c3 100644 --- a/apps/client/src/assets/privacy-policy.md +++ b/apps/client/src/assets/privacy-policy.md @@ -1,5 +1,3 @@ -Last updated: June 18, 2022 - This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You. We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. @@ -16,7 +14,7 @@ For the purposes of this Privacy Policy: - **Account** means a unique account created for You to access our Service or parts of our Service. - **Application** means the software program provided by the Company downloaded by You on any electronic device, named Ghostfolio App. -- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Ghostfolio. +- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Ghostfolio LLC. - **Country** refers to: Switzerland - **Device** means any device that can access the Service such as a computer, a cellphone or a digital tablet. - **Personal Data** is any information that relates to an identified or identifiable individual. @@ -78,3 +76,5 @@ You are advised to review this Privacy Policy periodically for any changes. Chan ## Contact Us If you have any questions about this Privacy Policy, You can contact us [here](https://ghostfol.io/en/about). + +Date of Last Revision: March 29, 2025 diff --git a/apps/client/src/assets/terms-of-service.md b/apps/client/src/assets/terms-of-service.md new file mode 100644 index 000000000..d2a6e598d --- /dev/null +++ b/apps/client/src/assets/terms-of-service.md @@ -0,0 +1,58 @@ +This Terms of Service Agreement (hereinafter referred to as the "Agreement") is a legally binding contract between you (hereinafter referred to as the "User" or "You") and Ghostfolio LLC (hereinafter referred to as "LICENSEE") governing your use of the web application and the application programming interface (API) (hereinafter referred to as the "Service") provided by LICENSEE. By either accessing or using the Service, or by downloading data provided by the Service, you agree to be bound by the terms and conditions of this Agreement. If you do not agree to these terms, please do not access or use the Service. + +## Definitions + +
        +
      1. "Service" refers to the services provided by LICENSEE, including, but not limited to, the web application, the application programming interface (API), and the provision of financial market data.
      2. +
      3. "User" refers to any individual or entity that either accesses or uses the Service, or downloads data provided by the Service.
      4. +
      5. "LICENSEE" refers to Ghostfolio LLC, the provider of the Service.
      6. +
      + +## License Grant + +LICENSEE grants the User a non-exclusive, non-transferable, revocable license to access and use the Service, and download data provided by the Service, solely for lawful and non-commercial purposes in accordance with the terms and conditions of this Agreement. + +## Use Restrictions + +The User agrees to the following use restrictions: + +
        +
      1. The Service provided by LICENSEE is for informational and educational purposes only and shall not be used for any commercial purposes.
      2. +
      3. The User shall not distribute, sell, rent, lease, sublicense, or otherwise transfer the data provided by the Service to any third party.
      4. +
      5. The User shall not modify, adapt, reverse engineer, decompile, disassemble, or create derivative works based on the Service.
      6. +
      7. The User shall not use the Service in any manner that violates applicable laws or regulations.
      8. +
      + +## Ownership + +The Service, and all data provided by the Service, is the property of LICENSEE and is protected by intellectual property laws. The User acknowledges that LICENSEE retains all rights, title, and interest in and to the Service. + +## Disclaimer of Warranty + +LICENSEE provides the Service and data provided by the Service "as is" and makes no representations or warranties regarding the accuracy, completeness, or reliability of the Service. The User uses the Service at their own risk. + +## Limitation of Liability + +LICENSEE shall not be liable for any direct, indirect, incidental, special, or consequential damages arising out of or in connection with the use or inability to use the Service or the data provided by the Service. + +## Termination + +This Agreement is effective until terminated by either party. The User may terminate this Agreement by ceasing to use the Service. LICENSEE may terminate this Agreement at any time without notice if the User breaches any of its terms. Upon termination, the User must cease all use of the Service and data provided by the Service. + +## Governing Law + +This Agreement shall be governed by and construed in accordance with the laws of Zurich, Switzerland, without regard to its conflict of law principles. + +## Entire Agreement + +This Agreement constitutes the entire agreement between the User and LICENSEE regarding the Service and supersedes all prior agreements and understandings, whether oral or written. + +## Changes to Agreement + +LICENSEE reserves the right to modify this Agreement at any time. Users are encouraged to review this Agreement periodically for updates. Continued use of the Service after changes to this Agreement constitutes acceptance of the modified terms. + +By accessing or using the Service, or downloading data provided by the Service, the User acknowledges that they have read, understood, and agreed to be bound by this Terms of Service Agreement. + +For any questions or concerns regarding this Agreement, please contact us [here](https://ghostfol.io/en/about). + +Date of Last Revision: March 29, 2025 diff --git a/apps/client/src/index.html b/apps/client/src/index.html index 47f2c3d1a..8b1dc2f92 100644 --- a/apps/client/src/index.html +++ b/apps/client/src/index.html @@ -45,14 +45,14 @@ sizes="16x16" type="image/png" /> - + - - - diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 357e27442..e6a23e41d 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -5,31 +5,55 @@ Features Característiques - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Internationalization Internacionalització - apps/client/src/app/app-routing.module.ts - 88 + libs/common/src/lib/routes/routes.ts + 119 Sign in Iniciar sessió - apps/client/src/app/app-routing.module.ts - 150 + apps/client/src/app/components/header/header.component.html + 422 apps/client/src/app/components/header/header.component.ts - 230 + 259 + + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 + + + libs/common/src/lib/routes/routes.ts + 81 + + + libs/common/src/lib/routes/routes.ts + 157 - + You are using the Live Demo. Esteu utilitzant una demo. @@ -37,7 +61,7 @@ 12 - + Create Account Crea un Compte @@ -52,4623 +76,5253 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 - - - Personal Finance - Finances Personals - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 - - Markets - Mercats + + Frequently Asked Questions (FAQ) + Preguntes Freqüents (FAQ) - apps/client/src/app/app.component.html - 61 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + El risc d’assumir pèrdues en les inversions és substancial. No és recomanable invertir diners que pugui necessitar a curt termini. - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/app.component.html + 221 - - Resources - Recursos + + about + sobre + kebab-case - apps/client/src/app/app.component.html - 64 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/components/header/header.component.html - 82 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/components/header/header.component.html - 291 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + libs/common/src/lib/routes/routes.ts + 190 - - - About - Sobre - apps/client/src/app/app.component.html - 70 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/components/header/header.component.html - 117 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/components/header/header.component.html - 364 + libs/common/src/lib/routes/routes.ts + 214 - - Blog - Blog + + license + llicencies + kebab-case - apps/client/src/app/app.component.html - 73 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + libs/common/src/lib/routes/routes.ts + 191 + + + privacy-policy + politica-de-privacitat + kebab-case - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + libs/common/src/lib/routes/routes.ts + 207 + + + faq + faq + kebab-case - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + libs/common/src/lib/routes/routes.ts + 245 + + + features + caracteristiques + kebab-case - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + libs/common/src/lib/routes/routes.ts + 255 + + + markets + mercats + kebab-case - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + libs/common/src/lib/routes/routes.ts + 260 + + + pricing + preu + kebab-case - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + libs/common/src/lib/routes/routes.ts + 270 + + + register + registrar-se + kebab-case - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + recursos + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/blog/blog-page.html - 5 + libs/common/src/lib/routes/routes.ts + 322 - - Changelog - Registre de canvis + + Alias + Àlies - apps/client/src/app/app.component.html - 77 + apps/client/src/app/components/access-table/access-table.component.html + 4 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 - - Features - Característiques + + Grantee + Beneficiari - apps/client/src/app/app.component.html - 79 + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + Permission + Permisos - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/access-table/access-table.component.html + 18 - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 - - Frequently Asked Questions (FAQ) - Preguntes Freqüents (FAQ) + + View + Vista - apps/client/src/app/app.component.html - 83 + apps/client/src/app/components/access-table/access-table.component.html + 23 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - License - Llicències + + Restricted view + Vista restringida - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/access-table/access-table.component.html + 26 - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Pricing - Preu + + Details + Detalls - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/access-table/access-table.component.html + 33 + + + Revoke + Revocar - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + Do you really want to revoke this granted access? + Realment vol revocar aquest accés? - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/access-table/access-table.component.ts + 108 + + + Cash Balance + Balanç de Caixa - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 - - - - Privacy Policy - Política de privacitat - - apps/client/src/app/app.component.html - 103 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 - - Community - Comunitat + + Platform + Plataforma - apps/client/src/app/app.component.html - 121 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 + + + Holdings + En cartera - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 + libs/ui/src/lib/assistant/assistant.html + 82 + + + Cash Balances + Balanç de Caixa - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + Transfer Cash Balance + Transferir Efectiu - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Name + Nom - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 89 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 - apps/client/src/app/pages/features/features-page.html - 259 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 - - - The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. - El risc d’assumir pèrdues en les inversions és substancial. No és recomanable invertir diners que pugui necessitar a curt termini. - apps/client/src/app/app.component.html - 200 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 - - - about - sobre - snake-case - apps/client/src/app/app.component.ts - 64 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 - apps/client/src/app/app.component.ts - 66 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 - apps/client/src/app/app.component.ts - 70 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 - apps/client/src/app/app.component.ts - 74 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 - apps/client/src/app/components/header/header.component.ts - 81 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 - apps/client/src/app/components/header/header.component.ts - 86 + libs/ui/src/lib/activities-table/activities-table.component.html + 138 - apps/client/src/app/core/paths.ts - 2 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 16 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + Total + Total - apps/client/src/app/pages/about/about-page.component.ts + apps/client/src/app/components/accounts-table/accounts-table.component.html 55 + + + Currency + Divisa - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + Value + Valor - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 - - - license - llicències - snake-case - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/ui/src/lib/account-balances/account-balances.component.html + 34 - - - privacy-policy - política de privacitat - snake-case - apps/client/src/app/app.component.ts - 75 + libs/ui/src/lib/activities-table/activities-table.component.html + 257 - apps/client/src/app/core/paths.ts - 8 + libs/ui/src/lib/activities-table/activities-table.component.html + 293 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 - - - faq - faq - snake-case - apps/client/src/app/app.component.ts - 77 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 - apps/client/src/app/core/paths.ts - 3 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 + + + Edit + Editar - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 430 - - features - característiques - snake-case + + Delete + Suprimir - apps/client/src/app/app.component.ts - 78 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 - apps/client/src/app/components/header/header.component.ts - 82 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 - apps/client/src/app/components/header/header.component.ts - 87 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/components/admin-overview/admin-overview.html + 131 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/ui/src/lib/account-balances/account-balances.component.html + 80 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/ui/src/lib/activities-table/activities-table.component.html + 457 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + + + Do you really want to delete this account? + Realment vol suprimir aquest compte? - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 + + + Type + Tipus - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 15 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 161 + + + Asset Profile + Perfil d’Actiu - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 - - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 - - markets - mercats - snake-case + + Historical Market Data + Dades Històriques de Mercat - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + + + Data Source + Origen de les Dades - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 + + + Priority + Prioritat - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + Attempts + Intents - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 + + + Created + Creat - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 - - pricing - preu - snake-case + + Finished + Finalitzat - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 + + + Status + Estat - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + + + Delete Jobs + Aturar Processos - apps/client/src/app/components/header/header.component.ts - 89 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + View Data + Veure les Dades - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + View Stacktrace + Veure Stacktrace - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + Execute Job + Executar Procés - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + Delete Job + Suprimir Procés - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + Details for + Detalls de - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + Date + Data - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + libs/ui/src/lib/account-balances/account-balances.component.html + 12 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 170 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + Market Price + Preu de Mercat - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + Benchmarks + Punts de referència - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + Currencies + Divises - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 - - - register - registrar-se - snake-case - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/pages/public/public-page.html + 88 + + + ETFs without Countries + ETFs sense País - apps/client/src/app/components/header/header.component.ts - 90 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + ETFs without Sectors + ETFs sense Sector - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + Filter by... + Filtra per... - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + Primera Activitat - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 - - resources - recursos - snake-case + + Activities Count + Nombre d’Activitats - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + Historical Data + Dades Històriques - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/components/header/header.component.ts - 91 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 + + + Sectors Count + Nombre de Sectors - apps/client/src/app/core/paths.ts - 10 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + Countries Count + Nombre de Països - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 + + + Gather Profile Data + Recopilar Dades del Perfil - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 + + + Delete Profiles + Eliminar Perfils - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + Do you really want to delete this asset profile? + Realment vol eliminar el perfil d’aquest actiu? - apps/client/src/app/pages/features/features-page.component.ts - 30 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Do you really want to delete these profiles? + Realment vol eliminar aquests perfils? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + Oops! Could not delete profiles. + Oooh! No s’han pogut eliminar els perfils - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 - - - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + Oops! Could not parse historical data. + Oooh! No s’han pogut recopilar les dades históriques. - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + The current market price is + El preu de mercat actual és - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 + + + Refresh + Refrescar - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 - - Alias - Àlies + + Import + Importar - apps/client/src/app/components/access-table/access-table.component.html - 4 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 11 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 - - - Grantee - Grantee - apps/client/src/app/components/access-table/access-table.component.html - 11 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 - - Permission - Permisos + + Sector + Sector - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 - - View - Vista + + Country + País - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-users/admin-users.html + 78 - - - Restricted view - Vista restringida - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 + + + Sectors + Sectors - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 - - - Details - Detalls - apps/client/src/app/components/access-table/access-table.component.html - 33 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 - - - Revoke - Revocar - apps/client/src/app/components/access-table/access-table.component.html - 75 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 - - - Do you really want to revoke this granted access? - Realment vol revocar aquest accés? - apps/client/src/app/components/access-table/access-table.component.ts - 67 + apps/client/src/app/pages/public/public-page.html + 106 - - Cash Balance - Balanç de Caixa + + Countries + Països - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 47 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 136 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 34 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 - - Equity - Patrimoni + + Symbol Mapping + Mapatge de Símbols - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 - - Activities - Activitats + + Scraper Configuration + Configuració del Proveïdor de Dades - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 + + + Test + Prova - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 + + + Url + Url - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 + 515 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 38 - apps/client/src/app/components/admin-users/admin-users.html - 135 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 25 + + + Note + Notes - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 - - Platform - Plataforma + + Add Asset Profile + Afegeix el Perfil de l’Actiu - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 67 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 + + + Search + Cerca - apps/client/src/app/components/accounts-table/accounts-table.component.html - 86 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 + + + Add Manually + Afegir manualment - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 48 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 - - Holdings - En cartera + + Name, symbol or ISIN + Nom, símbol o ISIN - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 - apps/client/src/app/components/home-holdings/home-holdings.html - 4 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 - apps/client/src/app/pages/public/public-page.html - 70 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 - libs/ui/src/lib/assistant/assistant.html - 46 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 - - Cash Balances - Balanç de Caixa + + Do you really want to delete this coupon? + Està segur qeu vol eliminar aquest cupó? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 - - Transfer Cash Balance - Transferir Efectiu + + Do you really want to delete this system message? + Està segur que vol eliminar aquest missatge del sistema? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + Do you really want to flush the cache? + Està segur que vol depurar el cache? - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 - - Name - Nom + + Please set your system message: + Si us plau, afegeixi el seu missatge del sistema: - apps/client/src/app/components/accounts-table/accounts-table.component.html - 43 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 + + + Version + Versió - apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + User Count + Número d’Usuaris - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + apps/client/src/app/components/admin-overview/admin-overview.html + 13 + + + Activity Count + Número d’Activitats - apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 - + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + + per User + per Usuari + + apps/client/src/app/components/admin-overview/admin-overview.html + 28 + + + + Add Currency + Afegir Divisa + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 + + + + User Signup + Registrar Usuari + + apps/client/src/app/components/admin-overview/admin-overview.html + 34 + + + + Read-only Mode + Mode Només Lecutra + + apps/client/src/app/components/admin-overview/admin-overview.html + 48 + + + + Data Gathering + Recollida de Dades + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + System Message + Missatge del Sistema + + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + + Set Message + Estableix el Missatge + + apps/client/src/app/components/admin-overview/admin-overview.html + 94 + + + + Coupons + Coupons + + apps/client/src/app/components/admin-overview/admin-overview.html + 102 + + + + Add + Afegir + + apps/client/src/app/components/admin-overview/admin-overview.html + 176 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + + + + Housekeeping + Ordre + + apps/client/src/app/components/admin-overview/admin-overview.html + 184 + + + + Flush Cache + Depurar el Cache + + apps/client/src/app/components/admin-overview/admin-overview.html + 200 + + + + Add Platform + Afegeix Plataforma + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + + Do you really want to delete this platform? + Està segur que vol eliminar aquesta plataforma? + + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + + Update platform + Actualitzar plataforma + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + + Add platform + Afegeix una plataforma + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + + Platforms + Plataformes + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + + Tags + Etiquetes + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 + + + + Add Tag + Afegir Etiqueta + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + + Do you really want to delete this tag? + Està segur que vol eliminar aquesta etiqueta? + + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + + Update tag + Actualitzar etiqueta + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + + Add tag + Afegir etiqueta + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + + Do you really want to delete this user? + Està segur que vol eliminar aquest usuari? + + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + + User + Usuari + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 31 + + + apps/client/src/app/components/header/header.component.html + 231 + + + + Engagement per Day + Implicació per Dia + + apps/client/src/app/components/admin-users/admin-users.html + 158 + + + + Last Request + Última Solicitut + + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + + Impersonate User + Actuar com un altre Usuari + + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + + Delete User + Eliminar Usuari + + apps/client/src/app/components/admin-users/admin-users.html + 261 + + + + Compare with... + Comparar amb... + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + + Manage Benchmarks + Gestionar els Punts de Referència + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 + + + + Portfolio + Portfolio + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 + + + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 + + + libs/common/src/lib/routes/routes.ts + 151 + + + + Benchmark + Punt de Referència + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + + Current Market Mood + Sentiment del Mercat + + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 + + + + Upgrade Plan + Millora la teva Subscripció + + apps/client/src/app/components/header/header.component.html + 193 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 70 + + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 + + + apps/client/src/app/pages/pricing/pricing-page.html + 299 + + + + Renew Plan + Renova la teva Subscripció + + apps/client/src/app/components/header/header.component.html + 191 + + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 18 + + + apps/client/src/app/pages/pricing/pricing-page.html + 297 + + + + User + Usuari + + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + + About Ghostfolio + Sobre Ghostfolio - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 15 + apps/client/src/app/components/header/header.component.html + 326 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 + + + Get started + Primers Passos - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 15 + apps/client/src/app/components/header/header.component.html + 432 + + + Oops! Incorrect Security Token. + Oooh! El testimoni de seguretat és incorrecte. - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 15 + apps/client/src/app/components/header/header.component.ts + 274 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 + + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 + + + + Minimum Price + Preu Mínim + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 + + + + Maximum Price + Preu Màxim + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + + Quantity + Quantitat + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 189 libs/ui/src/lib/activities-table/activities-table.component.html - 138 + 186 + + + Dividend Yield + Rendiment del Dividend - libs/ui/src/lib/holdings-table/holdings-table.component.html - 28 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + Fees + Comissions - libs/ui/src/lib/top-holdings/top-holdings.component.html - 16 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 88 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 - - Total - Total + + Indonesia + Indonesia - apps/client/src/app/components/accounts-table/accounts-table.component.html - 55 + libs/ui/src/lib/i18n.ts + 87 - - Currency - Divisa + + Activity + Activitat - apps/client/src/app/components/accounts-table/accounts-table.component.html + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Report Data Glitch + Informar d’un Problema amb les Dades + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 446 + + + + Active + en Actiiu + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Finalitzat + + apps/client/src/app/components/home-holdings/home-holdings.component.ts 65 + + + Table + Taula - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + Chart + Gràfic - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + Manage Activities + Gestionar Activitats - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 46 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Fear + Por - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 25 + apps/client/src/app/components/home-market/home-market.component.ts + 42 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + apps/client/src/app/components/markets/markets.component.ts + 47 - libs/ui/src/lib/activities-table/activities-table.component.html - 276 + libs/ui/src/lib/i18n.ts + 105 - - Value - Valor + + Greed + Cobdícia - apps/client/src/app/components/accounts-table/accounts-table.component.html - 171 + apps/client/src/app/components/home-market/home-market.component.ts + 43 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 206 + apps/client/src/app/components/markets/markets.component.ts + 48 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 53 + libs/ui/src/lib/i18n.ts + 106 + + + Last Days + Últims Dies - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 + apps/client/src/app/components/markets/markets.html + 17 + + + Welcome to Ghostfolio + Benvingut a Ghostfolio - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 + apps/client/src/app/components/home-overview/home-overview.html + 11 + + + Ready to take control of your personal finances? + Estàs preparat per controlar les teves finances personals? - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 + apps/client/src/app/components/home-overview/home-overview.html + 12 + + + Setup your accounts + Configura els teus comptes - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + apps/client/src/app/components/home-overview/home-overview.html + 19 + + + Get a comprehensive financial overview by adding your bank and brokerage accounts. + Obtingueu una visió financera completa afegint els vostres comptes bancaris i de corredoria. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + apps/client/src/app/components/home-overview/home-overview.html + 21 + + + Capture your activities + Captura les teves activitats - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + apps/client/src/app/components/home-overview/home-overview.html + 28 + + + Record your investment activities to keep your portfolio up to date. + Registra les teves activitats d’inversió per mantenir la teva cartera actualitzada. - libs/ui/src/lib/account-balances/account-balances.component.html - 34 + apps/client/src/app/components/home-overview/home-overview.html + 30 + + + Monitor and analyze your portfolio + Superviseu i analitzeu la vostra cartera - libs/ui/src/lib/activities-table/activities-table.component.html - 257 + apps/client/src/app/components/home-overview/home-overview.html + 37 + + + Track your progress in real-time with comprehensive analysis and insights. + Segueix el teu progrés en temps real amb anàlisis i informació exhaustiva. - libs/ui/src/lib/activities-table/activities-table.component.html - 293 + apps/client/src/app/components/home-overview/home-overview.html + 39 + + + Setup accounts + Configurar comptes - libs/ui/src/lib/holdings-table/holdings-table.component.html - 74 + apps/client/src/app/components/home-overview/home-overview.html + 52 + + + Add activity + Afegeix activitat - libs/ui/src/lib/top-holdings/top-holdings.component.html - 25 + apps/client/src/app/components/home-overview/home-overview.html + 60 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 102 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 8 - - Edit - Editar + + Total Amount + Import total - apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 + + + Savings Rate + Taxa d’estalvi - apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 + + + Security Token + Fitxa de seguretat - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - libs/ui/src/lib/activities-table/activities-table.component.html - 430 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - - - Delete - Suprimir - apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 + + + or + o - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/admin-overview/admin-overview.html - 206 + apps/client/src/app/pages/landing/landing-page.html + 48 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + apps/client/src/app/pages/landing/landing-page.html + 451 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - libs/ui/src/lib/account-balances/account-balances.component.html - 80 + apps/client/src/app/pages/register/register-page.html + 31 - libs/ui/src/lib/activities-table/activities-table.component.html - 457 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Do you really want to delete this account? - Realment vol suprimir aquest compte? + + Sign in with Internet Identity + Inicieu la sessió amb la identitat d’Internet - apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 - - Type - Tipus + + Sign in with Google + Inicieu la sessió amb Google - apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 + + + Stay signed in + Manteniu la sessió iniciada - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 22 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 + + + Oops! A data provider is experiencing the hiccups. + Ups! Un proveïdor de dades està tenint problemes. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 15 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + Market data is delayed for + Les dades del mercat s’han retardat - libs/ui/src/lib/activities-table/activities-table.component.html - 161 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 - - Asset Profile - Perfil d’Actiu + + Time in Market + Temps al mercat - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 - - Historical Market Data - Dades Històriques de Mercat + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activitat} other {activitats}} - apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 - - Symbol - Símbol + + Absolute Gross Performance + Rendiment brut absolut - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Absolute Net Performance + Rendiment net absolut - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 + + + Net Performance + Rendiment net - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 + + + Total Assets + Actius totals - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + Assets + Actius - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 - - Data Source - Origen de les Dades + + Buying Power + Poder adquisitiu - apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 + + + Excluded from Analysis + Exclòs de l’anàlisi - apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 + + + Liabilities + Passius - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + apps/client/src/app/pages/features/features-page.html + 102 - - Priority - Prioritat + + Net Worth + Valor net - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 - - Attempts - Intents + + Annualized Performance + Rendiment anualitzat - apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 - - Created - Creat + + Please set the amount of your emergency fund. + Definiu l’import del vostre fons d’emergència. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 - - Finished - Finalitzat + + Are you an ambitious investor who needs the full picture? + Ets un inversor ambiciós que necessita la imatge completa? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 - - Status - Estat + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + Actualitza a Ghostfolio Premium avui mateix i obtén accés a funcions exclusives per millorar la teva experiència d’inversió: - apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 - - Delete Jobs - Aturar Processos + + Portfolio Summary + Resum de la cartera - apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 - - - View Data - Veure les Dades - apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + apps/client/src/app/pages/pricing/pricing-page.html + 44 - - - View Stacktrace - View Stacktrace - apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + apps/client/src/app/pages/pricing/pricing-page.html + 205 - - Execute Job - Executar Procés + + Portfolio Allocations + Assignacions de cartera - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 - - - Delete Job - Suprimir Procés - apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + apps/client/src/app/pages/features/features-page.html + 161 - - - Details for - Detalls de - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 2 + apps/client/src/app/pages/pricing/pricing-page.html + 48 - - - Date - Data - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + apps/client/src/app/pages/pricing/pricing-page.html + 209 + + + Performance Benchmarks + Punts de referència de rendiment - libs/ui/src/lib/account-balances/account-balances.component.html - 12 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 - - libs/ui/src/lib/activities-table/activities-table.component.html - 170 + + apps/client/src/app/pages/pricing/pricing-page.html + 52 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 6 + apps/client/src/app/pages/pricing/pricing-page.html + 213 - - Market Price - Preu de Mercat + + FIRE Calculator + Calculadora de FOC - apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + apps/client/src/app/pages/pricing/pricing-page.html + 56 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 26 + apps/client/src/app/pages/pricing/pricing-page.html + 217 - - Cancel - Cancel·lar + + Professional Data Provider + Proveïdor de dades professional - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/pages/pricing/pricing-page.html + 237 + + + and more Features... + i més característiques... - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/pages/pricing/pricing-page.html + 72 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + apps/client/src/app/pages/pricing/pricing-page.html + 261 + + + Get the tools to effectively manage your finances and refine your personal investment strategy. + Aconsegueix les eines per gestionar eficaçment les teves finances i refinar la teva estratègia d’inversió personal. - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 + + + Skip + Saltar - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + Today + Avui - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/pages/public/public-page.html + 24 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + libs/ui/src/lib/assistant/assistant.component.ts + 348 - - Save - Guardar + + YTD + YTD - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + 1Y + 1 any - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + 5Y + 5 anys - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + Max + Màx - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + libs/ui/src/lib/assistant/assistant.component.ts + 401 + + + Oops! Could not grant access. + Vaja! No s’ha pogut concedir l’accés. - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + Grant access + Concedeix accés apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 + 7 + + + Private + Privat - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 + + + Public + Públic - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 25 - - Benchmarks - Punts de referència + + User ID + ID d’usuari - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 - - - Currencies - Divises - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 - - ETFs without Countries - ETFs sense País + + Granted Access + Accés concedit - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + apps/client/src/app/components/user-account-access/user-account-access.html + 57 - - ETFs without Sectors - ETFs sense Sector + + Please enter your coupon code. + Introduïu el vostre codi de cupó. - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 - - Filter by... - Filtra per... + + Could not redeem coupon code + No s’ha pogut bescanviar el codi de cupó - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 - - Asset Class - Classe d’Actiu + + Coupon code has been redeemed + El codi del cupó s’ha bescanviat - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 + + + Reload + Torna a carregar - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 + + + per year + per any - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/pages/pricing/pricing-page.html + 283 + + + Try Premium + Prova Premium - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 + + + Redeem Coupon + Bescanviar el cupó - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 - - Asset Sub Class - Subclasse d’Actiu + + Auto + Automàtic - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 + + + Do you really want to close your Ghostfolio account? + De debò vols tancar el teu compte de Ghostfolio? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + Do you really want to remove this sign in method? + De debò vols eliminar aquest mètode d’inici de sessió? - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 + + + Oops! There was an error setting up biometric authentication. + Ups! Hi ha hagut un error en configurar l’autenticació biomètrica. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 - - First Activity - Primera Activitat + + Presenter View + Vista del presentador - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 + + + Protection for sensitive information like absolute performances and quantity values + Protecció per a informació sensible com ara rendiments absoluts i valors de quantitat - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 + + + Base Currency + Moneda base - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 + + + Language + Llengua - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 - - Activities Count - Nombre d’Activitats + + If a translation is missing, kindly support us in extending it here. + Si falta alguna traducció, si us plau, ajudeu-nos a ampliar-la aquí. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Historical Data - Dades Històriques + + Locale + Localització - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 - - Sectors Count - Nombre de Sectors + + Date and number format + Format de data i número - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 - - Countries Count - Nombre de Països + + Appearance + Aparença - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 - - Gather Recent Data - Recopilar Dades Recents + + Light + Llum - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 - - Gather All Data - Recopilar Totes les Dades + + Dark + Fosc - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 - - Gather Profile Data - Recopilar Dades del Perfil + + Zen Mode + Mode Zen - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 + apps/client/src/app/pages/features/features-page.html + 246 - - Delete Profiles - Eliminar Perfils + + Distraction-free experience for turbulent times + Experiència sense distraccions per a temps turbulents - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 - - Do you really want to delete this asset profile? - Realment vol eliminar el perfil d’aquest actiu? + + Biometric Authentication + Autenticació biomètrica - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 - - Do you really want to delete these profiles? - Realment vol eliminar aquests perfils? + + Sign in with fingerprint + Inicieu la sessió amb l’empremta digital - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 - - Oops! Could not delete profiles. - Oooh! No s’han pogut eliminar els perfils + + Experimental Features + Característiques experimentals - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 - - Oops! Could not parse historical data. - Oooh! No s’han pogut recopilar les dades históriques. + + Sneak peek at upcoming functionality + Doneu un cop d’ull a les properes funcionalitats - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 - - The current market price is - El preu de mercat actual és + + Export Data + Exporta dades - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 - - Refresh - Refrescar + + Danger Zone + Zona de perill - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 - - Gather Historical Data - Recopilar Dades Històriques + + Close Account + Tanca el compte - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 - - Import - Importar - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 153 - + + This feature is currently unavailable. + Aquesta funció no està disponible actualment. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 186 + apps/client/src/app/core/http-response.interceptor.ts + 55 + + + Please try again later. + Si us plau, torna-ho a provar més tard. - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + apps/client/src/app/core/http-response.interceptor.ts + 57 - - - Sector - Sector - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + apps/client/src/app/core/http-response.interceptor.ts + 88 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 - - Country - País + + This action is not allowed. + Aquesta acció no està permesa. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + Oops! Something went wrong. + Vaja! Alguna cosa va fallar. - apps/client/src/app/components/admin-users/admin-users.html - 77 + apps/client/src/app/core/http-response.interceptor.ts + 86 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 - - Sectors - Sectors + + Okay + D’acord - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + apps/client/src/app/core/http-response.interceptor.ts + 89 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Ups! Sembla que esteu fent massa sol·licituds. Si us plau, aneu una mica més lent. - apps/client/src/app/pages/public/public-page.html + apps/client/src/app/core/http-response.interceptor.ts 106 - - Countries - Països + + About + Sobre - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + apps/client/src/app/app.component.html + 70 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + apps/client/src/app/components/header/header.component.html + 375 - - - Benchmark - Referència - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - - - Symbol Mapping - Mapatge de Símbols - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + libs/common/src/lib/routes/routes.ts + 220 - - Scraper Configuration - Configuració del Proveïdor de Dades + + Changelog + Registre de canvis - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + apps/client/src/app/app.component.html + 77 - - - Test - Prova - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 - - Url - Url + + License + llicència - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + apps/client/src/app/pages/about/license/license-page.html + 4 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 25 + libs/common/src/lib/routes/routes.ts + 193 - - Note - Notes + + Privacy Policy + Política de privadesa - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + apps/client/src/app/app.component.html + 105 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 78 + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + libs/common/src/lib/routes/routes.ts + 209 - - Add Asset Profile - Afegeix el Perfil de l’Actiu + + Our + El nostre - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 7 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 - - Search - Cerca + + Discover other exciting Open Source Software projects + Descobriu altres projectes de programari de codi obert emocionants - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 - - Add Manually - Afegir manualment + + Visit + Visita - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 - - Name, symbol or ISIN - Nom, símbol o ISIN + + Accounts + Comptes - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 29 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 + apps/client/src/app/components/admin-users/admin-users.html + 115 - - - Please add a currency: - Si us plau, afegiu una divisa: - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + apps/client/src/app/components/header/header.component.html + 58 - - - is an invalid currency! - no és una divisa vàlida! - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/header/header.component.html + 268 - - - Do you really want to delete this coupon? - Està segur qeu vol eliminar aquest cupó? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 - - - Do you really want to delete this currency? - Està segur que vol eliminar aquesta divisa? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + apps/client/src/app/pages/accounts/accounts-page.html + 4 - - - Do you really want to delete this system message? - Està segur que vol eliminar aquest missatge del sistema? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + libs/common/src/lib/routes/routes.ts + 69 - - Do you really want to flush the cache? - Està segur que vol depurar el cache? + + Oops, cash balance transfer has failed. + Vaja, la transferència del saldo en efectiu ha fallat. - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 - - Please set your system message: - Si us plau, afegeixi el seu missatge del sistema: + + Update account + Actualitza el compte - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 - - Version - Versió + + Add account + Afegeix un compte - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - - User Count - Número d’Usuaris + + Account ID + ID del compte - apps/client/src/app/components/admin-overview/admin-overview.html - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 - - Activity Count - Número d’Activitats + + From + Des de - apps/client/src/app/components/admin-overview/admin-overview.html - 19 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - per User - per Usuari + + To + A - apps/client/src/app/components/admin-overview/admin-overview.html - 28 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 - - Exchange Rates - Tipus de Canvi + + Transfer + Transferència - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Add Currency - Afegir Divisa + + Admin Control + Control d’administració - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 22 + apps/client/src/app/components/header/header.component.html + 74 - apps/client/src/app/components/admin-overview/admin-overview.html - 105 + apps/client/src/app/components/header/header.component.html + 289 - - - User Signup - Registrar Usuari - apps/client/src/app/components/admin-overview/admin-overview.html - 111 + libs/common/src/lib/routes/routes.ts + 64 - - Read-only Mode - Mode Només Lecutra + + Job Queue + Cua de treball - apps/client/src/app/components/admin-overview/admin-overview.html - 125 + libs/common/src/lib/routes/routes.ts + 46 - - Data Gathering - Recollida de Dades + + Market Data + Dades de mercat - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - - - System Message - Missatge del Sistema - apps/client/src/app/components/admin-overview/admin-overview.html - 149 + libs/common/src/lib/routes/routes.ts + 51 - - Set Message - Estableix el Missatge + + Settings + Configuració - apps/client/src/app/components/admin-overview/admin-overview.html - 171 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - - - Coupons - Coupons - apps/client/src/app/components/admin-overview/admin-overview.html - 179 + libs/common/src/lib/routes/routes.ts + 34 - - - Add - Afegir - apps/client/src/app/components/admin-overview/admin-overview.html - 239 + libs/common/src/lib/routes/routes.ts + 56 + + + Users + Usuaris - libs/ui/src/lib/account-balances/account-balances.component.html - 93 + libs/common/src/lib/routes/routes.ts + 61 - - Housekeeping - Ordre + + Overview + Visió general - apps/client/src/app/components/admin-overview/admin-overview.html - 247 + apps/client/src/app/components/header/header.component.html + 30 - - - Flush Cache - Depurar el Cache - apps/client/src/app/components/admin-overview/admin-overview.html - 251 + apps/client/src/app/components/header/header.component.html + 248 - - - Add Platform - Afegeix Plataforma - apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 - - - Accounts - Comptes - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/pages/admin/admin-page.component.ts + 48 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/pages/resources/resources-page.component.ts + 30 - apps/client/src/app/components/header/header.component.html - 54 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/components/header/header.component.html - 263 + libs/common/src/lib/routes/routes.ts + 170 + + + Blog + Bloc - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + apps/client/src/app/app.component.html + 74 - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 - - - Do you really want to delete this platform? - Està segur que vol eliminar aquesta plataforma? - apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 - - - Update platform - Actualitzar plataforma - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 8 + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 - - - Add platform - Afegeix una plataforma - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 10 + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 - - - Platforms - Plataformes - apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 - - - Tags - Etiquetes - apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 - - - Add Tag - Afegir Etiqueta - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 - - - Do you really want to delete this tag? - Està segur que vol eliminar aquesta etiqueta? - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 - - - Update tag - Actualitzar etiqueta - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 - - - Add tag - Afegir etiqueta - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 - - - Do you really want to delete this user? - Està segur que vol eliminar aquest usuari? - apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 - - - User - Usuari - apps/client/src/app/components/admin-users/admin-users.html - 29 + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 - - - Registration - Registrar-se - apps/client/src/app/components/admin-users/admin-users.html - 97 + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 - - - Engagement per Day - Implicació per Dia - apps/client/src/app/components/admin-users/admin-users.html - 157 + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 - - - Last Request - Última Solicitut - apps/client/src/app/components/admin-users/admin-users.html - 202 + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 - - - Impersonate User - Actuar com un altre Usuari - apps/client/src/app/components/admin-users/admin-users.html - 239 + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 - - - Delete User - Eliminar Usuari - apps/client/src/app/components/admin-users/admin-users.html - 251 + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 - - - Performance - Rendiment - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 + apps/client/src/app/pages/blog/blog-page.html + 5 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + libs/common/src/lib/routes/routes.ts + 225 - - Compare with... - Comparar amb... + + Discover the latest Ghostfolio updates and insights on personal finance + Descobriu les últimes actualitzacions i perspectives de Ghostfolio sobre finances personals - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 18 + apps/client/src/app/pages/blog/blog-page.html + 7 - - Manage Benchmarks - Gestionar els Punts de Referència + + As you are already logged in, you cannot access the demo account. + Com que ja has iniciat sessió, no pots accedir al compte de demostració. - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + apps/client/src/app/pages/demo/demo-page.component.ts 35 - - Portfolio - Portfolio + + Frequently Asked Questions (FAQ) + Preguntes freqüents (FAQ) - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 - - Benchmark - Punt de Referència + + General + General - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 - - Current Market Mood - Sentiment del Mercat + + Cloud + Núvol - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 - - Overview - Visió General + + Self-Hosting + Autoallotjament - apps/client/src/app/components/header/header.component.html - 28 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - apps/client/src/app/components/header/header.component.html - 245 + libs/common/src/lib/routes/routes.ts + 248 - - Portfolio - Portfolio + + self-hosting + autoallotjament + kebab-case - apps/client/src/app/components/header/header.component.html - 41 + libs/common/src/lib/routes/routes.ts + 243 - apps/client/src/app/components/header/header.component.html - 255 + libs/common/src/lib/routes/routes.ts + 246 - - Admin Control - Panell d’Administració + + Check out the numerous features of Ghostfolio to manage your wealth + Fes una ullada a les nombroses funcions de Ghostfolio per gestionar el teu patrimoni - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/pages/features/features-page.html + 7 + + + ETFs + ETFs - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/pages/features/features-page.html + 25 - - Upgrade Plan - Millora la teva Subscripció + + Bonds + Bons - apps/client/src/app/components/header/header.component.html - 185 + apps/client/src/app/pages/features/features-page.html + 38 + + + Wealth Items + Articles de riquesa - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + apps/client/src/app/pages/features/features-page.html + 76 + + + Import and Export + Importació i exportació - apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + apps/client/src/app/pages/features/features-page.html + 116 + + + Multi-Accounts + Multicomptes - apps/client/src/app/pages/pricing/pricing-page.html - 288 + apps/client/src/app/pages/features/features-page.html + 127 - - Renew Plan - Renova la teva Subscripció + + Portfolio Calculations + Càlculs de cartera - apps/client/src/app/components/header/header.component.html - 191 + apps/client/src/app/pages/features/features-page.html + 141 + + + Dark Mode + Mode fosc - apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + apps/client/src/app/pages/features/features-page.html + 233 + + + Market Mood + Estat d’ànim del mercat - apps/client/src/app/pages/pricing/pricing-page.html - 294 + apps/client/src/app/pages/features/features-page.html + 215 - - Me - Tu + + Static Analysis + Anàlisi estàtica - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/features/features-page.html + 179 - - User - Usuari + + Multi-Language + Multi-idioma - apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + apps/client/src/app/pages/features/features-page.html + 259 + + + Open Source Software + Programari de codi obert - apps/client/src/app/components/header/header.component.html - 229 + apps/client/src/app/pages/features/features-page.html + 295 - - My Ghostfolio - El meu Ghostfolio + + Get Started + Comença - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/features/features-page.html + 320 + + + apps/client/src/app/pages/public/public-page.html + 220 - - About Ghostfolio - Sobre Ghostfolio + + Holdings + Explotacions - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - - - Sign in - Iniciar Sessió - apps/client/src/app/components/header/header.component.html - 412 + apps/client/src/app/pages/public/public-page.html + 70 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + libs/common/src/lib/routes/routes.ts + 90 - - - Get started - Primers Passos - apps/client/src/app/components/header/header.component.html - 422 + libs/common/src/lib/routes/routes.ts + 167 - - Oops! Incorrect Security Token. - Oooh! El testimoni de seguretat és incorrecte. + + Summary + Resum - apps/client/src/app/components/header/header.component.ts - 245 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + libs/common/src/lib/routes/routes.ts + 105 - - Change - Canvia + + Markets + Mercats - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + apps/client/src/app/app.component.html + 61 - - - Average Unit Price - Preu Mig per Unitat - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + apps/client/src/app/components/header/header.component.html + 408 - - - Minimum Price - Preu Mínim - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + apps/client/src/app/components/home-market/home-market.html + 2 - - - Maximum Price - Preu Màxim - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + apps/client/src/app/components/markets/markets.html + 2 - - - Quantity - Quantitat - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + apps/client/src/app/pages/resources/resources-page.component.ts + 40 - libs/ui/src/lib/activities-table/activities-table.component.html - 186 + libs/common/src/lib/routes/routes.ts + 95 - - - Investment - Inversió - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 + libs/common/src/lib/routes/routes.ts + 100 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 - - Dividend - Dividend + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio és un tauler de control de finances personals per fer un seguiment del teu patrimoni net, incloent-hi efectiu, accions, ETF i criptomonedes en múltiples plataformes. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + aplicació, actiu, criptomoneda, tauler de control, ETF, finances, gestió, rendiment, cartera, programari, acció, negociació, riquesa, web3 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 + apps/client/src/app/pages/i18n/i18n-page.html + 10 + + + My Account + El meu compte - apps/client/src/app/pages/features/features-page.html - 63 + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + Open Source Wealth Management Software + Programari de gestió patrimonial de codi obert - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + Manage your wealth like a boss + Gestiona la teva riquesa com un cap - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + apps/client/src/app/pages/landing/landing-page.html + 6 - - Dividend Yield - Rendiment del Dividend + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio és un tauler de control de codi obert i amb privacitat per a les teves finances personals. Analitza la distribució dels teus actius, coneix el teu patrimoni net i pren decisions d’inversió sòlides i basades en dades. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/landing/landing-page.html + 10 - - Fees - Comissions + + Get Started + Comença - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + apps/client/src/app/pages/landing/landing-page.html + 42 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 84 + apps/client/src/app/pages/landing/landing-page.html + 447 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + apps/client/src/app/pages/pricing/pricing-page.html + 351 - - - Activity - Activitat - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - - Report Data Glitch - Informar d’un Problema amb les Dades + + Monthly Active Users + Usuaris actius mensuals - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + apps/client/src/app/pages/landing/landing-page.html + 70 - - Active - en Actiiu + + Stars on GitHub + Estrelles a GitHub - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/landing/landing-page.html + 88 - - - Closed - Finalitzat - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/open/open-page.html + 103 - - Table - Taula + + Pulls on Docker Hub + Activa el Docker Hub - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/pages/landing/landing-page.html + 106 - - - Chart - Gràfic - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/pages/open/open-page.html + 117 - - Manage Activities - Gestionar Activitats + + As seen in + Com es veu a - apps/client/src/app/components/home-holdings/home-holdings.html - 63 + apps/client/src/app/pages/landing/landing-page.html + 115 - - Fear - Por + + Protect your assets. Refine your personal investment strategy. + Protegeix els teus actius. Refina la teva estratègia d’inversió personal. - apps/client/src/app/components/home-market/home-market.component.ts - 27 + apps/client/src/app/pages/landing/landing-page.html + 226 + + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio permet a la gent ocupada fer un seguiment d’accions, ETF o criptomonedes sense ser rastrejada. - libs/ui/src/lib/i18n.ts - 98 + apps/client/src/app/pages/landing/landing-page.html + 230 - - Greed - Cobdícia + + 360° View + Vista de 360° - apps/client/src/app/components/home-market/home-market.component.ts - 28 + apps/client/src/app/pages/landing/landing-page.html + 240 + + + Get the full picture of your personal finances across multiple platforms. + Obtingueu la imatge completa de les vostres finances personals en múltiples plataformes. - libs/ui/src/lib/i18n.ts - 99 + apps/client/src/app/pages/landing/landing-page.html + 243 - - Last Days - Últims Dies + + Web3 Ready + Web3 llest - apps/client/src/app/components/home-market/home-market.html - 7 + apps/client/src/app/pages/landing/landing-page.html + 251 - - Welcome to Ghostfolio - Benvingut a Ghostfolio + + Use Ghostfolio anonymously and own your financial data. + Utilitza Ghostfolio de manera anònima i sigues propietari de les teves dades financeres. - apps/client/src/app/components/home-overview/home-overview.html - 7 + apps/client/src/app/pages/landing/landing-page.html + 254 - - Ready to take control of your personal finances? - Estàs preparat per controlar les teves finances personals? + + Benefit from continuous improvements through a strong community. + Beneficia’t de millores contínues gràcies a una comunitat forta. - apps/client/src/app/components/home-overview/home-overview.html - 8 + apps/client/src/app/pages/landing/landing-page.html + 264 - - Setup your accounts - Configura els teus comptes + + Why Ghostfolio? + Per què Ghostfolio? - apps/client/src/app/components/home-overview/home-overview.html - 15 + apps/client/src/app/pages/landing/landing-page.html + 272 - - Get a comprehensive financial overview by adding your bank and brokerage accounts. - Get a comprehensive financial overview by adding your bank and brokerage accounts. + + Ghostfolio is for you if you are... + Ghostfolio és per a tu si ets... - apps/client/src/app/components/home-overview/home-overview.html - 17 + apps/client/src/app/pages/landing/landing-page.html + 274 - - Capture your activities - Capture your activities + + trading stocks, ETFs or cryptocurrencies on multiple platforms + negociar accions, ETF o criptomonedes en múltiples plataformes - apps/client/src/app/components/home-overview/home-overview.html - 24 + apps/client/src/app/pages/landing/landing-page.html + 280 - - Record your investment activities to keep your portfolio up to date. - Record your investment activities to keep your portfolio up to date. + + pursuing a buy & hold strategy + perseguint una compra & mantenir l’estratègia - apps/client/src/app/components/home-overview/home-overview.html - 26 + apps/client/src/app/pages/landing/landing-page.html + 286 - - Monitor and analyze your portfolio - Monitor and analyze your portfolio + + interested in getting insights of your portfolio composition + interessat a obtenir informació sobre la composició de la vostra cartera - apps/client/src/app/components/home-overview/home-overview.html - 33 + apps/client/src/app/pages/landing/landing-page.html + 291 - - Track your progress in real-time with comprehensive analysis and insights. - Track your progress in real-time with comprehensive analysis and insights. + + valuing privacy and data ownership + valorant la privadesa i la propietat de les dades - apps/client/src/app/components/home-overview/home-overview.html - 35 + apps/client/src/app/pages/landing/landing-page.html + 296 - - Setup accounts - Setup accounts + + into minimalism + al minimalisme - apps/client/src/app/components/home-overview/home-overview.html - 44 + apps/client/src/app/pages/landing/landing-page.html + 299 - - Add activity - Add activity + + caring about diversifying your financial resources + preocupant-se per diversificar els seus recursos econòmics - apps/client/src/app/components/home-overview/home-overview.html - 52 + apps/client/src/app/pages/landing/landing-page.html + 303 + + + interested in financial independence + interessada en la independència financera - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 8 + apps/client/src/app/pages/landing/landing-page.html + 307 - - Summary - Summary + + saying no to spreadsheets in + dir no als fulls de càlcul - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/pages/landing/landing-page.html + 311 - - Total Amount - Total Amount + + still reading this list + encara llegint aquesta llista - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + apps/client/src/app/pages/landing/landing-page.html + 314 - - Savings Rate - Savings Rate + + Learn more about Ghostfolio + Més informació sobre Ghostfolio - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + apps/client/src/app/pages/landing/landing-page.html + 319 - - Security Token - Security Token + + What our users are saying + Que nostre usuaris estan dient - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 + apps/client/src/app/pages/landing/landing-page.html + 328 + + + Members from around the globe are using Ghostfolio Premium + Membres de tot el món estan utilitzant Ghostfolio Premium - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 + apps/client/src/app/pages/landing/landing-page.html + 367 + + + How does Ghostfolio work? + Com ho fa Ghostfolio treballar? - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/pages/landing/landing-page.html + 384 - - or - or + + Get started in only 3 steps + Comença en només 3 passos - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/pages/landing/landing-page.html + 386 + + + Sign up anonymously* + Registra’t de manera anònima* - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + apps/client/src/app/pages/landing/landing-page.html + 392 + + + * no e-mail address nor credit card required + * no es requereix cap adreça de correu electrònic ni targeta de crèdit apps/client/src/app/pages/landing/landing-page.html - 47 + 394 + + + Add any of your historical transactions + Afegiu qualsevol de les vostres transaccions històriques apps/client/src/app/pages/landing/landing-page.html - 450 + 406 + + + Get valuable insights of your portfolio composition + Obteniu informació valuosa sobre la composició de la vostra cartera - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 + apps/client/src/app/pages/landing/landing-page.html + 418 + + + Are you ready? + Són tu llest? - apps/client/src/app/pages/register/register-page.html - 30 + apps/client/src/app/pages/landing/landing-page.html + 432 + + + Join now or check out the example account + Uneix-te ara o consulteu el compte d’exemple - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + apps/client/src/app/pages/landing/landing-page.html + 435 - - Sign in with Internet Identity - Sign in with Internet Identity + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + A Ghostfolio, la transparència és la base dels nostres valors. Publiquem el codi font com a programari de codi obert (OSS) sota elLlicència AGPL-3.0 i compartim obertament mètriques clau agregades de l’estat operatiu de la plataforma. - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 + apps/client/src/app/pages/open/open-page.html + 7 - - Sign in with Google - Sign in with Google + + (Last 24 hours) + (Últimes 24 hores) - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 + apps/client/src/app/pages/open/open-page.html + 37 - - Stay signed in - Stay signed in + + Active Users + Usuaris actius - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 + apps/client/src/app/pages/open/open-page.html + 40 - - - Oops! A data provider is experiencing the hiccups. - Oops! A data provider is experiencing the hiccups. - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/pages/open/open-page.html + 62 - - Market data is delayed for - Market data is delayed for + + (Last 30 days) + (Últims 30 dies) - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/pages/open/open-page.html + 48 - - - Time in Market - Time in Market - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 + apps/client/src/app/pages/open/open-page.html + 59 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + New Users + Usuaris nous - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/open/open-page.html + 51 - - Buy - Buy + + Users in Slack community + Usuaris de la comunitat Slack - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + apps/client/src/app/pages/open/open-page.html + 75 - - Sell - Sell + + Contributors on GitHub + Col·laboradors a GitHub - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + apps/client/src/app/pages/open/open-page.html + 89 - - Absolute Gross Performance - Absolute Gross Performance + + (Last 90 days) + (Últims 90 dies) - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 + apps/client/src/app/pages/open/open-page.html + 127 - - Absolute Net Performance - Absolute Net Performance + + Uptime + Temps de funcionament - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 + apps/client/src/app/pages/open/open-page.html + 132 - - Net Performance - Net Performance + + Activities + Activitats - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - - - Total Assets - Total Assets - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 143 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 - - - Valuables - Valuables - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 - - - Emergency Fund - Emergency Fund - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 - apps/client/src/app/pages/features/features-page.html - 89 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 + apps/client/src/app/components/admin-users/admin-users.html + 136 - - - Cash - Cash - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Assets - Assets - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - - - Buying Power - Buying Power - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 - - - Excluded from Analysis - Excluded from Analysis - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + libs/common/src/lib/routes/routes.ts + 128 - - Liabilities - Liabilities + + Update activity + Activitat d’actualització - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 + + + Stocks, ETFs, bonds, cryptocurrencies, commodities + Accions, ETF, bons, criptomonedes, matèries primeres - apps/client/src/app/pages/features/features-page.html - 102 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 - - - Net Worth - Net Worth - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 65 - - Annualized Performance - Annualized Performance + + One-time fee, annual account fees + Comissió única, comissions de compte anual - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - Interest - Interest + + Distribution of corporate earnings + Distribució dels beneficis de les empreses - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 - - Please set the amount of your emergency fund. - Please set the amount of your emergency fund. + + Revenue for lending out money + Ingressos per prestar diners - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 - - Are you an ambitious investor who needs the full picture? - Are you an ambitious investor who needs the full picture? + + Mortgages, personal loans, credit cards + Hipoteques, préstecs personals, targetes de crèdit - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 - - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + + Luxury items, real estate, private companies + Articles de luxe, immobiliari, empreses privades - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 - - Portfolio Summary - Portfolio Summary + + Update Cash Balance + Actualitzar el saldo d’efectiu - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 24 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 + + + Unit Price + Preu unitari - apps/client/src/app/pages/pricing/pricing-page.html - 57 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 - apps/client/src/app/pages/pricing/pricing-page.html - 213 + libs/ui/src/lib/activities-table/activities-table.component.html + 210 - - Portfolio Allocations - Portfolio Allocations - - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 28 - + + Import Activities + Activitats d’importació - apps/client/src/app/pages/features/features-page.html - 161 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 - apps/client/src/app/pages/pricing/pricing-page.html - 61 + libs/ui/src/lib/activities-table/activities-table.component.html + 9 - apps/client/src/app/pages/pricing/pricing-page.html - 217 + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - - Performance Benchmarks - Performance Benchmarks + + Import Dividends + Importar dividends - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 32 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 129 - apps/client/src/app/pages/pricing/pricing-page.html - 65 + libs/ui/src/lib/activities-table/activities-table.component.html + 29 - apps/client/src/app/pages/pricing/pricing-page.html - 221 + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - - FIRE Calculator - FIRE Calculator + + Importing data... + S’estan important dades... - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 36 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 167 + + + Import has been completed + La importació s’ha completat - apps/client/src/app/pages/pricing/pricing-page.html - 69 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 176 + + + Validating data... + S’estan validant les dades... - apps/client/src/app/pages/pricing/pricing-page.html - 225 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 - - Professional Data Provider - Professional Data Provider + + Select Holding + Seleccioneu Holding - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 40 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 + + + Select File + Seleccioneu Fitxer - apps/client/src/app/pages/pricing/pricing-page.html - 240 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 22 - - and more Features... - and more Features... + + Holding + Holding - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 44 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 - apps/client/src/app/pages/pricing/pricing-page.html - 85 + libs/ui/src/lib/assistant/assistant.html + 179 + + + Load Dividends + Càrrega de dividends - apps/client/src/app/pages/pricing/pricing-page.html - 252 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 - - Get the tools to effectively manage your finances and refine your personal investment strategy. - Get the tools to effectively manage your finances and refine your personal investment strategy. + + Choose or drop a file here + Trieu o deixeu anar un fitxer aquí - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 - - Skip - Skip + + The following file formats are supported: + S’admeten els formats de fitxer següents: - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 - - Today - Today + + Select Dividends + Seleccioneu Dividends - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 + + + Select Activities + Seleccioneu Activitats - libs/ui/src/lib/assistant/assistant.component.ts - 221 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 - - YTD - YTD + + Back + Enrere - apps/client/src/app/components/toggle/toggle.component.ts - 22 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 - - 1Y - 1Y - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - + + Allocations + Allocations - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - - - 5Y - 5Y - apps/client/src/app/components/toggle/toggle.component.ts - 24 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/common/src/lib/routes/routes.ts + 133 - - Max - Max + + Proportion of Net Worth + Proporció del patrimoni net - apps/client/src/app/components/toggle/toggle.component.ts - 25 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 + + + By Platform + Per plataforma - libs/ui/src/lib/assistant/assistant.component.ts - 260 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 44 - - Oops! Could not grant access. - Oops! Could not grant access. + + By Currency + Per Moneda - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 - - Grant access - Grant access + + By Asset Class + Per classe d’actiu - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 - - Private - Private + + By Holding + Per Holding - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 - - Public - Public + + By Sector + Per sectors - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 25 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 - - User ID - User ID + + By Continent + Per continent - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 45 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 + + + By Market + Per Mercat - apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 175 - - Granted Access - Granted Access + + Regions + Regions - apps/client/src/app/components/user-account-access/user-account-access.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 - - - Please enter your coupon code: - Please enter your coupon code: - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + apps/client/src/app/pages/public/public-page.html + 143 - - Could not redeem coupon code - Could not redeem coupon code + + Developed Markets + Mercats desenvolupats - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 - - - Coupon code has been redeemed - Coupon code has been redeemed - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + apps/client/src/app/pages/public/public-page.html + 160 - - Reload - Reload + + Emerging Markets + Mercats emergents - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 - - - per year - per year - apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + apps/client/src/app/pages/public/public-page.html + 169 + + + Other Markets + Altres Mercats - apps/client/src/app/pages/pricing/pricing-page.html - 274 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 - - - Try Premium - Try Premium - apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + apps/client/src/app/pages/public/public-page.html + 178 - - Redeem Coupon - Redeem Coupon + + By Country + Per País - apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 - - Auto - Auto + + By Account + Per compte - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 - - Do you really want to close your Ghostfolio account? - Do you really want to close your Ghostfolio account? + + By ETF Provider + Pel proveïdor d’ETF - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 - - Do you really want to remove this sign in method? - Do you really want to remove this sign in method? + + By ETF Holding + Per ETF Holding - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + Approximation based on the top holdings of each ETF + Aproximació basada en les participacions principals de cada ETF - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 - - Settings - Settings + + Analysis + Anàlisi - apps/client/src/app/components/user-account-settings/user-account-settings.html + apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 - - - Presenter View - Presenter View - apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + libs/common/src/lib/routes/routes.ts + 138 - - Protection for sensitive information like absolute performances and quantity values - Protection for sensitive information like absolute performances and quantity values + + Dividend + Dividend - apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 - - - Base Currency - Base Currency - apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 - - - Language - Language - apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + apps/client/src/app/pages/features/features-page.html + 63 - - - If a translation is missing, kindly support us in extending it here. - If a translation is missing, kindly support us in extending it here. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 - - - Locale - Locale - apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 - - - Date and number format - Date and number format - apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + libs/ui/src/lib/i18n.ts + 36 - - Appearance - Appearance + + Investment + Inversió - apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - - - Auto - Auto - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - - - Light - Light - apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - - - Dark - Dark - apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 - - Zen Mode - Zen Mode + + Monthly + Mensualment - apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 + + + Yearly + Anualment - apps/client/src/app/pages/features/features-page.html - 191 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 - - Distraction-free experience for turbulent times - Distraction-free experience for turbulent times + + Absolute Asset Performance + Rendiment absolut dels actius - apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Biometric Authentication - Biometric Authentication + + Asset Performance + Rendiment de l’actiu - apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Sign in with fingerprint - Sign in with fingerprint + + Absolute Currency Performance + Rendiment absolut de la moneda - apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 - - Experimental Features - Experimental Features + + Currency Performance + Rendiment de la moneda - apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 - - Sneak peek at upcoming functionality - Sneak peek at upcoming functionality + + Absolute Net Performance + Rendiment net absolut - apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 - - Export Data - Export Data + + Net Performance + Rendiment net - apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 - - Danger Zone - Danger Zone + + Top + A dalt - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 - - Close Account - Close Account + + Bottom + A baix - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 - - This feature is currently unavailable. - This feature is currently unavailable. + + Portfolio Evolution + Evolució de la cartera - apps/client/src/app/core/http-response.interceptor.ts - 53 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 - - Please try again later. - Please try again later. + + Investment Timeline + Cronologia de la inversió - apps/client/src/app/core/http-response.interceptor.ts - 55 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 + + + Current Streak + Ratxa actual - apps/client/src/app/core/http-response.interceptor.ts - 80 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 + + + Longest Streak + Ratxa més llarga - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 - - This action is not allowed. - This action is not allowed. + + Dividend Timeline + Cronologia de dividends - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 - - Oops! Something went wrong. - Oops! Something went wrong. + + FIRE + FOC - apps/client/src/app/core/http-response.interceptor.ts - 78 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 4 + + + Calculator + Calculadora - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 - - Okay - Okay + + 4% Rule + 4% Regla - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - apps/client/src/app/core/http-response.interceptor.ts - 81 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + Currency Cluster Risks + Riscos del clúster de divises - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! It looks like you’re making too many requests. Please slow down a bit. + + Account Cluster Risks + Riscos del clúster de comptes - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 - - About - About + + Pricing + Preus - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 + apps/client/src/app/app.component.html + 99 - apps/client/src/app/pages/about/about-page.component.ts - 44 + apps/client/src/app/components/header/header.component.html + 105 - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 + apps/client/src/app/components/header/header.component.html + 313 - - - Changelog - Changelog - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/components/header/header.component.html + 389 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 - - - License - License - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 271 - - Privacy Policy - Privacy Policy - - apps/client/src/app/pages/about/about-page.component.ts - 62 - + + Pricing Plans + Plans de preus - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 4 - - Our - Our + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + La nostra oferta oficial al núvol Ghostfolio Premium és la manera més senzilla de començar. A causa del temps que estalvia, aquesta serà la millor opció per a la majoria de la gent. Els ingressos s’utilitzen per cobrir els costos de la infraestructura d’allotjament i per finançar el desenvolupament en curs. - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + apps/client/src/app/pages/pricing/pricing-page.html + 7 - - Discover other exciting Open Source Software projects - Discover other exciting Open Source Software projects + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Si prefereixes executar Ghostfolio a la teva pròpia infraestructura, consulta el codi font i les instruccions a GitHub. - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 14 - - Visit - Visit + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + Per a inversors experts en tecnologia que prefereixen executar Ghostfolio a la seva pròpia infraestructura. - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/pricing/pricing-page.html + 26 - - Accounts - Accounts + + Unlimited Transactions + Transaccions il·limitades - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 32 - - - Oops, cash balance transfer has failed. - Oops, cash balance transfer has failed. - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/pages/pricing/pricing-page.html + 121 - - - Update account - Update account - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/pages/pricing/pricing-page.html + 193 - - Add account - Add account + + Unlimited Accounts + Comptes il·limitats - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/pages/pricing/pricing-page.html + 36 - - - Account ID - Account ID - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 96 + apps/client/src/app/pages/pricing/pricing-page.html + 125 - - - From - From - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/pricing/pricing-page.html + 197 - - To - To + + Portfolio Performance + Rendiment de la cartera - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/pricing/pricing-page.html + 40 - - - Transfer - Transfer - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/pricing/pricing-page.html + 129 - - - Admin Control - Admin Control - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/pages/pricing/pricing-page.html + 201 - - Job Queue - Job Queue + + Data Import and Export + Importació i exportació de dades - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/pages/pricing/pricing-page.html + 60 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/pages/pricing/pricing-page.html + 133 - - - Market Data - Market Data - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/pages/pricing/pricing-page.html + 221 + + + Community Support + Suport comunitari - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + apps/client/src/app/pages/pricing/pricing-page.html + 77 - - Settings - Settings + + Self-hosted, update manually. + S’allotja automàticament, actualitza manualment. - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 + apps/client/src/app/pages/pricing/pricing-page.html + 81 + + + Free + Gratuït - apps/client/src/app/pages/admin/admin-page.component.ts - 32 + apps/client/src/app/pages/pricing/pricing-page.html + 83 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/pages/pricing/pricing-page.html + 146 + + + For new investors who are just getting started with trading. + Per a nous inversors que acaben de començar a operar. - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + apps/client/src/app/pages/pricing/pricing-page.html + 116 - - Users - Users + + Fully managed Ghostfolio cloud offering. + Oferta al núvol Ghostfolio totalment gestionada. - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/pages/pricing/pricing-page.html + 144 - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + apps/client/src/app/pages/pricing/pricing-page.html + 270 - - Overview - Overview + + For ambitious investors who need the full picture of their financial assets. + Per a inversors ambiciosos que necessiten la imatge completa dels seus actius financers. - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/pages/pricing/pricing-page.html + 187 + + + Email and Chat Support + Suport per correu electrònic i xat - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/pages/pricing/pricing-page.html + 266 + + + One-time payment, no auto-renewal. + Pagament únic, sense renovació automàtica. - apps/client/src/app/pages/resources/resources-page.component.ts - 16 + apps/client/src/app/pages/pricing/pricing-page.html + 303 + + + It’s free. + És gratuït. - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + apps/client/src/app/pages/pricing/pricing-page.html + 353 + + + Hello, has shared a Portfolio with you! + Hola, ha compartit un Portafoli amb tu! - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + apps/client/src/app/pages/public/public-page.html + 5 - - Blog - Blog + + Continents + Continents - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/pages/public/public-page.html + 124 - - Discover the latest Ghostfolio updates and insights on personal finance - Discover the latest Ghostfolio updates and insights on personal finance + + Would you like to refine your personal investment strategy? + Vols refinar la teva estratègia d’inversió personal? - apps/client/src/app/pages/blog/blog-page.html - 7 + apps/client/src/app/pages/public/public-page.html + 212 - - As you are already logged in, you cannot access the demo account. - As you are already logged in, you cannot access the demo account. + + Ghostfolio empowers you to keep track of your wealth. + Ghostfolio us permet fer un seguiment de la vostra riquesa. - apps/client/src/app/pages/demo/demo-page.component.ts - 35 + apps/client/src/app/pages/public/public-page.html + 216 - - Frequently Asked Questions (FAQ) - Frequently Asked Questions (FAQ) + + Registration + Inscripció - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/components/admin-users/admin-users.html + 98 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 281 - - General - General + + Continue with Internet Identity + Continueu amb Internet Identity - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + apps/client/src/app/pages/register/register-page.html + 42 - - Cloud - Cloud - - apps/client/src/app/pages/faq/faq-page.component.ts - 41 - + + Continue with Google + Continueu amb Google - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/register/register-page.html + 53 - - Self-Hosting - Self-Hosting + + Copy to clipboard + Copia al porta-retalls - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 + + + Personal Finance Tools + Eines de finances personals - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 - - - self-hosting - self-hosting - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 329 - - Frequently Asked Questions (FAQ) - Frequently Asked Questions (FAQ) + + open-source-alternative-to + alternativa-codi-obert-a + kebab-case - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + libs/common/src/lib/routes/routes.ts + 324 + + + Discover Open Source Alternatives for Personal Finance Tools + Descobriu alternatives de codi obert per a les eines de finances personals - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 - - FAQ - FAQ + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Aquesta pàgina de resum presenta una selecció acurada d’eines de finances personals comparades amb l’alternativa de codi obert Ghostfolio. Si valores la transparència, la privadesa de dades i la col·laboració comunitària, Ghostfolio t’ofereix una excel·lent oportunitat per prendre el control de la teva gestió financera. - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Exploreu els enllaços següents per comparar una varietat d'eines de finances personals amb Ghostfolio. - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 - - Check out the numerous features of Ghostfolio to manage your wealth - Check out the numerous features of Ghostfolio to manage your wealth + + Open Source Alternative to + Alternativa de codi obert a - apps/client/src/app/pages/features/features-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 - - Stocks - Stocks + + Switzerland + Suïssa - apps/client/src/app/pages/features/features-page.html - 15 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - - - ETFs - ETFs - apps/client/src/app/pages/features/features-page.html - 25 + libs/ui/src/lib/i18n.ts + 96 - - Bonds - Bonds + + Global + Global - apps/client/src/app/pages/features/features-page.html - 38 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - - - Cryptocurrencies - Cryptocurrencies - apps/client/src/app/pages/features/features-page.html - 51 + libs/ui/src/lib/i18n.ts + 16 - - Wealth Items - Wealth Items + + The Open Source Alternative to + L’alternativa de codi obert a - apps/client/src/app/pages/features/features-page.html - 76 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 - - Import and Export - Import and Export + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Estàs buscant una alternativa de codi obert a ? Ghostfolio és una potent eina de gestió de portafolis que proporciona a les persones una plataforma completa per fer el seguiment, analitzar i optimitzar les seves inversions. Tant si ets un inversor amb experiència com si tot just comences, Ghostfolio ofereix una interfície intuïtiva i una àmplia gamma de funcionalitats per ajudar-te a prendre decisions informades i a prendre el control del teu futur financer. - apps/client/src/app/pages/features/features-page.html - 115 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 - - Multi-Accounts - Multi-Accounts + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio és un programari de codi obert (OSS), que proporciona una alternativa rendible a , especialment adequada per a persones amb un pressupost ajustat, com ara aquelles que segueixen el camí cap a la independència financera i jubilació anticipada (FIRE). Mitjançant els esforços col·lectius d’una comunitat de desenvolupadors i apassionats de les finances personals, Ghostfolio millora contínuament les seves capacitats, la seva seguretat i l’experiència d’usuari. - apps/client/src/app/pages/features/features-page.html - 127 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 - - Portfolio Calculations - Portfolio Calculations + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Explorem en profunditat la taula comparativa detallada de Ghostfolio vs que trobaràs a continuació per entendre a fons com es posiciona Ghostfolio en relació amb . Analitzarem diversos aspectes com ara funcionalitats, privadesa de dades, preus i molt més, per tal que puguis prendre una decisió ben informada segons les teves necessitats personals. - apps/client/src/app/pages/features/features-page.html - 141 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - Dark Mode - Dark Mode + + Ghostfolio vs comparison table + Taula comparativa Ghostfolio vs - apps/client/src/app/pages/features/features-page.html - 178 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 - - Market Mood - Market Mood + + Founded + Fundat - apps/client/src/app/pages/features/features-page.html - 206 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 - - Static Analysis - Static Analysis + + Origin + Origen - apps/client/src/app/pages/features/features-page.html - 225 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 - - Multi-Language - Multi-Language + + Region + Regió - apps/client/src/app/pages/features/features-page.html - 242 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 - - Open Source Software - Open Source Software + + Available in + Disponible a - apps/client/src/app/pages/features/features-page.html - 278 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 - - Get Started - Get Started + + ✅ Yes + ✅ Sí - apps/client/src/app/pages/features/features-page.html - 303 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 - apps/client/src/app/pages/public/public-page.html - 220 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 - - - Holdings - Holdings - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 - apps/client/src/app/pages/home/home-page.component.ts - 42 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 - apps/client/src/app/pages/zen/zen-page.component.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 - - - Summary - Summary - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 - apps/client/src/app/pages/home/home-page.component.ts - 47 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 - - Markets - Markets + + ❌ No + ❌ No - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 - apps/client/src/app/pages/resources/resources-page.component.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 - - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - apps/client/src/app/pages/i18n/i18n-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 - - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 - - - My Account - My Account - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 - - Open Source Wealth Management Software - Open Source Wealth Management Software + + Self-Hosting + Autoallotjament - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 - - Manage your wealth like a boss - Manage your wealth like a boss + + Use anonymously + Utilitza de manera anònima - apps/client/src/app/pages/landing/landing-page.html - 5 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 210 - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + + Free Plan + Pla gratuït - apps/client/src/app/pages/landing/landing-page.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 - - Get Started - Get Started + + Starting from + A partir de - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/pricing/pricing-page.html - 324 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - Live Demo - Live Demo - - apps/client/src/app/pages/landing/landing-page.html - 49 - + + Notes + Notes - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 - - Monthly Active Users - Monthly Active Users + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Tingues en compte que la informació proporcionada a la taula comparativa Ghostfolio vs es basa en la nostra investigació i anàlisi independents. Aquest lloc web no està afiliat a ni a cap altre producte esmentat en la comparació. A mesura que evoluciona el panorama de les eines de finances personals, és essencial verificar qualsevol detall o canvi específic directament a la pàgina del producte corresponent. Necessites actualitzar dades? Ajuda’ns a mantenir la informació precisa a GitHub. - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - Stars on GitHub - Stars on GitHub + + Ready to take your investments to the next level? + Preparat per portar les teves inversions al següent nivell? - apps/client/src/app/pages/landing/landing-page.html - 88 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + Fes un seguiment, analitza i visualitza el teu patrimoni sense esforç amb Ghostfolio. - apps/client/src/app/pages/open/open-page.html - 103 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 - - Pulls on Docker Hub - Pulls on Docker Hub + + Resources + Recursos - apps/client/src/app/pages/landing/landing-page.html - 106 + apps/client/src/app/app.component.html + 64 - apps/client/src/app/pages/open/open-page.html - 117 + apps/client/src/app/components/header/header.component.html + 88 - - - As seen in - As seen in - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/components/header/header.component.html + 301 - - - Protect your assets. Refine your personal investment strategy. - Protect your assets. Refine your personal investment strategy. - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 - - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - apps/client/src/app/pages/landing/landing-page.html - 229 + libs/common/src/lib/routes/routes.ts + 332 - - 360° View - 360° View + + Membership + Pertinença - apps/client/src/app/pages/landing/landing-page.html - 240 + libs/common/src/lib/routes/routes.ts + 31 + + + libs/ui/src/lib/membership-card/membership-card.component.html + 37 - - Get the full picture of your personal finances across multiple platforms. - Get the full picture of your personal finances across multiple platforms. + + Access + Access - apps/client/src/app/pages/landing/landing-page.html - 242 + libs/common/src/lib/routes/routes.ts + 26 - - Web3 Ready - Web3 Ready + + My Ghostfolio + El meu Ghostfolio - apps/client/src/app/pages/landing/landing-page.html - 251 + apps/client/src/app/components/header/header.component.html + 277 - - - Use Ghostfolio anonymously and own your financial data. - Use Ghostfolio anonymously and own your financial data. - apps/client/src/app/pages/landing/landing-page.html - 253 + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 - - Open Source - Open Source + + Oops, authentication has failed. + Ups, l’autenticació ha fallat. - apps/client/src/app/pages/landing/landing-page.html - 261 + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 - - Benefit from continuous improvements through a strong community. - Benefit from continuous improvements through a strong community. + + Try again + Torna-ho a provar - apps/client/src/app/pages/landing/landing-page.html - 263 + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 - - Why Ghostfolio? - Why Ghostfolio? + + Go back to Home Page + Torna a la pàgina d’inici - apps/client/src/app/pages/landing/landing-page.html - 272 + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 - - Ghostfolio is for you if you are... - Ghostfolio is for you if you are... + + Do you really want to delete this account balance? + Realment voleu eliminar el saldo d’aquest compte? - apps/client/src/app/pages/landing/landing-page.html - 273 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - trading stocks, ETFs or cryptocurrencies on multiple platforms - trading stocks, ETFs or cryptocurrencies on multiple platforms + + Export Activities + Activitats d’exportació - apps/client/src/app/pages/landing/landing-page.html - 280 + libs/ui/src/lib/activities-table/activities-table.component.html + 41 - - - pursuing a buy & hold strategy - pursuing a buy & hold strategy - apps/client/src/app/pages/landing/landing-page.html - 286 + libs/ui/src/lib/activities-table/activities-table.component.html + 396 - - interested in getting insights of your portfolio composition - interested in getting insights of your portfolio composition + + Export Drafts as ICS + Exporta esborranys com a ICS - apps/client/src/app/pages/landing/landing-page.html - 291 + libs/ui/src/lib/activities-table/activities-table.component.html + 54 - - - valuing privacy and data ownership - valuing privacy and data ownership - apps/client/src/app/pages/landing/landing-page.html - 296 + libs/ui/src/lib/activities-table/activities-table.component.html + 409 - - into minimalism - into minimalism + + Delete Activities + Suprimeix les activitats - apps/client/src/app/pages/landing/landing-page.html - 299 + libs/ui/src/lib/activities-table/activities-table.component.html + 67 - - caring about diversifying your financial resources - caring about diversifying your financial resources + + Draft + Esborrany - apps/client/src/app/pages/landing/landing-page.html - 303 + libs/ui/src/lib/activities-table/activities-table.component.html + 145 - - interested in financial independence - interested in financial independence + + Clone + Clonar - apps/client/src/app/pages/landing/landing-page.html - 307 + libs/ui/src/lib/activities-table/activities-table.component.html + 436 - - saying no to spreadsheets in - saying no to spreadsheets in + + Export Draft as ICS + Exporta l’esborrany com a ICS - apps/client/src/app/pages/landing/landing-page.html - 311 + libs/ui/src/lib/activities-table/activities-table.component.html + 446 - - still reading this list - still reading this list + + Do you really want to delete these activities? + De veritat vols suprimir aquestes activitats? - apps/client/src/app/pages/landing/landing-page.html - 314 + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 - - Learn more about Ghostfolio - Learn more about Ghostfolio + + Do you really want to delete this activity? + Realment vols suprimir aquesta activitat? - apps/client/src/app/pages/landing/landing-page.html - 319 + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 - - What our users are saying - What our users are saying + + Week to date + Setmana fins avui - apps/client/src/app/pages/landing/landing-page.html - 327 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Members from around the globe are using Ghostfolio Premium - Members from around the globe are using Ghostfolio Premium + + WTD + WTD - apps/client/src/app/pages/landing/landing-page.html - 366 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - How does Ghostfolio work? - How does Ghostfolio work? + + Month to date + Mes fins a la data - apps/client/src/app/pages/landing/landing-page.html - 383 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Get started in only 3 steps - Get started in only 3 steps + + MTD + MTD - apps/client/src/app/pages/landing/landing-page.html - 386 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Sign up anonymously* - Sign up anonymously* + + Year to date + Any fins a la data - apps/client/src/app/pages/landing/landing-page.html - 392 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - * no e-mail address nor credit card required - * no e-mail address nor credit card required + + year + any - apps/client/src/app/pages/landing/landing-page.html - 394 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - - - Add any of your historical transactions - Add any of your historical transactions - apps/client/src/app/pages/landing/landing-page.html - 405 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - - - Get valuable insights of your portfolio composition - Get valuable insights of your portfolio composition - apps/client/src/app/pages/landing/landing-page.html - 417 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - Are you ready? - Are you ready? + + years + anys - apps/client/src/app/pages/landing/landing-page.html - 431 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Join now or check out the example account - Join now or check out the example account + + Asset Profiles + Perfils d’actius - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - - Get Started - Get Started + + Date Range + Interval de dates - apps/client/src/app/pages/landing/landing-page.html - 446 + libs/ui/src/lib/assistant/assistant.html + 143 - - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + + Reset Filters + Restableix els filtres - apps/client/src/app/pages/open/open-page.html - 6 + libs/ui/src/lib/assistant/assistant.html + 238 - - (Last 24 hours) - (Last 24 hours) + + Apply Filters + Aplicar filtres - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/assistant/assistant.html + 248 - - Active Users - Active Users + + 50-Day Trend + Tendència de 50 dies - apps/client/src/app/pages/open/open-page.html - 40 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + Tendència de 200 dies - apps/client/src/app/pages/open/open-page.html - 62 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 - - (Last 30 days) - (Last 30 days) + + Last All Time High + Darrer tot el temps - apps/client/src/app/pages/open/open-page.html - 48 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 + + + Change from All Time High + Canvi des del màxim històric - apps/client/src/app/pages/open/open-page.html - 59 + libs/ui/src/lib/benchmark/benchmark.component.html + 110 - - New Users - New Users + + from ATH + de l’ATH - apps/client/src/app/pages/open/open-page.html - 51 + libs/ui/src/lib/benchmark/benchmark.component.html + 112 - - Users in Slack community - Users in Slack community + + Market data provided by + Dades de mercat proporcionades per - apps/client/src/app/pages/open/open-page.html - 75 + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 - - Contributors on GitHub - Contributors on GitHub + + Savings Rate per Month + Taxa d’estalvi per mes - apps/client/src/app/pages/open/open-page.html - 89 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 - - (Last 90 days) - (Last 90 days) + + Annual Interest Rate + Taxa d’interès anual - apps/client/src/app/pages/open/open-page.html - 127 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 - - Uptime - Uptime + + Retirement Date + Data de jubilació - apps/client/src/app/pages/open/open-page.html - 132 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 - - Activities - Activities + + Projected Total Amount + Import total previst - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 + + + Deposit + Dipòsit - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 - - Update activity - Update activity + + Interest + Interès - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 10 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 - - - Stocks, ETFs, bonds, cryptocurrencies, commodities - Stocks, ETFs, bonds, cryptocurrencies, commodities - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 25 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 65 + libs/ui/src/lib/i18n.ts + 38 - - One-time fee, annual account fees - One-time fee, annual account fees + + Savings + Estalvi - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 - - Distribution of corporate earnings - Distribution of corporate earnings + + Allocation + Assignació - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 - - - Revenue for lending out money - Revenue for lending out money - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 - - - Mortgages, personal loans, credit cards - Mortgages, personal loans, credit cards - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 57 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 40 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 - - Luxury items, real estate, private companies - Luxury items, real estate, private companies + + Show all + Mostra-ho tot - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 73 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 - + Account - Account + Compte apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 85 @@ -4679,2957 +5333,2802 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 157 + + + libs/ui/src/lib/i18n.ts + 4 - - Update Cash Balance - Update Cash Balance + + Asia-Pacific + Àsia-Pacífic - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 112 + libs/ui/src/lib/i18n.ts + 5 - - Unit Price - Unit Price + + Asset Class + Classe d’actius - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 - libs/ui/src/lib/activities-table/activities-table.component.html - 210 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 - - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 - - - Fee - Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 + 290 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + libs/ui/src/lib/assistant/assistant.html + 218 - libs/ui/src/lib/activities-table/activities-table.component.html - 234 + libs/ui/src/lib/i18n.ts + 6 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from + + Asset Sub Class + Subclasse d’actiu - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 - - - Import Activities - Import Activities - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 - - - Import Dividends - Import Dividends - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + + + libs/ui/src/lib/i18n.ts + 7 - - Importing data... - Importing data... + + Buy and sell + Comprar i vendre - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + libs/ui/src/lib/i18n.ts + 8 - - Import has been completed - Import has been completed + + Core + Bàsic - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + libs/ui/src/lib/i18n.ts + 10 - - Validating data... - Validating data... + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily + Canvia fàcilment a Ghostfolio Premium o Ghostfolio Open Source - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + libs/ui/src/lib/i18n.ts + 12 - - Select Holding - Select Holding + + Switch to Ghostfolio Premium easily + Canvia fàcilment a Ghostfolio Premium - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 20 + libs/ui/src/lib/i18n.ts + 13 - - Select File - Select File + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily + Canvia fàcilment a Ghostfolio Open Source o Ghostfolio Basic - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 22 + libs/ui/src/lib/i18n.ts + 14 - - Holding - Holding + + Emergency Fund + Fons d’emergència - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 32 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 - libs/ui/src/lib/assistant/assistant.html - 127 + apps/client/src/app/pages/features/features-page.html + 89 - - - Load Dividends - Load Dividends - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 68 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 - - - Choose or drop a file here - Choose or drop a file here - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/i18n.ts + 15 - - The following file formats are supported: - The following file formats are supported: + + Grant + Subvenció - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 90 + libs/ui/src/lib/i18n.ts + 17 - - Select Dividends - Select Dividends + + Higher Risk + Risc Alt - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 113 + libs/ui/src/lib/i18n.ts + 18 - - Select Activities - Select Activities + + This activity already exists. + Aquesta activitat ja existeix. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 115 + libs/ui/src/lib/i18n.ts + 19 - - Back - Back + + Japan + Japó - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 144 + libs/ui/src/lib/i18n.ts + 89 + + + Lower Risk + Risc Baix - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 178 + libs/ui/src/lib/i18n.ts + 20 - - Allocations - Allocations + + Month + Mes - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 21 + + + Months + Mesos - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/ui/src/lib/i18n.ts + 22 - - Allocations - Allocations + + Other + Altres - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + libs/ui/src/lib/i18n.ts + 23 - - - Proportion of Net Worth - Proportion of Net Worth - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 12 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 - - By Platform - By Platform + + Preset + Predefinit - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 44 + libs/ui/src/lib/i18n.ts + 25 - - By Currency - By Currency - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 63 + + Retirement Provision + Provisió de jubilació + + libs/ui/src/lib/i18n.ts + 26 - - By Asset Class - By Asset Class + + Satellite + Satèl·lit - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 85 + libs/ui/src/lib/i18n.ts + 27 - - By Holding - By Holding + + Symbol + Símbol - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 107 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 - - - By Sector - By Sector - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 130 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 - - - By Continent - By Continent - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 153 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 - - - By Market - By Market - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 175 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 - - - Regions - Regions - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 198 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 - apps/client/src/app/pages/public/public-page.html - 143 + libs/ui/src/lib/i18n.ts + 28 - - Developed Markets - Developed Markets + + Tag + Etiqueta - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 222 + libs/ui/src/lib/assistant/assistant.html + 207 - apps/client/src/app/pages/public/public-page.html - 160 + libs/ui/src/lib/i18n.ts + 29 - - Emerging Markets - Emerging Markets + + Year + Any - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 231 + libs/ui/src/lib/i18n.ts + 30 + + + Years + Anys - apps/client/src/app/pages/public/public-page.html - 169 + libs/ui/src/lib/i18n.ts + 31 - - Other Markets - Other Markets + + Buy + Comprar - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 240 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 - apps/client/src/app/pages/public/public-page.html - 178 + libs/ui/src/lib/i18n.ts + 35 - - No data available - No data available + + Fee + Comissió - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/pages/public/public-page.html - 188 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - libs/ui/src/lib/benchmark/benchmark.component.html - 137 + libs/ui/src/lib/i18n.ts + 37 + + + Valuable + Valuós - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + libs/ui/src/lib/i18n.ts + 39 - - By Country - By Country + + Liability + Passiu - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 264 + libs/ui/src/lib/i18n.ts + 40 - - By Account - By Account + + Sell + Vendre - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 286 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 - - - By ETF Provider - By ETF Provider - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 306 + libs/ui/src/lib/i18n.ts + 41 - - By ETF Holding - By ETF Holding + + Cash + Efectiu - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + + + libs/ui/src/lib/i18n.ts + 53 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Commodity + Mercaderia - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + libs/ui/src/lib/i18n.ts + 45 - - Analysis - Analysis + + Equity + Patrimoni - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/ui/src/lib/i18n.ts + 46 - - Dividend - Dividend + + Fixed Income + Ingressos Fixos - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + libs/ui/src/lib/i18n.ts + 47 + + + Liquidity + Liquiditat libs/ui/src/lib/i18n.ts - 36 + 48 - - Investment - Investment + + Real Estate + Immobiliari - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + libs/ui/src/lib/i18n.ts + 49 + + + Bond + Bona - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + libs/ui/src/lib/i18n.ts + 52 + + + Cryptocurrency + Criptomoneda - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + libs/ui/src/lib/i18n.ts + 55 - - Monthly - Monthly + + ETF + ETF - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + libs/ui/src/lib/i18n.ts + 56 - - Yearly - Yearly + + Mutual Fund + Fons d’inversió - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + libs/ui/src/lib/i18n.ts + 57 - - Analysis - Analysis + + Precious Metal + Metall preciós - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + libs/ui/src/lib/i18n.ts + 58 - - Absolute Asset Performance - Absolute Asset Performance + + Private Equity + Capital privat - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + libs/ui/src/lib/i18n.ts + 59 - - Asset Performance - Asset Performance + + Stock + Acció - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + libs/ui/src/lib/i18n.ts + 60 - - Absolute Currency Performance - Absolute Currency Performance + + Africa + Àfrica - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + libs/ui/src/lib/i18n.ts + 67 - - Currency Performance - Currency Performance + + Asia + Àsia - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + libs/ui/src/lib/i18n.ts + 68 - - Absolute Net Performance - Absolute Net Performance + + Europe + Europa - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + libs/ui/src/lib/i18n.ts + 69 - - Net Performance - Net Performance + + North America + Amèrica del Nord - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + libs/ui/src/lib/i18n.ts + 70 - - Top - Top + + Oceania + Oceania - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + libs/ui/src/lib/i18n.ts + 71 - - Bottom - Bottom + + South America + Amèrica del Sud - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + libs/ui/src/lib/i18n.ts + 72 - - Portfolio Evolution - Portfolio Evolution + + Extreme Fear + Extreme Fear - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + libs/ui/src/lib/i18n.ts + 103 - - Investment Timeline - Investment Timeline + + Extreme Greed + Extreme Greed - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + libs/ui/src/lib/i18n.ts + 104 - - Current Streak - Current Streak + + Neutral + Neutral - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + libs/ui/src/lib/i18n.ts + 107 - - Longest Streak - Longest Streak + + Valid until + Valid until - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 - - - Dividend Timeline - Dividend Timeline - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + libs/ui/src/lib/membership-card/membership-card.component.html + 42 - - FIRE - FIRE + + Time to add your first activity. + Time to add your first activity. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 4 + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 - - Calculator - Calculator + + No data available + No data available - apps/client/src/app/pages/portfolio/fire/fire-page.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 - - - 4% Rule - 4% Rule - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 + apps/client/src/app/pages/public/public-page.html + 188 - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + libs/ui/src/lib/benchmark/benchmark.component.html + 202 - - - Currency Cluster Risks - Currency Cluster Risks - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 - - - Account Cluster Risks - Account Cluster Risks - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 - - - Pricing - Pricing - apps/client/src/app/pages/pricing/pricing-page-routing.module.ts - 13 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - - Pricing Plans - Pricing Plans + + Show more + Show more - apps/client/src/app/pages/pricing/pricing-page.html - 4 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. + + Alternative + Alternative - apps/client/src/app/pages/pricing/pricing-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + + App + App - apps/client/src/app/pages/pricing/pricing-page.html - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 - - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + + Budgeting + Budgeting - apps/client/src/app/pages/pricing/pricing-page.html - 38 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 - - Unlimited Transactions - Unlimited Transactions + + Community + Community - apps/client/src/app/pages/pricing/pricing-page.html - 45 + apps/client/src/app/app.component.html + 130 - apps/client/src/app/pages/pricing/pricing-page.html - 134 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 - apps/client/src/app/pages/pricing/pricing-page.html - 201 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 - - - Unlimited Accounts - Unlimited Accounts - apps/client/src/app/pages/pricing/pricing-page.html - 49 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 - apps/client/src/app/pages/pricing/pricing-page.html - 138 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 - apps/client/src/app/pages/pricing/pricing-page.html - 205 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 - - - Portfolio Performance - Portfolio Performance - apps/client/src/app/pages/pricing/pricing-page.html - 53 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 - apps/client/src/app/pages/pricing/pricing-page.html - 142 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 - apps/client/src/app/pages/pricing/pricing-page.html - 209 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 - - - Data Import and Export - Data Import and Export - apps/client/src/app/pages/pricing/pricing-page.html - 73 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 - apps/client/src/app/pages/pricing/pricing-page.html - 146 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 - apps/client/src/app/pages/pricing/pricing-page.html - 229 + apps/client/src/app/pages/features/features-page.html + 276 - - - Community Support - Community Support - apps/client/src/app/pages/pricing/pricing-page.html - 90 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 - - Self-hosted, update manually. - Self-hosted, update manually. + + Family Office + Family Office - apps/client/src/app/pages/pricing/pricing-page.html - 94 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 - - Free - Free - - apps/client/src/app/pages/pricing/pricing-page.html - 95 - + + Investor + Investor - apps/client/src/app/pages/pricing/pricing-page.html - 158 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 - - For new investors who are just getting started with trading. - For new investors who are just getting started with trading. + + Open Source + Open Source - apps/client/src/app/pages/pricing/pricing-page.html - 128 + apps/client/src/app/pages/landing/landing-page.html + 261 - - - Fully managed Ghostfolio cloud offering. - Fully managed Ghostfolio cloud offering. - apps/client/src/app/pages/pricing/pricing-page.html - 157 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + Personal Finance + Personal Finance - apps/client/src/app/pages/pricing/pricing-page.html - 261 + apps/client/src/app/app.component.html + 57 - - - For ambitious investors who need the full picture of their financial assets. - For ambitious investors who need the full picture of their financial assets. - apps/client/src/app/pages/pricing/pricing-page.html - 194 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 - - Email and Chat Support - Email and Chat Support + + Privacy + Privacy - apps/client/src/app/pages/pricing/pricing-page.html - 257 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 - - One-time payment, no auto-renewal. - One-time payment, no auto-renewal. + + Software + Software - apps/client/src/app/pages/pricing/pricing-page.html - 298 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 - - It’s free. - It’s free. + + Tool + Tool - apps/client/src/app/pages/pricing/pricing-page.html - 327 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 - - Hello, has shared a Portfolio with you! - Hello, has shared a Portfolio with you! + + User Experience + User Experience - apps/client/src/app/pages/public/public-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 - - Currencies - Currencies + + Wealth + Wealth - apps/client/src/app/pages/public/public-page.html - 88 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 - - Continents - Continents + + Wealth Management + Wealth Management - apps/client/src/app/pages/public/public-page.html - 124 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? + + Australia + Australia - apps/client/src/app/pages/public/public-page.html - 211 + libs/ui/src/lib/i18n.ts + 76 - - Ghostfolio empowers you to keep track of your wealth. - Ghostfolio empowers you to keep track of your wealth. + + Austria + Austria - apps/client/src/app/pages/public/public-page.html - 215 + libs/ui/src/lib/i18n.ts + 77 - - Registration - Registration + + Belgium + Belgium - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 78 - - Continue with Internet Identity - Continue with Internet Identity + + Bulgaria + Bulgaria - apps/client/src/app/pages/register/register-page.html - 42 + libs/ui/src/lib/i18n.ts + 80 - - Continue with Google - Continue with Google + + Canada + Canada - apps/client/src/app/pages/register/register-page.html - 53 + libs/ui/src/lib/i18n.ts + 81 - - Copy to clipboard - Copy to clipboard + + Czech Republic + Czech Republic - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + libs/ui/src/lib/i18n.ts + 82 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. + + Finland + Finland - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + libs/ui/src/lib/i18n.ts + 83 - - Agree and continue - Agree and continue + + France + France - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + libs/ui/src/lib/i18n.ts + 84 - - Personal Finance Tools - Personal Finance Tools + + Germany + Germany - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + libs/ui/src/lib/i18n.ts + 85 - - open-source-alternative-to - open-source-alternative-to + + India + India - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + libs/ui/src/lib/i18n.ts + 86 + + + Italy + Italy - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 88 - - Open Source Alternative to - Open Source Alternative to + + Netherlands + Netherlands - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + libs/ui/src/lib/i18n.ts + 90 - - Discover Open Source Alternatives for Personal Finance Tools - Discover Open Source Alternatives for Personal Finance Tools + + New Zealand + New Zealand - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + libs/ui/src/lib/i18n.ts + 91 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + + Poland + Poland - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/i18n.ts + 92 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Explore the links below to compare a variety of personal finance tools with Ghostfolio. + + Romania + Romania - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + libs/ui/src/lib/i18n.ts + 93 - - Open Source Alternative to - Open Source Alternative to + + South Africa + South Africa - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + libs/ui/src/lib/i18n.ts + 95 - - Switzerland - Switzerland + + Thailand + Thailand - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + libs/ui/src/lib/i18n.ts + 97 + + + United States + United States libs/ui/src/lib/i18n.ts - 90 + 100 - - Global - Global + + Error + Error - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + Deactivate + Deactivate - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/components/rule/rule.component.html + 72 - - The Open Source Alternative to - The Open Source Alternative to + + Activate + Activate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + apps/client/src/app/components/rule/rule.component.html + 74 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + + Inactive + Inactive - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + + Cancel + Cancel - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - - - Ghostfolio vs comparison table - Ghostfolio vs comparison table - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - Founded - Founded - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 77 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 - - - Origin - Origin - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 82 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 - - - Region - Region - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 87 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 - - - Available in - Available in - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 - - - ✅ Yes - ✅ Yes - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 140 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 157 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 179 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 196 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 218 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 235 + libs/ui/src/lib/i18n.ts + 9 + + + Close + Close - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 257 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 274 + libs/ui/src/lib/i18n.ts + 11 - - ❌ No - ❌ No + + Yes + Yes - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 147 + libs/ui/src/lib/i18n.ts + 32 + + + Copy link to clipboard + Copy link to clipboard - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 164 + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + Portfolio Snapshot + Portfolio Snapshot - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 186 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 + + + Change with currency effect Change + Change with currency effect Change - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 203 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 + + + Performance with currency effect Performance + Performance with currency effect Performance - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 225 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 + + + Threshold Min + Threshold Min - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 242 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 + + + Threshold Max + Threshold Max - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 264 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 + + + Customize + Customize - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 281 + apps/client/src/app/components/rule/rule.component.html + 67 - - Self-Hosting - Self-Hosting + + No auto-renewal. + No auto-renewal. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Use anonymously - Use anonymously + + This year + This year - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + apps/client/src/app/pages/public/public-page.html + 42 - - Free Plan - Free Plan + + From the beginning + From the beginning - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + apps/client/src/app/pages/public/public-page.html + 60 - - Starting from - Starting from + + Oops! Invalid currency. + Oops! Invalid currency. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 + + + This page has been archived. + This page has been archived. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + 14 - - year - year + + is Open Source Software + is Open Source Software apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + 139 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + 156 - - Notes - Notes + + is not Open Source Software + is not Open Source Software apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 302 + 146 - - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + 163 - - Ready to take your investments to the next level? - Ready to take your investments to the next level? + + can be self-hosted + can be self-hosted apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + 178 - - - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 + 195 - - Get Started - Get Started + + cannot be self-hosted + cannot be self-hosted apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + 185 - - - Personal Finance Tools - Personal Finance Tools apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Resources - Resources - - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + 202 - - Guides - Guides + + can be used anonymously + can be used anonymously - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Glossary - Glossary - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Membership - Membership + + cannot be used anonymously + cannot be used anonymously - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Access - Access + + offers a free plan + offers a free plan - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - My Ghostfolio - My Ghostfolio + + does not offer a free plan + does not offer a free plan - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - Oops, authentication has failed. - Oops, authentication has failed. - apps/client/src/app/pages/webauthn/webauthn-page.html - 19 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Try again - Try again + + Oops! Could not find any assets. + Oops! Could not find any assets. - apps/client/src/app/pages/webauthn/webauthn-page.html - 27 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - Go back to Home Page - Go back to Home Page + + Data Providers + Data Providers - apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Do you really want to delete this account balance? - Do you really want to delete this account balance? + + Set API key + Set API key - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Import Activities - Import Activities - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges - libs/ui/src/lib/activities-table/activities-table.component.html - 371 + libs/ui/src/lib/i18n.ts + 24 - - Import Dividends - Import Dividends - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - + + Ukraine + Ukraine - libs/ui/src/lib/activities-table/activities-table.component.html - 383 + libs/ui/src/lib/i18n.ts + 98 - - Export Activities - Export Activities - - libs/ui/src/lib/activities-table/activities-table.component.html - 41 - + + Join now + Join now - libs/ui/src/lib/activities-table/activities-table.component.html - 396 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Export Drafts as ICS - Export Drafts as ICS - - libs/ui/src/lib/activities-table/activities-table.component.html - 54 - + + Glossary + Glossary - libs/ui/src/lib/activities-table/activities-table.component.html - 409 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - Delete Activities - Delete Activities - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Draft - Draft - libs/ui/src/lib/activities-table/activities-table.component.html - 145 + libs/common/src/lib/routes/routes.ts + 293 - - Clone - Clone + + Guides + Guides - libs/ui/src/lib/activities-table/activities-table.component.html - 436 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Export Draft as ICS - Export Draft as ICS - libs/ui/src/lib/activities-table/activities-table.component.html - 446 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Do you really want to delete these activities? - Do you really want to delete these activities? - libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + libs/common/src/lib/routes/routes.ts + 301 - - Do you really want to delete this activity? - Do you really want to delete this activity? + + guides + guides + kebab-case - libs/ui/src/lib/activities-table/activities-table.component.ts - 229 + libs/common/src/lib/routes/routes.ts + 296 - - - Find holding... - Find holding... - libs/ui/src/lib/assistant/assistant.component.ts - 144 + libs/common/src/lib/routes/routes.ts + 299 - - Week to date - Week to date + + glossary + glossary + kebab-case - libs/ui/src/lib/assistant/assistant.component.ts - 223 + libs/common/src/lib/routes/routes.ts + 288 - - - WTD - WTD - libs/ui/src/lib/assistant/assistant.component.ts - 223 + libs/common/src/lib/routes/routes.ts + 291 - - Month to date - Month to date + + Threshold range + Threshold range - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - MTD - MTD + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Year to date - Year to date + + Economic Market Cluster Risks + Economic Market Cluster Risks - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - year - year + + of + of - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - years - years + + daily requests + daily requests - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - No entries... - No entries... + + Remove API key + Remove API key - libs/ui/src/lib/assistant/assistant.html - 63 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 + + + Do you really want to delete the API key? + Do you really want to delete the API key? - libs/ui/src/lib/assistant/assistant.html - 84 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Asset Profiles - Asset Profiles + + Please enter your Ghostfolio API key: + Please enter your Ghostfolio API key: - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Date Range - Date Range + + API Requests Today + API Requests Today - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Reset Filters - Reset Filters + + Could not generate an API key + Could not generate an API key - libs/ui/src/lib/assistant/assistant.html - 185 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - Apply Filters - Apply Filters + + Set this API key in your self-hosted environment: + Set this API key in your self-hosted environment: - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - Index - Index + + Ghostfolio Premium Data Provider API Key + Ghostfolio Premium Data Provider API Key - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - 50-Day Trend - 50-Day Trend + + Do you really want to generate a new API key? + Do you really want to generate a new API key? - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - 200-Day Trend - 200-Day Trend + + API Key + API Key - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - Last All Time High - Last All Time High + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - Change from All Time High - Change from All Time High + + out of + out of - libs/ui/src/lib/benchmark/benchmark.component.html - 81 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - from ATH - from ATH + + rules align with your portfolio. + rules align with your portfolio. - libs/ui/src/lib/benchmark/benchmark.component.html - 83 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Market data provided by - Market data provided by + + Save + Save - libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html - 2 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - - - Savings Rate per Month - Savings Rate per Month - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 10 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Annual Interest Rate - Annual Interest Rate - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 21 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - Retirement Date - Retirement Date - libs/ui/src/lib/fire-calculator/fire-calculator.component.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Projected Total Amount - Projected Total Amount - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Deposit - Deposit - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Interest - Interest - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - libs/ui/src/lib/i18n.ts - 38 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 - - - Savings - Savings - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - - - Allocation - Allocation - libs/ui/src/lib/holdings-table/holdings-table.component.html - 98 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 40 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 + + + Asset Class Cluster Risks + Asset Class Cluster Risks - libs/ui/src/lib/top-holdings/top-holdings.component.html - 116 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Show all - Show all + + Me + Me - libs/ui/src/lib/holdings-table/holdings-table.component.html - 197 + apps/client/src/app/components/header/header.component.html + 213 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Account - Account + + Received Access + Received Access - libs/ui/src/lib/i18n.ts - 4 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Asia-Pacific - Asia-Pacific + + Please enter your Ghostfolio API key. + Please enter your Ghostfolio API key. - libs/ui/src/lib/i18n.ts - 5 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Asset Class - Asset Class + + AI prompt has been copied to the clipboard + AI prompt has been copied to the clipboard - libs/ui/src/lib/i18n.ts - 6 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Asset Sub Class - Asset Sub Class + + Link has been copied to the clipboard + Link has been copied to the clipboard - libs/ui/src/lib/i18n.ts - 7 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Buy and sell - Buy and sell + + Regional Market Cluster Risks + Regional Market Cluster Risks - libs/ui/src/lib/i18n.ts - 8 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Core - Core + + Lazy + Lazy - libs/ui/src/lib/i18n.ts - 10 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Switch to Ghostfolio Premium or Ghostfolio Open Source easily - Switch to Ghostfolio Premium or Ghostfolio Open Source easily + + Instant + Instant - libs/ui/src/lib/i18n.ts - 12 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Switch to Ghostfolio Premium easily - Switch to Ghostfolio Premium easily + + Default Market Price + Default Market Price - libs/ui/src/lib/i18n.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Switch to Ghostfolio Open Source or Ghostfolio Basic easily - Switch to Ghostfolio Open Source or Ghostfolio Basic easily + + Mode + Mode - libs/ui/src/lib/i18n.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Emergency Fund - Emergency Fund + + Selector + Selector - libs/ui/src/lib/i18n.ts - 15 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Grant - Grant + + HTTP Request Headers + HTTP Request Headers - libs/ui/src/lib/i18n.ts - 17 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - Higher Risk - Higher Risk + + end of day + end of day - libs/ui/src/lib/i18n.ts - 18 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - This activity already exists. - This activity already exists. + + real-time + real-time - libs/ui/src/lib/i18n.ts - 19 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Japan - Japan + + Open Duck.ai + Open Duck.ai - libs/ui/src/lib/i18n.ts - 84 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Lower Risk - Lower Risk + + Create + Create - libs/ui/src/lib/i18n.ts - 20 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - Month - Month + + Change + Change - libs/ui/src/lib/i18n.ts - 21 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - Months - Months - libs/ui/src/lib/i18n.ts - 22 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Other - Other + + Performance + Performance - libs/ui/src/lib/i18n.ts - 23 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Preset - Preset - libs/ui/src/lib/i18n.ts - 25 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Retirement Provision - Retirement Provision - libs/ui/src/lib/i18n.ts - 26 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - - Satellite - Satellite - libs/ui/src/lib/i18n.ts - 27 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Symbol - Symbol + + Copy portfolio data to clipboard for AI prompt + Copy portfolio data to clipboard for AI prompt - libs/ui/src/lib/i18n.ts - 28 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - Tag - Tag + + Copy AI prompt to clipboard for analysis + Copy AI prompt to clipboard for analysis - libs/ui/src/lib/i18n.ts - 29 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - Year - Year + + Armenia + Armenia libs/ui/src/lib/i18n.ts - 30 + 75 - - Years - Years + + British Virgin Islands + British Virgin Islands libs/ui/src/lib/i18n.ts - 31 + 79 - - Buy - Buy + + Singapore + Singapore libs/ui/src/lib/i18n.ts - 35 + 94 - - Fee - Fee + + Terms and Conditions + Terms and Conditions - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - Valuable - Valuable + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Please keep your security token safe. If you lose it, you will not be able to recover your account. - libs/ui/src/lib/i18n.ts - 39 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Liability - Liability + + I understand that if I lose my security token, I cannot recover my account + I understand that if I lose my security token, I cannot recover my account - libs/ui/src/lib/i18n.ts - 40 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Sell - Sell + + Continue + Continue - libs/ui/src/lib/i18n.ts - 41 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Cash - Cash + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Here is your security token. It is only visible once, please store and keep it in a safe place. - libs/ui/src/lib/i18n.ts - 44 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Commodity - Commodity + + Security token + Security token - libs/ui/src/lib/i18n.ts - 45 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Equity - Patrimoni - libs/ui/src/lib/i18n.ts - 46 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Fixed Income - Fixed Income + + Do you really want to generate a new security token for this user? + Do you really want to generate a new security token for this user? - libs/ui/src/lib/i18n.ts - 47 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - Liquidity - Liquidity + + Generate Security Token + Generate Security Token - libs/ui/src/lib/i18n.ts - 48 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Real Estate - Real Estate + + United Kingdom + United Kingdom libs/ui/src/lib/i18n.ts - 49 + 99 - - Bond - Bond + + Terms of Service + Terms of Service - libs/ui/src/lib/i18n.ts - 52 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Cryptocurrency - Cryptocurrency + + terms-of-service + terms-of-service + kebab-case - libs/ui/src/lib/i18n.ts - 53 + libs/common/src/lib/routes/routes.ts + 212 - - - ETF - ETF - libs/ui/src/lib/i18n.ts - 54 + libs/common/src/lib/routes/routes.ts + 215 - - Mutual Fund - Mutual Fund + + Terms of Service + Terms of Service - libs/ui/src/lib/i18n.ts - 55 + apps/client/src/app/app.component.html + 112 - - - Precious Metal - Precious Metal - libs/ui/src/lib/i18n.ts - 56 + libs/common/src/lib/routes/routes.ts + 217 - - Private Equity - Private Equity + + and I agree to the Terms of Service. + and I agree to the Terms of Service. - libs/ui/src/lib/i18n.ts - 57 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Stock - Stock + + () is already in use. + () is already in use. - libs/ui/src/lib/i18n.ts - 58 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Africa - Africa + + An error occurred while updating to (). + An error occurred while updating to (). - libs/ui/src/lib/i18n.ts - 65 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Asia - Asia + + Apply + Apply - libs/ui/src/lib/i18n.ts - 66 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Europe - Europe + + with API access for + with API access for - libs/ui/src/lib/i18n.ts - 67 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - North America - North America + + Gather Recent Historical Market Data + Gather Recent Historical Market Data - libs/ui/src/lib/i18n.ts - 68 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Oceania - Oceania + + Gather All Historical Market Data + Gather All Historical Market Data - libs/ui/src/lib/i18n.ts - 69 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - South America - South America + + Gather Historical Market Data + Gather Historical Market Data - libs/ui/src/lib/i18n.ts - 70 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Extreme Fear - Extreme Fear + + Data Gathering is off + Data Gathering is off - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Extreme Greed - Extreme Greed + + Performance Calculation + Performance Calculation - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Neutral - Neutral + + someone + someone - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Membership - Membership + + Add asset to watchlist + Add asset to watchlist - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Valid until - Valid until + + Watchlist + Watchlist - apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - libs/ui/src/lib/membership-card/membership-card.component.html - 42 + apps/client/src/app/pages/features/features-page.html + 197 - - - Time to add your first activity. - Time to add your first activity. - libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html - 12 + libs/common/src/lib/routes/routes.ts + 110 - - No data available - No data available + + Do you really want to delete this item? + Do you really want to delete this item? - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 + + + Log out + Log out - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + apps/client/src/app/components/header/header.component.html + 329 - - Show more - Show more + + Calculations are based on delayed market data and may not be displayed in real-time. + Calculations are based on delayed market data and may not be displayed in real-time. - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/home-market/home-market.html + 44 - - - Alternative - Alternative - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/markets/markets.html + 53 - - App - App + + changelog + changelog + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + libs/common/src/lib/routes/routes.ts + 180 - - - Budgeting - Budgeting - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 183 - - Community - Community + + Demo user account has been synced. + Demo user account has been synced. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Family Office - Family Office + + Sync Demo User Account + Sync Demo User Account - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Investor - Investor + + Set up + Set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Open Source - Open Source + + No emergency fund has been set up + No emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Personal Finance - Personal Finance + + An emergency fund has been set up + An emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Privacy - Privacy + + Fee Ratio + Fee Ratio - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Software - Software + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Tool - Tool + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - User Experience - User Experience + + Name + Name - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth - Wealth + + Find holding or page... + Find holding or page... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Wealth Management - Wealth Management + + Quick Links + Quick Links - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 56 - - Australia - Australia + + Asset Profiles + Asset Profiles - libs/ui/src/lib/i18n.ts - 73 + libs/ui/src/lib/assistant/assistant.html + 112 - - Austria - Austria + + Live Demo + Live Demo - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Belgium - Belgium - libs/ui/src/lib/i18n.ts - 75 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Bulgaria - Bulgaria - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 231 - - Canada - Canada + + Open Source Alternative to + Open Source Alternative to - libs/ui/src/lib/i18n.ts - 77 + libs/common/src/lib/routes/routes.ts + 326 - - Czech Republic - Czech Republic + + Single Account + Single Account - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Finland - Finland + + Your net worth is managed by a single account + Your net worth is managed by a single account - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - France - France + + Your net worth is managed by ${accountsLength} accounts + Your net worth is managed by ${accountsLength} accounts - libs/ui/src/lib/i18n.ts - 80 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - Germany - Germany + + personal-finance-tools + personal-finance-tools + kebab-case - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 312 - - - India - India - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 315 - - - Italy - Italy - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 323 - - Netherlands - Netherlands + + markets + markets + kebab-case - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 304 - - - New Zealand - New Zealand - libs/ui/src/lib/i18n.ts - 86 + libs/common/src/lib/routes/routes.ts + 307 - - Poland - Poland + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Romania - Romania + + Get Access + Get Access - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - South Africa - South Africa + + Learn more + Learn more - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - Thailand - Thailand + + Limited Offer! + Limited Offer! - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - United States - United States + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Error - Error + + Available + Available - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Deactivate - Deactivate + + Unavailable + Unavailable - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Activate - Activate + + new + new - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Inactive - Inactive - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Cancel - Cancel + + Investment + Investment - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Close - Close + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Yes - Yes + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Copy link to clipboard - Copy link to clipboard + + Equity + Equity - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Change with currency effect Change - Change with currency effect Change + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Performance with currency effect Performance - Performance with currency effect Performance + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Threshold Min - Threshold Min + + Fixed Income + Fixed Income - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Close - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Customize - Customize + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - No auto-renewal. - No auto-renewal. + + Investment: Base Currency + Investment: Base Currency - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - Today - Today + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - This year - This year + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - From the beginning - From the beginning + + Investment + Investment - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - Oops! Invalid currency. - Oops! Invalid currency. + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - This page has been archived. - This page has been archived. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - is Open Source Software - is Open Source Software + + start + start + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 336 - - - is not Open Source Software - is not Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + libs/common/src/lib/routes/routes.ts + 337 - - is Open Source Software - is Open Source Software + + Do you really want to generate a new security token? + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is not Open Source Software - is not Open Source Software + + Generate + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - can be self-hosted - can be self-hosted + + Stocks + Stocks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - cannot be self-hosted - cannot be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/pages/features/features-page.html + 15 - - can be self-hosted - can be self-hosted + + Cryptocurrencies + Cryptocurrencies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/markets/markets.component.ts + 53 + + + apps/client/src/app/pages/features/features-page.html + 51 - - cannot be self-hosted - cannot be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - can be used anonymously - can be used anonymously + + Manage Asset Profile + Manage Asset Profile - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - cannot be used anonymously - cannot be used anonymously + + Alternative Investment + Alternative Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 44 - - can be used anonymously - can be used anonymously + + Collectible + Collectible - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + libs/ui/src/lib/i18n.ts + 54 - - cannot be used anonymously - cannot be used anonymously + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + No results found... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Emerging Markets - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Your net worth is managed by 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europe - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + North America - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Find Ghostfolio on GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Join the Ghostfolio Slack community - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Follow Ghostfolio on X (formerly Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Send an e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Follow Ghostfolio on LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Support Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 2a49abfb3..7065552f1 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -1,7 +1,7 @@ - + Create Account Registrieren @@ -16,16 +16,20 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. Das Ausfallrisiko beim Börsenhandel kann erheblich sein. Es ist nicht ratsam, Geld zu investieren, welches du kurzfristig benötigst. apps/client/src/app/app.component.html - 200 + 221 - + Grantee Empfänger @@ -33,7 +37,7 @@ 11 - + Type Typ @@ -53,7 +57,7 @@ 161 - + Details Details @@ -61,7 +65,7 @@ 33 - + Revoke Widerrufen @@ -74,50 +78,10 @@ Möchtest du diese Zugangsberechtigung wirklich widerrufen? apps/client/src/app/components/access-table/access-table.component.ts - 67 - - - - Activities - Aktivitäten - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + 108 - + Name Name @@ -126,23 +90,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -154,7 +122,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -173,7 +141,7 @@ 88 - + Total Gesamt @@ -181,7 +149,7 @@ 55 - + Value Wert @@ -198,31 +166,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -249,64 +201,56 @@ 102 - + Edit Bearbeiten apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Löschen apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -316,16 +260,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? Möchtest du dieses Konto wirklich löschen? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + 148 - + Delete Jobs Jobs löschen @@ -333,31 +281,7 @@ 151 - - Symbol - Symbol - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 - - - + Data Source Datenquelle @@ -366,18 +290,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Versuche @@ -385,7 +309,7 @@ 83 - + Created Erstellt @@ -393,7 +317,7 @@ 92 - + Finished Abgeschlossen @@ -401,31 +325,39 @@ 101 - + Status Status apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Asset Profiles Anlageprofile - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data Historische Marktdaten apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Daten anzeigen @@ -433,7 +365,7 @@ 166 - + View Stacktrace Stacktrace anzeigen @@ -441,7 +373,7 @@ 173 - + Delete Job Job löschen @@ -449,7 +381,7 @@ 180 - + Details for Details für @@ -457,12 +389,12 @@ 2 - + Date Datum apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -477,127 +409,43 @@ 6 - + Market Price Marktpreis apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Abbrechen - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 - - - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 - - - - Save - Speichern - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 - - - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - + First Activity Erste Aktivität apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + 148 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + 198 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + 214 libs/ui/src/lib/holdings-table/holdings-table.component.html 50 - + Activity Count Anzahl Aktivitäten @@ -605,40 +453,24 @@ 19 - + Historical Data Historische Daten apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + 166 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html 44 - - Please add a currency: - Bitte Währung hinzufügen: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 - - Do you really want to delete this coupon? Möchtest du diesen Gutscheincode wirklich löschen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 - - - - Do you really want to delete this currency? - Möchtest du diese Währung wirklich löschen? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + 194 @@ -646,7 +478,7 @@ Möchtest du den Cache wirklich leeren? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + 231 @@ -654,10 +486,10 @@ Bitte gebe deine Systemmeldung ein: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + 251 - + User Count Anzahl Benutzer @@ -665,7 +497,7 @@ 13 - + per User pro Benutzer @@ -673,112 +505,100 @@ 28 - - Gather Recent Data - Letzte Daten einholen + + Gather Recent Historical Market Data + Letzte historische Marktdaten synchronisieren apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + 226 - - Gather All Data - Alle Daten einholen + + Gather All Historical Market Data + Alle historischen Marktdaten synchronisieren apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + 231 - + Gather Profile Data - Profildaten herunterladen + Profildaten synchronisieren apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + 235 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Exchange Rates - Wechselkurse - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + 44 - + Add Currency Währung hinzufügen apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + System Message Systemmeldung apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Systemmeldung setzen apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Read-only Mode Lese-Modus apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + Coupons Gutscheincodes apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Hinzufügen apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Verwaltung apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Cache leeren apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -786,46 +606,38 @@ Möchtest du diesen Benutzer wirklich löschen? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Benutzer apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + 31 apps/client/src/app/components/header/header.component.html - 229 - - - - Registration - Registrierung - - apps/client/src/app/components/admin-users/admin-users.html - 97 + 231 - + Engagement per Day Engagement pro Tag apps/client/src/app/components/admin-users/admin-users.html - 157 + 158 - + Last Request Letzte Abfrage apps/client/src/app/components/admin-users/admin-users.html - 202 + 204 - + Current Market Mood Aktuelle Marktstimmung @@ -833,399 +645,207 @@ 12 - - Overview - Übersicht + + About Ghostfolio + Über Ghostfolio apps/client/src/app/components/header/header.component.html - 28 + 326 - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Portfolio - Portfolio + + Get Started + Registrieren - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 320 - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/public/public-page.html + 220 - - Accounts - Konten + + Sign in + Einloggen - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/header/header.component.html - 263 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + libs/common/src/lib/routes/routes.ts + 157 + + + Oops! Incorrect Security Token. + Ups! Falsches Sicherheits-Token. - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/components/header/header.component.ts + 274 - - - Admin Control - Administration - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 - - Resources - Ressourcen + + Manage Activities + Aktivitäten verwalten - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Last Days + Letzte Tage - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/markets/markets.html + 17 + + + Security Token + Sicherheits-Token - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - - - Pricing - Preise - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - About - Über + + or + oder - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/pages/landing/landing-page.html + 48 - - - Me - Ich - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/landing/landing-page.html + 451 - - - My Ghostfolio - Mein Ghostfolio - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - - - About Ghostfolio - Über Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Features - Features - - apps/client/src/app/app.component.html - 79 - + + Sign in with Internet Identity + Einloggen mit Internet Identity - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + Einloggen mit Google - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Markets - Märkte + + Stay signed in + Eingeloggt bleiben - apps/client/src/app/app.component.html + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html 61 + + + Time in Market + Zeit im Markt - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + Absolute Brutto Performance - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Absolute Net Performance + Absolute Netto Performance - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 - - Get Started - Registrieren + + Net Performance + Netto Performance - apps/client/src/app/pages/features/features-page.html - 303 - - - apps/client/src/app/pages/public/public-page.html - 220 - - - - Sign in - Einloggen - - apps/client/src/app/app-routing.module.ts - 150 - - - apps/client/src/app/components/header/header.component.ts - 230 - - - - Oops! Incorrect Security Token. - Ups! Falsches Sicherheits-Token. - - apps/client/src/app/components/header/header.component.ts - 245 - - - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 - - - - Manage Activities - Aktivitäten verwalten - - apps/client/src/app/components/home-holdings/home-holdings.html - 63 - - - - Last Days - Letzte Tage - - apps/client/src/app/components/home-market/home-market.html - 7 - - - - Summary - Zusammenfassung - - apps/client/src/app/components/home-summary/home-summary.html - 2 - - - - Security Token - Sicherheits-Token - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 - - - - or - oder - - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 - - - apps/client/src/app/pages/landing/landing-page.html - 47 - - - apps/client/src/app/pages/landing/landing-page.html - 450 - - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 - - - apps/client/src/app/pages/register/register-page.html - 30 - - - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 - - - - Sign in with Internet Identity - Einloggen mit Internet Identity - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 - - - - Sign in with Google - Einloggen mit Google - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 - - - - Stay signed in - Eingeloggt bleiben - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 - - - - Sign in - Einloggen - - apps/client/src/app/components/header/header.component.html - 412 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 - - - - Time in Market - Zeit im Markt - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 - - - - Buy - Kauf - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 - - - - Sell - Verkauf - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 - - - - Investment - Einlage - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - - Absolute Gross Performance - Absolute Brutto Performance - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 - - - - Absolute Net Performance - Absolute Netto Performance - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 - - - - Net Performance - Netto Performance - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 - + Total Assets Gesamtanlagevermögen @@ -1233,76 +853,28 @@ 143 - - Valuables - Wertsachen - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Notfallfonds - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Kaufkraft apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Net Worth Gesamtvermögen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Performance pro Jahr apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividenden - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 @@ -1310,76 +882,76 @@ Bitte setze den Betrag deines Notfallfonds. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + 71 - + Sectors Sektoren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Länder apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Tags Tags apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + Report Data Glitch Datenfehler melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 - + Allocation Allokation + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -1393,19 +965,7 @@ 116 - - Performance - Performance - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 - - - + Show all Alle anzeigen @@ -1417,60 +977,44 @@ Today Heute - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/public/public-page.html + 24 libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1J - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5J - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1478,191 +1022,75 @@ Okay apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About Über Ghostfolio - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Privacy Policy - Datenschutzbestimmungen - - apps/client/src/app/app.component.html - 103 - - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 - - - - Blog - Blog apps/client/src/app/app.component.html - 73 - - - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 - - - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 - - - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 - - - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 - - - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 - - - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 - - - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 - - - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 - - - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 - - - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 - - - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 - - - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 70 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/header/header.component.html + 375 - - - Changelog - Changelog - apps/client/src/app/app.component.html - 77 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/common/src/lib/routes/routes.ts + 220 - - License - Lizenz + + Privacy Policy + Datenschutzbestimmungen apps/client/src/app/app.component.html - 88 + 105 - apps/client/src/app/pages/about/license/license-page.html + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 - - - Privacy Policy - Datenschutzbestimmungen - - apps/client/src/app/pages/about/about-page.component.ts - 62 - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 209 My Ghostfolio Mein Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 - - Please enter your coupon code: - Bitte gebe deinen Gutscheincode ein: + + Please enter your coupon code. + Bitte gebe deinen Gutscheincode ein. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1670,7 +1098,7 @@ Gutscheincode konnte nicht eingelöst werden apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1678,7 +1106,7 @@ Gutscheincode wurde eingelöst apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1686,7 +1114,7 @@ Neu laden apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1694,114 +1122,94 @@ Möchtest du diese Anmeldemethode wirklich löschen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Konto - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Mitgliedschaft - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year pro Jahr apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Premium ausprobieren apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Gutschein einlösen apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Präsentationsansicht apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Basiswährung apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Locale Lokalität + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Datums- und Zahlenformat apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Zen Mode Zen Modus apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Sign in with fingerprint Einloggen mit Fingerabdruck apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + User ID Benutzer ID @@ -1810,18 +1218,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Gewährte Zugangsberechtigung apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Zugang gewähren @@ -1829,7 +1237,7 @@ 7 - + Public Öffentlich @@ -1841,35 +1249,51 @@ Accounts Konten - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - Update account - Konto aktualisieren - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/components/admin-users/admin-users.html + 115 - - - Add account - Konto hinzufügen - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/components/header/header.component.html + 58 + + + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 - - Cash - Bargeld + + Update account + Konto aktualisieren - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 + + + + Add account + Konto hinzufügen + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - + Currency Währung @@ -1878,11 +1302,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1894,14 +1318,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Cash-Bestand @@ -1917,7 +1341,7 @@ 34 - + Platform Plattform @@ -1933,7 +1357,7 @@ 48 - + Account ID Konto ID @@ -1945,16 +1369,116 @@ Admin Control Administration - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 + + + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 Blog Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 + + + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 + + + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 + + + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 + + + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 + + + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 + + + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 + + + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 + + + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 + + + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 + + + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 + + + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 + + + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 + + + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 + + + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 + + + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 + + + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 + + + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 @@ -1969,91 +1493,135 @@ Frequently Asked Questions (FAQ) Häufig gestellte Fragen (FAQ) - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Features - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Overview Übersicht - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 Markets Märkte - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 - - - Allocations - Allokationen - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 - + Allocations Allokationen apps/client/src/app/pages/portfolio/allocations/allocations-page.html 4 + + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 133 + - + By Account Nach Konto @@ -2061,7 +1629,7 @@ 286 - + By Currency Nach Währung @@ -2069,7 +1637,7 @@ 63 - + By Asset Class Nach Anlageklasse @@ -2077,7 +1645,7 @@ 85 - + By Holding Nach Position @@ -2085,7 +1653,7 @@ 107 - + By Sector Nach Sektor @@ -2093,7 +1661,7 @@ 130 - + By Continent Nach Kontinent @@ -2101,7 +1669,7 @@ 153 - + By Country Nach Land @@ -2109,7 +1677,7 @@ 264 - + Regions Regionen @@ -2122,50 +1690,42 @@ - Analysis - Analyse - - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 - - - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 - - - Analysis Analyse apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 + + libs/common/src/lib/routes/routes.ts + 138 + - + Investment Timeline Zeitstrahl der Investitionen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + Top Gewinner apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom Verlierer apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + FIRE FIRE @@ -2173,7 +1733,7 @@ 4 - + Calculator Rechner @@ -2181,7 +1741,7 @@ 7 - + 4% Rule 4% Regel @@ -2190,26 +1750,6 @@ - Holdings - Positionen - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - Holdings Positionen @@ -2225,24 +1765,36 @@ 70 - libs/ui/src/lib/assistant/assistant.html - 46 + libs/common/src/lib/routes/routes.ts + 90 - - - Update activity + + libs/common/src/lib/routes/routes.ts + 167 + + + + Holdings + Positionen + + libs/ui/src/lib/assistant/assistant.html + 82 + + + + Update activity Aktivität bearbeiten apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 10 - + Add activity Aktivität hinzufügen apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2252,77 +1804,69 @@ Sell Verkauf + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Name, Symbol oder ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 124 - + Quantity Anzahl apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Unit Price Stückpreis apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 214 libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Fee - Gebühr - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 234 - - - + Note Kommentar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2330,47 +1874,51 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 275 - - Asset Class - Anlageklasse + + Activities + Aktivitäten - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + 207 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/admin-users/admin-users.html + 136 - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Activities - Aktivitäten - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 @@ -2378,7 +1926,7 @@ Daten importieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2386,42 +1934,66 @@ Der Import wurde abgeschlossen apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 Pricing Preise + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 + Portfolio Portfolio apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + 124 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + 92 - - - Currencies - Währungen - apps/client/src/app/pages/public/public-page.html - 88 + libs/common/src/lib/routes/routes.ts + 151 - + Continents Kontinente @@ -2429,23 +2001,27 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. Ghostfolio verschafft dir den Überblick über dein Vermögen. apps/client/src/app/pages/public/public-page.html - 215 + 216 Registration Registrierung - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Continue with Internet Identity Weiter mit Internet Identity @@ -2453,7 +2029,7 @@ 42 - + Continue with Google Weiter mit Google @@ -2461,39 +2037,39 @@ 53 - + Copy to clipboard In die Zwischenablage kopieren apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Ich stimme zu, meinen Security Token an einem sicheren Ort hinterlegt zu haben. Sollte ich diesen verlieren, kann ich mein Konto nicht wiederherstellen. + + Resources + Ressourcen - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Zustimmen und fortfahren - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Ressourcen - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Ups, die Authentifizierung ist fehlgeschlagen. @@ -2501,7 +2077,7 @@ 19 - + Try again Nochmals versuchen @@ -2509,15 +2085,15 @@ 27 - + Go back to Home Page Zurück zur Startseite apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 - + Draft Geplant @@ -2530,10 +2106,18 @@ Aktivitäten importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Aktivitäten exportieren @@ -2545,7 +2129,7 @@ 396 - + Export Drafts as ICS Geplante Aktivitäten als ICS exportieren @@ -2557,7 +2141,7 @@ 409 - + Clone Kopieren @@ -2565,7 +2149,7 @@ 436 - + Export Draft as ICS Geplante Aktivität als ICS exportieren @@ -2578,34 +2162,26 @@ Möchtest du diese Aktivität wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Index - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High Änderung vom Allzeithoch libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH vom AZH libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Jahreszinssatz @@ -2613,7 +2189,7 @@ 21 - + Time to add your first activity. Erste Aktivität jetzt hinzufügen. @@ -2621,20 +2197,20 @@ 12 - + Language Sprache apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + 56 - + Get started Registrieren apps/client/src/app/components/header/header.component.html - 422 + 432 @@ -2642,7 +2218,7 @@ Diese Funktion ist derzeit nicht verfügbar. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -2650,15 +2226,15 @@ Bitte versuche es später noch einmal. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + 186 @@ -2666,98 +2242,58 @@ Ups! Es ist etwas schief gelaufen. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 - - - - Change - Änderung - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 - - - - Average Unit Price - Ø Preis pro Einheit - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + 184 - + Minimum Price Minimum Preis apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Maximum Price Maximum Preis apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 - - - - Asset Sub Class - Anlageunterklasse - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 143 - + Sector Sektor apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + 242 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + 263 - + Country Land apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Developed Markets Entwickelte Länder @@ -2769,7 +2305,7 @@ 160 - + Emerging Markets Schwellenländer @@ -2781,7 +2317,7 @@ 169 - + Other Markets Übrige Länder @@ -2793,12 +2329,12 @@ 178 - + Projected Total Amount Projizierter Gesamtbetrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2806,7 +2342,7 @@ Monatlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + 88 @@ -2814,15 +2350,19 @@ Einlage libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 Interest Verzinsung + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + 370 libs/ui/src/lib/i18n.ts @@ -2834,23 +2374,23 @@ Ersparnisse libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 - + Countries Count Anzahl Länder apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + 184 - + Sectors Count Anzahl Sektoren apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + 175 @@ -2858,11 +2398,15 @@ Angst apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -2870,11 +2414,15 @@ Gier apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 @@ -2882,10 +2430,10 @@ Filtern nach... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + 379 - + Alias Alias @@ -2897,23 +2445,23 @@ 11 - - Hello, has shared a Portfolio with you! - Hallo, hat ein Portfolio mit dir geteilt! + + Hello, has shared a Portfolio with you! + Hallo, hat ein Portfolio mit dir geteilt! apps/client/src/app/pages/public/public-page.html - 4 + 5 - + Experimental Features Experimentelle Funktionen apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 - + Compare with... Vergleichen mit... @@ -2924,12 +2472,16 @@ Benchmark Benchmark + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + 136 - + Proportion of Net Worth Anteil am Gesamtvermögen @@ -2937,12 +2489,12 @@ 12 - + Excluded from Analysis Von der Analyse ausgenommen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 @@ -2950,39 +2502,35 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 - - - Appearance - Aussehen apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + 172 - - Auto - Automatisch + + Appearance + Aussehen apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Hell apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Dunkel apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 @@ -2990,15 +2538,15 @@ Gesamtbetrag apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 - + Portfolio Evolution Portfolio Wertentwicklung apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 @@ -3006,12 +2554,24 @@ Sparrate apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 Account Konto + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3020,6 +2580,30 @@ Asset Class Anlageklasse + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3028,6 +2612,26 @@ Symbol Symbol + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3036,6 +2640,10 @@ Tag Tag + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3044,9 +2652,13 @@ Cash Bargeld + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3060,6 +2672,10 @@ Equity Beteiligungskapital + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + libs/ui/src/lib/i18n.ts 46 @@ -3094,7 +2710,7 @@ Kryptowährung libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3102,7 +2718,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3110,7 +2726,7 @@ Investmentfonds libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3118,7 +2734,7 @@ Edelmetall libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3126,7 +2742,7 @@ Privates Beteiligungskapital libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3134,12 +2750,24 @@ Aktie libs/ui/src/lib/i18n.ts - 58 + 60 Emergency Fund Notfallfonds + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3154,19 +2782,35 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 No data available Keine Daten verfügbar + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 @@ -3174,7 +2818,7 @@ Nordamerika libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3182,7 +2826,7 @@ Afrika libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3190,7 +2834,7 @@ Asien libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3198,7 +2842,7 @@ Europa libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3206,7 +2850,7 @@ Ozeanien libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3214,10 +2858,10 @@ Südamerika libs/ui/src/lib/i18n.ts - 70 + 72 - + The following file formats are supported: Folgende Dateiformate werden unterstützt: @@ -3225,7 +2869,7 @@ 90 - + Back Zurück @@ -3237,92 +2881,60 @@ 178 - - Community - Community - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 - - - + Activities Count Anzahl Aktivitäten apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + 157 - + Refresh Aktualisieren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + 17 - + Symbol Mapping Symbol Zuordnung apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 - + Dividend Timeline Zeitstrahl der Dividenden apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 Dividend Dividenden + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts @@ -3332,17 +2944,37 @@ Asset Sub Class Anlageunterklasse + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + libs/ui/src/lib/i18n.ts 7 - + User Signup Benutzer Registrierung apps/client/src/app/components/admin-overview/admin-overview.html - 111 + 34 @@ -3350,10 +2982,10 @@ Daten validieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + Import Importieren @@ -3366,46 +2998,42 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Market Data Marktdaten - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Users Benutzer - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 61 Summary Zusammenfassung - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 - + Holding Position @@ -3414,10 +3042,10 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Dividenden laden @@ -3430,7 +3058,7 @@ Jährlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3438,15 +3066,23 @@ Dividenden importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Gültig bis apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3501,39 +3137,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values Ausblenden von sensiblen Informationen wie absoluter Performance und Stückzahl apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times Unbeschwertes Erlebnis für turbulente Zeiten apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality Vorschau auf kommende Funktionalität apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? Bist du ein ambitionierter Investor, der den kompletten Überblick benötigt? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Portfolio Zusammenfassung @@ -3542,14 +3178,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Performance Benchmarks @@ -3558,14 +3194,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator FIRE Rechner @@ -3574,14 +3210,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... und weitere Features... @@ -3590,175 +3226,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Überspringen apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Abonnement abschliessen apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Für technisch versierte Anleger, die Ghostfolio auf der eigenen Infrastruktur betreiben möchten. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Unlimitierte Transaktionen apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Unlimitierte Accounts apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Portfolio Performance apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Selbst gehostet, manuelles Update. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Kostenlos apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Für Einsteiger, die gerade mit dem Börsenhandel beginnen. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Vollständig verwaltetes Ghostfolio Cloud-Angebot. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Für ambitionierte Anleger, die den vollständigen Überblick über ihr Anlagevermögen benötigen. apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Einmalige Zahlung, keine automatische Erneuerung. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Jetzt loslegen apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - + It’s free. Es ist kostenlos. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 353 - + Fees Gebühren apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3766,10 +3418,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Portfolio Allokationen @@ -3782,14 +3434,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Sparrate pro Monat @@ -3797,20 +3449,20 @@ 10 - + Data Import and Export Datenimport und -export apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3821,20 +3473,20 @@ 13 - + Community Support Community Support apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support E-Mail und Chat Support apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3853,7 +3505,7 @@ 14 - + Market data provided by Marktdaten bereitgestellt von @@ -3861,15 +3513,7 @@ 2 - - Oops! Could not get the historical exchange rate from - Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - + Retirement Date Pensionierungsdatum @@ -3877,15 +3521,15 @@ 32 - - Gather Historical Data - Historische Daten herunterladen + + Gather Historical Market Data + Historische Marktdaten synchronisieren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + 29 - + Professional Data Provider Professioneller Datenanbieter @@ -3894,10 +3538,10 @@ apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans Preispläne @@ -3905,7 +3549,7 @@ 4 - + Renew Plan Abonnement erneuern @@ -3914,35 +3558,35 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Unser offizielles Ghostfolio Premium Cloud-Angebot ist der einfachste Weg für den Einstieg. Aufgrund der Zeitersparnis ist dies die beste Option für die meisten Nutzer. Die Einnahmen werden zur Deckung der Betriebskosten und zur Finanzierung der Weiterentwicklung verwendet. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Unser offizielles Ghostfolio Premium Cloud-Angebot ist der einfachste Weg für den Einstieg. Aufgrund der Zeitersparnis ist dies die beste Option für die meisten Nutzer. Die Einnahmen werden zur Deckung der Betriebskosten für Hosting und professionelle Datenanbieter sowie zur Finanzierung der Weiterentwicklung verwendet. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User Benutzer verwenden apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User Benutzer löschen apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 @@ -3950,10 +3594,10 @@ Möchtest du diese Aktivitäten wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider Nach ETF-Anbieter @@ -3961,7 +3605,7 @@ 306 - + Update platform Plattform bearbeiten @@ -3969,7 +3613,7 @@ 8 - + Add platform Plattform hinzufügen @@ -3977,16 +3621,20 @@ 10 - + Url Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3998,18 +3646,18 @@ Möchtest du diese Plattform wirklich löschen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms Plattformen apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance Cash-Bestand aktualisieren @@ -4017,7 +3665,7 @@ 112 - + By Platform Nach Plattform @@ -4025,56 +3673,44 @@ 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: Wechsle noch heute zu Ghostfolio Premium und erhalte Zugang zu exklusiven Funktionen, die das Investieren erleichtern: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. Nutze die Werkzeuge, um deine Finanzen effektiv zu verwalten und deine persönliche Anlagestrategie zu verfeinern. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform Plattform hinzufügen apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings Einstellungen - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Beteiligungskapital - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 @@ -4085,7 +3721,7 @@ 19 - + Manage Benchmarks Benchmarks verwalten @@ -4093,7 +3729,7 @@ 35 - + Select Holding Position auswählen @@ -4101,7 +3737,7 @@ 20 - + Select File Datei auswählen @@ -4109,7 +3745,7 @@ 22 - + Select Dividends Dividenden auswählen @@ -4117,7 +3753,7 @@ 113 - + Select Activities Aktivitäten auswählen @@ -4125,64 +3761,36 @@ 115 - - Import Activities - Aktivitäten importieren - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Dividenden importieren - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Private Finanzen + + Frequently Asked Questions (FAQ) + Häufig gestellte Fragen (FAQ) - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Häufig gestellte Fragen (FAQ) - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak Aktueller Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak Längster Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 @@ -4217,12 +3825,12 @@ 30 - + Liabilities Verbindlichkeiten apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4233,35 +3841,35 @@ Changelog Changelog - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License Lizenz - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Aktien - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs ETFs @@ -4269,7 +3877,7 @@ 25 - + Bonds Anleihen @@ -4277,15 +3885,7 @@ 38 - - Cryptocurrencies - Kryptowährungen - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items Wertsachen @@ -4293,15 +3893,15 @@ 76 - + Import and Export Import und Export apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts Unterstützung mehrerer Konten @@ -4309,7 +3909,7 @@ 127 - + Portfolio Calculations Portfolio Berechnungen @@ -4317,44 +3917,44 @@ 141 - + Dark Mode Dark Mode apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood Marktstimmung apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis Statische Analyse apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language Mehrsprachigkeit apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software Open Source Software apps/client/src/app/pages/features/features-page.html - 278 + 295 @@ -4365,15 +3965,15 @@ 40 - + Scraper Configuration Scraper Konfiguration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile Anlageprofil hinzufügen @@ -4385,19 +3985,23 @@ Personal Finance Tools Tools für persönliche Finanzen - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Entdecke Open Source Alternativen für Personal Finance Tools apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Gegründet @@ -4405,7 +4009,7 @@ 77 - + Origin Ursprung @@ -4413,7 +4017,7 @@ 82 - + Region Region @@ -4421,15 +4025,15 @@ 87 - + Available in Verfügbar in apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Ja @@ -4465,7 +4069,7 @@ 274 - + ❌ No ❌ Nein @@ -4501,31 +4105,31 @@ 281 - + Self-Hosting Self-Hosting apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Anonyme Nutzung apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Kostenlose Nutzung apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Hinweise @@ -4533,39 +4137,15 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Mit Ghostfolio kannst du dein Vermögen einfach überwachen, analysieren und visualisieren. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Tools für persönliche Finanzen - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Ratgeber - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 - - - - Glossary - Lexikon - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + 329 - + Stocks, ETFs, bonds, cryptocurrencies, commodities Aktien, ETFs, Anleihen, Kryptowährungen, Rohstoffe @@ -4577,7 +4157,7 @@ 65 - + Mortgages, personal loans, credit cards Hypotheken, Darlehen, Kreditkarten @@ -4585,7 +4165,7 @@ 57 - + Luxury items, real estate, private companies Luxusartikel, Immobilien, private Unternehmen @@ -4596,6 +4176,10 @@ Buy Kauf + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4614,7 +4198,7 @@ ETFs ohne Länder apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 @@ -4622,15 +4206,15 @@ ETFs ohne Sektoren apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets Anlagevermögen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 @@ -4641,7 +4225,7 @@ 25 - + By Market Nach Markt @@ -4662,118 +4246,98 @@ Japan libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio Herzlich willkommen bei Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts Konten einrichten apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. Verschaffe dir einen umfassenden Überblick, indem du deine Bank- und Wertpapierkonten hinzufügst. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities Aktivitäten erfassen apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. Erfasse deine Investitionsaktivitäten, um dein Portfolio auf dem neuesten Stand zu halten. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio Portfolio überwachen und analysieren apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. Verfolge die Entwicklung in Echtzeit mit umfassenden Analysen und Einblicken. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - Keine Daten verfügbar - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? Bist du bereit, die Kontrolle über deine Finanzen zu übernehmen? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts Konten einrichten apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication Biometrische Authentifizierung apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. Bei Ghostfolio gehört Transparenz zum zentralen Inhalt unserer Grundwerte. Wir publizieren den Quellcode als Open-Source-Software (OSS) unter der AGPL-3.0-Lizenz und veröffentlichen aggregierte Kennzahlen über den Betriebsstatus der Plattform. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users Aktive Nutzer @@ -4785,7 +4349,7 @@ 62 - + New Users Neue Nutzer @@ -4793,7 +4357,7 @@ 51 - + Users in Slack community Nutzer in der Slack Community @@ -4801,7 +4365,7 @@ 75 - + Contributors on GitHub Contributors auf GitHub @@ -4809,7 +4373,7 @@ 89 - + Stars on GitHub Sterne auf GitHub @@ -4821,7 +4385,7 @@ 103 - + Pulls on Docker Hub Downloads auf Docker Hub @@ -4833,7 +4397,7 @@ 117 - + Uptime Verfügbarkeit @@ -4841,12 +4405,12 @@ 132 - + Export Data Daten exportieren apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 @@ -4854,10 +4418,14 @@ Währungen apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 - + Our Unsere @@ -4865,7 +4433,7 @@ 6 - + Visit Besuche @@ -4873,7 +4441,7 @@ 28 - + Discover other exciting Open Source Software projects Entdecke weitere interessante Open Source Software Projekte @@ -4881,31 +4449,15 @@ 9 - - Frequently Asked Questions (FAQ) - Häufig gestellte Fragen (FAQ) - - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 - - - apps/client/src/app/pages/faq/saas/saas-page.html - 4 - - - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 - - - + Check out the numerous features of Ghostfolio to manage your wealth Entdecke die zahlreichen Funktionen von Ghostfolio zur Vermögensverwaltung apps/client/src/app/pages/features/features-page.html - 6 + 7 - + Discover the latest Ghostfolio updates and insights on personal finance Entdecke die neuesten Ghostfolio Updates und Beiträge zu persönlichen Finanzen @@ -4913,43 +4465,31 @@ 7 - + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. Wenn du Ghostfolio lieber auf deiner eigenen Infrastruktur betreiben möchtest, findest du den Quellcode und weitere Informationen auf GitHub. apps/client/src/app/pages/pricing/pricing-page.html - 26 + 14 - + Manage your wealth like a boss Verwalte dein Vermögen wie ein Profi apps/client/src/app/pages/landing/landing-page.html - 5 + 6 - + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio ist ein Open Source Dashboard für deine persönlichen Finanzen mit Fokus auf Datenschutz. Analysiere deine Vermögensverteilung, ermittle dein Nettovermögen und treffe fundierte, datengestützte Investitionsentscheidungen. - - apps/client/src/app/pages/landing/landing-page.html - 9 - - - - Get Started - Jetzt loslegen + Ghostfolio ist ein Open Source Dashboard für deine persönlichen Finanzen mit Fokus auf Datenschutz. Analysiere deine Vermögensverteilung, ermittle dein Gesamtvermögen und treffe fundierte, datengestützte Investitionsentscheidungen. apps/client/src/app/pages/landing/landing-page.html - 41 - - - apps/client/src/app/pages/pricing/pricing-page.html - 324 + 10 - + Monthly Active Users Monatlich aktive Nutzer @@ -4957,7 +4497,7 @@ 70 - + As seen in Bekannt aus @@ -4965,23 +4505,23 @@ 115 - + Protect your assets. Refine your personal investment strategy. Schütze dein Vermögen. Optimiere deine persönliche Anlagestrategie. apps/client/src/app/pages/landing/landing-page.html - 225 + 226 - + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. Ghostfolio ermöglicht es geschäftigen Leuten, den Überblick über Aktien, ETFs oder Kryptowährungen zu behalten, ohne überwacht zu werden. apps/client/src/app/pages/landing/landing-page.html - 229 + 230 - + 360° View 360° Ansicht @@ -4989,7 +4529,7 @@ 240 - + Web3 Ready Web3 ready @@ -4997,31 +4537,23 @@ 251 - + Use Ghostfolio anonymously and own your financial data. Nutze Ghostfolio ganz anonym und behalte deine Finanzdaten. apps/client/src/app/pages/landing/landing-page.html - 253 - - - - Open Source - Open Source - - apps/client/src/app/pages/landing/landing-page.html - 261 + 254 - + Benefit from continuous improvements through a strong community. Profitiere von kontinuierlichen Verbesserungen durch eine aktive Community. apps/client/src/app/pages/landing/landing-page.html - 263 + 264 - + Why Ghostfolio? Warum Ghostfolio? @@ -5029,15 +4561,15 @@ 272 - + Ghostfolio is for you if you are... Ghostfolio ist für dich geeignet, wenn du... apps/client/src/app/pages/landing/landing-page.html - 273 + 274 - + trading stocks, ETFs or cryptocurrencies on multiple platforms Aktien, ETFs oder Kryptowährungen auf unterschiedlichen Plattformen handelst @@ -5045,7 +4577,7 @@ 280 - + pursuing a buy & hold strategy eine Buy & Hold Strategie verfolgst @@ -5053,7 +4585,7 @@ 286 - + interested in getting insights of your portfolio composition dich für die Zusammensetzung deines Portfolios interessierst @@ -5061,7 +4593,7 @@ 291 - + valuing privacy and data ownership Privatsphäre und Datenhoheit wertschätzt @@ -5069,7 +4601,7 @@ 296 - + into minimalism zum Frugalismus oder Minimalismus neigst @@ -5077,7 +4609,7 @@ 299 - + caring about diversifying your financial resources dich um die Diversifizierung deiner finanziellen Mittel kümmerst @@ -5085,7 +4617,7 @@ 303 - + interested in financial independence Interesse an finanzieller Freiheit hast @@ -5093,7 +4625,7 @@ 307 - + saying no to spreadsheets in Nein sagst zu Excel-Tabellen im Jahr @@ -5101,7 +4633,7 @@ 311 - + still reading this list diese Liste bis zum Ende liest @@ -5109,7 +4641,7 @@ 314 - + Learn more about Ghostfolio Erfahre mehr über Ghostfolio @@ -5117,31 +4649,31 @@ 319 - + What our users are saying Was unsere Nutzer sagen apps/client/src/app/pages/landing/landing-page.html - 327 + 328 - + Members from around the globe are using Ghostfolio Premium Nutzer aus aller Welt verwenden Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 366 + 367 - + How does Ghostfolio work? Wie funktioniert Ghostfolio ? apps/client/src/app/pages/landing/landing-page.html - 383 + 384 - + Sign up anonymously* Registriere dich anonym* @@ -5149,7 +4681,7 @@ 392 - + * no e-mail address nor credit card required * Keine E-Mail-Adresse oder Kreditkarte erforderlich @@ -5157,51 +4689,39 @@ 394 - + Add any of your historical transactions Füge historische Transaktionen hinzu apps/client/src/app/pages/landing/landing-page.html - 405 + 406 - + Get valuable insights of your portfolio composition Erhalte nützliche Erkenntnisse über die Zusammensetzung deines Portfolios apps/client/src/app/pages/landing/landing-page.html - 417 + 418 - + Are you ready? Bist du bereit? apps/client/src/app/pages/landing/landing-page.html - 431 - - - - Live Demo - Live Demo - - apps/client/src/app/pages/landing/landing-page.html - 49 - - - apps/client/src/app/pages/landing/landing-page.html - 451 + 432 - + Get the full picture of your personal finances across multiple platforms. Verschaffe dir einen vollständigen Überblick deiner persönlichen Finanzen über mehrere Plattformen hinweg. apps/client/src/app/pages/landing/landing-page.html - 242 + 243 - + Get started in only 3 steps Beginne mit nur 3 Schritten @@ -5209,2427 +4729,3406 @@ 386 - + faq haeufig-gestellte-fragen - snake-case - - apps/client/src/app/app.component.ts - 77 - - - apps/client/src/app/core/paths.ts - 3 - - - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 - + kebab-case - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 245 - + features features - snake-case + kebab-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 255 + + + about + ueber-uns + kebab-case - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/core/paths.ts - 4 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 214 + + + privacy-policy + datenschutzbestimmungen + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 207 + + + license + lizenz + kebab-case - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 191 - - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + + + markets + maerkte + kebab-case + + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + libs/common/src/lib/routes/routes.ts + 260 + + + + pricing + preise + kebab-case + + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 270 - - about - ueber-uns - snake-case + + register + registrierung + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + ressourcen + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 322 + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Diese Übersichtsseite zeigt eine Auswahl an Tools zur Verwaltung der persönliche Finanzen im Vergleich zur Open Source Alternative Ghostfolio. Wenn du Wert auf Transparenz, Datenschutz und die gemeinschaftliche Zusammenarbeit der Open Source Community legst, bietet dir Ghostfolio eine ausgezeichnete Möglichkeit, die Kontrolle über dein Finanzmanagement zu übernehmen. - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Über die Links unten kannst du eine Reihe an Tools mit Ghostfolio vergleichen. - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + Open Source Alternative to + Open Source Alternative zu - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + The Open Source Alternative to + Die Open Source Alternative zu - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Suchst du nach einer Open Source Alternative zu ? Ghostfolio ist ein leistungsstarkes Portfolio Management Tool, das Privatpersonen eine umfassende Plattform bietet, um ihre Investitionen zu verfolgen, zu analysieren und zu optimieren. Egal, ob du ein erfahrener Investor bist oder gerade erst anfängst, Ghostfolio bietet eine intuitive Benutzeroberfläche und eine Vielzahl an Funktionen, die dir dabei helfen, fundierte Entscheidungen zu treffen und die Kontrolle über deine finanzielle Zukunft zu übernehmen. - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio ist eine Open Source Software (OSS), die eine kostengünstige Alternative zu darstellt und sich besonders für Personen mit knappem Budget eignet, wie z.B. für diejenigen, die finanzielle Unabhängigkeit und einen frühen Ruhestand anstreben (FIRE). Ghostfolio nutzt die gemeinsamen Aktivitäten einer Community von Entwicklern und Finanzenthusiasten, um seine Funktionalität, Sicherheit und Benutzerfreundlichkeit kontinuierlich zu verbessern. - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Wir möchten uns in der untenstehenden Ghostfolio vs Vergleichstabelle ein detailliertes Bild davon machen, wie Ghostfolio im Vergleich zu positioniert ist. Wir werden dabei verschiedene Aspekte wie Funktionen, Datenschutz, Preise und weiteres untersuchen, damit du eine gut informierte Entscheidung für deine persönlichen Anforderungen treffen kannst. - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + open-source-alternative-to + open-source-alternative-zu + kebab-case - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 324 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Bitte beachte, dass die bereitgestellten Ghostfolio vs Informationen auf unserer unabhängigen Recherche und Analyse beruhen. Diese Webseite steht in keiner Verbindung zu oder einem anderen im Vergleich erwähnten Produkt. Da sich die Landschaft der Personal Finance Tools ständig weiterentwickelt, ist es wichtig, alle spezifischen Details oder Änderungen direkt auf der jeweiligen Produktseite zu überprüfen. Brauchen die Daten eine Auffrischung? Unterstütze uns bei der Pflege der aktuellen Daten auf GitHub. - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 + + + Ready to take your investments to the next level? + Bereit, deine Investitionen auf ein neues Levelzu bringen? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Switzerland + Schweiz apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + 57 - - - privacy-policy - datenschutzbestimmungen - snake-case - apps/client/src/app/app.component.ts - 75 + libs/ui/src/lib/i18n.ts + 96 + + + Global + Weltweit - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/ui/src/lib/i18n.ts + 16 - - license - lizenz - snake-case + + (Last 24 hours) + (Letzte 24 Stunden) - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/open/open-page.html + 37 + + + (Last 30 days) + (Letzte 30 Tage) - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/open/open-page.html + 59 - - markets - maerkte - snake-case + + (Last 90 days) + (Letzte 90 Tage) - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/pages/open/open-page.html + 127 + + + Choose or drop a file here + Wähle eine Datei aus oder ziehe sie hierhin - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + You are using the Live Demo. + Du verwendest die Live Demo. - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/app.component.html + 12 + + + One-time fee, annual account fees + Einmalige Eröffnungsgebühr, jährliche Kontoführungsgebühren - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 + + + Distribution of corporate earnings + Ausschüttung von Unternehmensgewinnen - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Fee + Gebühr - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + libs/ui/src/lib/i18n.ts + 37 + + + Revenue for lending out money + Ertrag für das Ausleihen von Geld - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 - - pricing - preise - snake-case + + Add Tag + Tag hinzufügen - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + Do you really want to delete this tag? + Möchtest du diesen Tag wirklich löschen? - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Tag bearbeiten - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Tag hinzufügen - apps/client/src/app/components/header/header.component.ts - 89 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Currency Cluster Risks + Währungsklumpenrisiken - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + Account Cluster Risks + Kontoklumpenrisiken - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Transfer Cash Balance + Cash-Bestand Transfer - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html 7 + + + Version + Version - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + From + Von - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + To + Nach - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 - - - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + Transfer + Transferieren - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + Membership + Mitgliedschaft - libs/ui/src/lib/membership-card/membership-card.component.ts + libs/common/src/lib/routes/routes.ts 31 - - - register - registrierung - snake-case - apps/client/src/app/app.component.ts - 81 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Zugang - apps/client/src/app/components/header/header.component.ts - 90 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Anlageprofil - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Do you really want to delete this asset profile? + Möchtest du dieses Anlageprofil wirklich löschen? - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Suche - apps/client/src/app/pages/faq/saas/saas-page.component.ts + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 16 + + + Add Manually + Manuell hinzufügen - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Mit dem Finanz-Dashboard Ghostfolio kannst du dein Vermögen in Cash, Aktien, ETFs und Kryptowährungen über mehrere Finanzinstitute überwachen. - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Letztes Allzeithoch - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - resources - ressourcen - snake-case + + User + Benutzer - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs Vergleichstabelle - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + Open Source Wealth Management Software + Open Source Software für die Vermögensverwaltung - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + aktie, app, asset, dashboard, etf, finanzen, kryptowährung, management, performance, portfolio, software, trading, vermögen, web3 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/i18n/i18n-page.html 10 + + + Oops, cash balance transfer has failed. + Ups, der Cash-Bestand Transfer ist fehlgeschlagen. - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Extreme Angst - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Extreme Gier - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Neutral - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + Ups! Die historischen Daten konnten nicht geparsed werden. - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + Möchtest du diese Systemmeldung wirklich löschen? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + 50 Tage Trend - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + 200 Tage Trend - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + Cash Balances + Cash-Bestände - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + Starting from + Ab - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Diese Übersichtsseite zeigt eine Auswahl an Tools zur Verwaltung der persönliche Finanzen im Vergleich zur Open Source Alternative Ghostfolio. Wenn du Wert auf Transparenz, Datenschutz und die gemeinschaftliche Zusammenarbeit der Open Source Community legst, bietet dir Ghostfolio eine ausgezeichnete Möglichkeit, die Kontrolle über dein Finanzmanagement zu übernehmen. + + Do you really want to delete this account balance? + Möchtest du diesen Cash-Bestand wirklich löschen? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Über die Links unten kannst du eine Reihe an Tools mit Ghostfolio vergleichen. + + If a translation is missing, kindly support us in extending it here. + Wenn eine Übersetzung fehlt, unterstütze uns bitte dabei, sie hier zu ergänzen. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Open Source Alternative to - Open Source Alternative zu + + The current market price is + Der aktuelle Marktpreis ist - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Open Source Alternative to - Open Source Alternative zu + + Test + Test - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - The Open Source Alternative to - Die Open Source Alternative zu + + Date Range + Zeitraum - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + libs/ui/src/lib/assistant/assistant.html + 143 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Suchst du nach einer Open Source Alternative zu ? Ghostfolio ist ein leistungsstarkes Portfolio Management Tool, das Privatpersonen eine umfassende Plattform bietet, um ihre Investitionen zu verfolgen, zu analysieren und zu optimieren. Egal, ob du ein erfahrener Investor bist oder gerade erst anfängst, Ghostfolio bietet eine intuitive Benutzeroberfläche und eine Vielzahl an Funktionen, die dir dabei helfen, fundierte Entscheidungen zu treffen und die Kontrolle über deine finanzielle Zukunft zu übernehmen. + + Permission + Rechte - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/access-table/access-table.component.html 18 - - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio ist eine Open Source Software (OSS), die eine kostengünstige Alternative zu darstellt und sich besonders für Personen mit knappem Budget eignet, wie z.B. für diejenigen, die finanzielle Unabhängigkeit und einen frühen Ruhestand anstreben (FIRE). Ghostfolio nutzt die gemeinsamen Aktivitäten einer Community von Entwicklern und Finanzenthusiasten, um seine Funktionalität, Sicherheit und Benutzerfreundlichkeit kontinuierlich zu verbessern. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html 32 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Wir möchten uns in der untenstehenden Ghostfolio vs Vergleichstabelle ein detailliertes Bild davon machen, wie Ghostfolio im Vergleich zu positioniert ist. Wir werden dabei verschiedene Aspekte wie Funktionen, Datenschutz, Preise und weiteres untersuchen, damit du eine gut informierte Entscheidung für deine persönlichen Anforderungen treffen kannst. - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 - - - - open-source-alternative-to - open-source-alternative-zu + + Restricted view + Eingeschränkte Ansicht - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts + apps/client/src/app/components/access-table/access-table.component.html 26 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Bitte beachte, dass die bereitgestellten Ghostfolio vs Informationen auf unserer unabhängigen Recherche und Analyse beruhen. Diese Webseite steht in keiner Verbindung zu oder einem anderen im Vergleich erwähnten Produkt. Da sich die Landschaft der Personal Finance Tools ständig weiterentwickelt, ist es wichtig, alle spezifischen Details oder Änderungen direkt auf der jeweiligen Produktseite zu überprüfen. Brauchen die Daten eine Auffrischung? Unterstütze uns bei der Pflege der aktuellen Daten auf GitHub. + + Oops! Could not grant access. + Ups! Der Zugang konnte nicht gewährt werden. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 - - Ready to take your investments to the next level? - Bereit, deine Investitionen auf ein neues Levelzu bringen? + + Private + Privat - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - Get Started - Jetzt loslegen + + Job Queue + Job Warteschlange - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + libs/common/src/lib/routes/routes.ts + 46 + + + + Market data is delayed for + Die Marktdaten sind verzögert für + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Investment + Investition + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + + Absolute Asset Performance + Absolute Anlage Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + + Asset Performance + Anlage Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + + Absolute Currency Performance + Absolute Währungsperformance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + + Currency Performance + Währungsperformance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + + Absolute Net Performance + Absolute Netto Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + + Net Performance + Netto Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + + Week to date + Seit Wochenbeginn + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + WTD + WTD + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + Month to date + Seit Monatsbeginn + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + MTD + MTD + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + Year to date + Seit Jahresbeginn + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + View + Ansicht + + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + + Oops! A data provider is experiencing the hiccups. + Ups! Ein Datenprovider-Partner hat gerade ein Problem. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Wenn du heute in den Ruhestand gehen würdest, könnest du pro Jahr oder pro Monatentnehmen, bezogen auf dein Gesamtanlagevermögen von und einer Entnahmerate von 4%. + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + + Reset Filters + Filter zurücksetzen + + libs/ui/src/lib/assistant/assistant.html + 238 + + + + year + Jahr + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + Jahre + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Apply Filters + Filter anwenden + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + Data Gathering + Finanzmarktdaten synchronisieren + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + General + Allgemein + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Cloud + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Self-Hosting + + apps/client/src/app/pages/faq/faq-page.component.ts + 60 + + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + self-hosting + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Ups! Es sieht so aus, als würdest du zu viele Anfragen senden. Bitte geh es ein bisschen langsamer an. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + My Account + Mein Konto + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Active + Aktiv + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Abgeschlossen + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Indonesia + Indonesien + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Aktivität + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Dividend Yield + Dividendenrendite + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Execute Job + Job ausführen + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Priority + Priorität + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + This action is not allowed. + Diese Aktion ist nicht zulässig. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Liquidity + Liquidität + + libs/ui/src/lib/i18n.ts + 48 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {Aktivität} other {Aktivitäten}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Kauf und Verkauf + + libs/ui/src/lib/i18n.ts + 8 + + + + Delete Activities + Aktivitäten löschen + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internationalisierung + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + Möchtest du dieses Ghostfolio Konto wirklich schliessen? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Gefahrenzone + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Konto schliessen + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Nach ETF Position + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Annäherung auf Basis der grössten Positionen pro ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Melde dich jetzt an oder probiere die Live Demo aus + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + Ups! Beim Einrichten der biometrischen Authentifizierung ist ein Fehler aufgetreten. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Mehr anzeigen + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Benchmarks + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Profile löschen + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Möchtest du diese Profile wirklich löschen? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + Ups! Die Profile konnten nicht gelöscht werden. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + Tabelle + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Diagramm + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + Möchtest du deine persönliche Anlagestrategie verfeinern? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternative + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + App + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Budgetierung + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Community + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Family Office + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Investor + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Open Source + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Persönliche Finanzen + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Datenschutz + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Software + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Tool + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + User Experience + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Vermögen + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Vermögensverwaltung + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Australien + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Österreich + + libs/ui/src/lib/i18n.ts + 77 - - Switzerland - Schweiz + + Belgium + Belgien - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bulgarien + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Kanada + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + Tschechien + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finnland + + libs/ui/src/lib/i18n.ts + 83 + + + + France + Frankreich + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Deutschland + + libs/ui/src/lib/i18n.ts + 85 + + + + India + Indien + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Italien + + libs/ui/src/lib/i18n.ts + 88 + + + Netherlands + Niederlande libs/ui/src/lib/i18n.ts 90 - - Global - Weltweit + + New Zealand + Neuseeland - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + libs/ui/src/lib/i18n.ts + 91 + + + Poland + Polen libs/ui/src/lib/i18n.ts - 16 + 92 - - (Last 24 hours) - (Letzte 24 Stunden) + + Romania + Rumänien - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/i18n.ts + 93 - - (Last 30 days) - (Letzte 30 Tage) + + South Africa + Südafrika - apps/client/src/app/pages/open/open-page.html + libs/ui/src/lib/i18n.ts + 95 + + + + Thailand + Thailand + + libs/ui/src/lib/i18n.ts + 97 + + + + United States + USA + + libs/ui/src/lib/i18n.ts + 100 + + + + Error + Fehler + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + + Deactivate + Deaktivieren + + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Aktivieren + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Inactive + Inaktiv + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Cancel + Abbrechen + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 48 - apps/client/src/app/pages/open/open-page.html - 59 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 - - (Last 90 days) - (Letzte 90 Tage) + + Close + Schliessen - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 - - Choose or drop a file here - Wähle eine Datei aus oder ziehe sie hierhin + + Yes + Ja - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/i18n.ts + 32 + + + + Copy link to clipboard + Link in die Zwischenablage kopieren + + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + + Portfolio Snapshot + Portfolio Snapshot + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 + + + + Change with currency effect Change + Änderung mit Währungseffekt Änderung + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 + + + + Performance with currency effect Performance + Performance mit Währungseffekt Performance + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - You are using the Live Demo. - Du verwendest die Live Demo. + + Threshold Min + Schwellenwert (Minimum) - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - One-time fee, annual account fees - Einmalige Eröffnungsgebühr, jährliche Kontoführungsgebühren + + Threshold Max + Schwellenwert (Maximum) - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Distribution of corporate earnings - Ausschüttung von Unternehmensgewinnen + + Customize + Anpassen - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/rule/rule.component.html + 67 - - Oops! Could not get the historical exchange rate from - Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom + + No auto-renewal. + Keine automatische Erneuerung. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Fee - Gebühr + + This year + Dieses Jahr - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/public/public-page.html + 42 - - Interest - Zins + + From the beginning + Seit Beginn - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/public/public-page.html + 60 - - Revenue for lending out money - Ertrag für das Ausleihen von Geld + + Oops! Invalid currency. + Ups! Ungültige Währung. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 49 - - Add Tag - Tag hinzufügen + + This page has been archived. + Diese Seite wurde archiviert. - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Do you really want to delete this tag? - Möchtest du diesen Tag wirklich löschen? + + is Open Source Software + ist Open Source Software - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - - - Update tag - Tag bearbeiten - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Add tag - Tag hinzufügen + + is not Open Source Software + ist keine Open Source Software - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Currency Cluster Risks - Währungsklumpenrisiken - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Account Cluster Risks - Kontoklumpenrisiken + + can be self-hosted + kann selbst gehostet werden - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Transfer Cash Balance - Cash-Bestand Transfer + + cannot be self-hosted + kann nicht selbst gehostet werden - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Benchmark - Benchmark + + can be used anonymously + kann anonym genutzt werden - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Version - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Settings - Einstellungen + + cannot be used anonymously + kann nicht anonym genutzt werden - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - From - Von - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - To - Nach + + offers a free plan + hat ein kostenloses Angebot - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Transfer - Transferieren - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Membership - Mitgliedschaft + + does not offer a free plan + hat kein kostenloses Angebot - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Access - Zugang + + Oops! Could not find any assets. + Ups! Es konnten leider keine Assets gefunden werden. - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 + + + Data Providers + Datenanbieter - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Find holding... - Finde Position... + + Set API key + API-Schlüssel setzen - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - No entries... - Keine Einträge vorhanden... + + Get access to 80’000+ tickers from over 50 exchanges + Erhalte Zugang zu 80’000+ Tickern von über 50 Handelsplätzen - libs/ui/src/lib/assistant/assistant.html - 63 + libs/ui/src/lib/i18n.ts + 24 + + + Ukraine + Ukraine - libs/ui/src/lib/assistant/assistant.html - 84 + libs/ui/src/lib/i18n.ts + 98 - - Asset Profile - Anlageprofil + + Join now + Jetzt teilnehmen - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Do you really want to delete this asset profile? - Möchtest du dieses Anlageprofil wirklich löschen? + + Glossary + Lexikon - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - Search - Suche - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Add Manually - Manuell hinzufügen - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + libs/common/src/lib/routes/routes.ts + 293 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Mit dem Finanz-Dashboard Ghostfolio kannst du dein Vermögen in Cash, Aktien, ETFs und Kryptowährungen über mehrere Finanzinstitute überwachen. + + Guides + Ratgeber - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/resources/guides/resources-guides.component.html 4 - - - Last All Time High - Letztes Allzeithoch - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 + + + libs/common/src/lib/routes/routes.ts + 301 + + + + guides + ratgeber + kebab-case + + libs/common/src/lib/routes/routes.ts + 296 - - - User - Benutzer - apps/client/src/app/components/admin-users/admin-users.html - 29 + libs/common/src/lib/routes/routes.ts + 299 - - Ghostfolio vs comparison table - Ghostfolio vs Vergleichstabelle + + glossary + lexikon + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + libs/common/src/lib/routes/routes.ts + 288 - - - Open Source Wealth Management Software - Open Source Software für die Vermögensverwaltung - apps/client/src/app/pages/i18n/i18n-page.html - 14 + libs/common/src/lib/routes/routes.ts + 291 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - aktie, app, asset, dashboard, etf, finanzen, kryptowährung, management, performance, portfolio, software, trading, vermögen, web3 + + Threshold range + Schwellenwertbereich - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html 9 - - Oops, cash balance transfer has failed. - Ups, der Cash-Bestand Transfer ist fehlgeschlagen. + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray nutzt statische Analysen, um potenzielle Probleme und Risiken in deinem Portfolio aufzudecken. Passe die untenstehenden Regeln an und lege individuelle Schwellenwerte fest, um sie mit deiner persönlichen Anlagestrategie abzustimmen. - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Extreme Fear - Extreme Angst + + Economic Market Cluster Risks + Wirtschaftsraumklumpenrisiken - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - Extreme Greed - Extreme Gier + + of + von - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Neutral - Neutral + + daily requests + täglichen Anfragen - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Oops! Could not parse historical data. - Ups! Die historischen Daten konnten nicht geparsed werden. + + Remove API key + API-Schlüssel löschen - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Do you really want to delete this system message? - Möchtest du diese Systemmeldung wirklich löschen? + + Do you really want to delete the API key? + Möchtest du den API-Schlüssel wirklich löschen? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - 50-Day Trend - 50 Tage Trend + + Please enter your Ghostfolio API key: + Bitte gib den API-Schlüssel ein: - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - 200-Day Trend - 200 Tage Trend + + API Requests Today + Heutige API Anfragen - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Cash Balances - Cash-Bestände + + Could not generate an API key + API-Schlüssel konnte nicht erstellt werden - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - Starting from - Ab - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 - + + Set this API key in your self-hosted environment: + Setze diesen API-Schlüssel in deiner selbst gehosteten Umgebung: - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - year - Jahr + + Ghostfolio Premium Data Provider API Key + API-Schlüssel für den Ghostfolio Premium Datenanbieter - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 + + + Do you really want to generate a new API key? + Möchtest du wirklich einen neuen API-Schlüssel erstellen? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Do you really want to delete this account balance? - Möchtest du diesen Cash-Bestand wirklich löschen? + + API Key + API-Schlüssel - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - is an invalid currency! - ist eine ungültige Währung! + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Ghostfolio Premium Datenanbieter API-Schlüssel für selbst gehostete Umgebungen erstellen... - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - If a translation is missing, kindly support us in extending it here. - Wenn eine Übersetzung fehlt, unterstütze uns bitte dabei, sie hier zu ergänzen. + + out of + von - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - The current market price is - Der aktuelle Marktpreis ist + + rules align with your portfolio. + Regeln werden von deinem Portfolio erfüllt. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Test - Test + + Save + Speichern apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 559 - - - Date Range - Zeitraum - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Permission - Rechte - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Restricted view - Eingeschränkte Ansicht - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Oops! Could not grant access. - Ups! Der Zugang konnte nicht gewährt werden. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Private - Privat apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + 65 - - - Job Queue - Job Warteschlange - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Market data is delayed for - Die Marktdaten sind verzögert für - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Investment - Einlage - - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 - + + Asset Class Cluster Risks + Anlageklasseklumpenrisiken - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + Me + Ich - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/header/header.component.html + 213 - - - Absolute Asset Performance - Absolute Anlage Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Asset Performance - Anlage Performance + + Received Access + Erhaltene Zugangsberechtigung - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Absolute Currency Performance - Absolute Währungsperformance + + Please enter your Ghostfolio API key. + Bitte gebe deinen Ghostfolio API-Schlüssel ein. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Currency Performance - Währungsperformance + + AI prompt has been copied to the clipboard + KI-Anweisung wurde in die Zwischenablage kopiert - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Absolute Net Performance - Absolute Netto Performance + + Link has been copied to the clipboard + Link wurde in die Zwischenablage kopiert - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Net Performance - Netto Performance + + Regional Market Cluster Risks + Regionale Marktklumpenrisiken - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Week to date - Seit Wochenbeginn + + Lazy + Verzögert - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - WTD - WTD + + Instant + Sofort - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Month to date - Seit Monatsbeginn + + Default Market Price + Standardmarktpreis - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - MTD - MTD + + Mode + Modus - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Year to date - Seit Jahresbeginn + + Selector + Selektor - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - View - Ansicht + + HTTP Request Headers + HTTP Request-Headers - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 + + + end of day + Tagesende - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Oops! A data provider is experiencing the hiccups. - Ups! Ein Datenprovider-Partner hat gerade ein Problem. + + real-time + in Echtzeit - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Wenn du heute in den Ruhestand gehen würdest, könnest du pro Jahr oder pro Monatentnehmen, bezogen auf dein Gesamtanlagevermögen von und einer Entnahmerate von 4%. + + Open Duck.ai + Öffne Duck.ai - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Reset Filters - Filter zurücksetzen + + Create + Erstelle - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - year - Jahr + + Change + Änderung - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - years - Jahre - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Apply Filters - Filter anwenden + + Performance + Performance - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - Data Gathering - Daten einholen - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - General - Allgemein - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Cloud - Cloud - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Self-Hosting - Self-Hosting + + Copy portfolio data to clipboard for AI prompt + Kopiere Portfolio-Daten in die Zwischenablage für KI-Anweisung - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 + + + Copy AI prompt to clipboard for analysis + Kopiere KI-Anweisung in die Zwischenablage für Analyse - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - self-hosting - self-hosting + + Armenia + Armenien - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/ui/src/lib/i18n.ts + 75 - - FAQ - Häufig gestellte Fragen + + British Virgin Islands + Britische Jungferninseln - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + Singapur - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Ups! Es sieht so aus, als würdest du zu viele Anfragen senden. Bitte geh es ein bisschen langsamer an. + + Terms and Conditions + Nutzungsbedingungen - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - My Account - Mein Konto + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Bitte bewahre dein Sicherheits-Token sicher auf. Wenn du es verlierst, kannst du dein Benutzerkonto nicht wiederherstellen. - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Active - Aktiv + + I understand that if I lose my security token, I cannot recover my account + Ich nehme zur Kenntnis, dass ich mein Benutzerkonto nicht wiederherstellen kann, wenn ich mein Sicherheits-Token verliere - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Closed - Abgeschlossen + + Continue + Weiter - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Activity - Aktivität + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Hier ist dein Sicherheits-Token. Es ist nur ein einziges Mal sichtbar. Bitte bewahre es sicher auf. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Dividend Yield - Dividendenrendite + + Security token + Sicherheits-Token - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Execute Job - Job ausführen - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Priority - Priorität + + Do you really want to generate a new security token for this user? + Möchtest du für diesen Benutzer wirklich ein neues Sicherheits-Token generieren? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - This action is not allowed. - Diese Aktion ist nicht zulässig. + + Generate Security Token + Sicherheits-Token generieren - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Liquidity - Liquidität + + United Kingdom + Vereinigtes Königreich libs/ui/src/lib/i18n.ts - 48 + 99 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {Aktivität} other {Aktivitäten}} + + Terms of Service + Allgemeine Geschäftsbedingungen - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Buy and sell - Kauf und Verkauf + + terms-of-service + allgemeine-geschaeftsbedingungen + kebab-case - libs/ui/src/lib/i18n.ts - 8 + libs/common/src/lib/routes/routes.ts + 212 - - - Delete Activities - Aktivitäten löschen - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + libs/common/src/lib/routes/routes.ts + 215 - - Internationalization - Internationalisierung + + Terms of Service + Allgemeine Geschäftsbedingungen - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/app.component.html + 112 + + + libs/common/src/lib/routes/routes.ts + 217 - - Do you really want to close your Ghostfolio account? - Möchtest du dieses Ghostfolio Konto wirklich schliessen? + + and I agree to the Terms of Service. + und ich stimme den Allgemeinen Geschäftsbedingungen zu. - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Danger Zone - Gefahrenzone + + () is already in use. + () wird bereits verwendet. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Close Account - Konto schliessen + + An error occurred while updating to (). + Bei der Änderung zu () ist ein Fehler aufgetreten. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - By ETF Holding - Nach ETF Position + + Apply + Übernehmen - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Approximation based on the top holdings of each ETF - Annäherung auf Basis der grössten Positionen pro ETF + + with API access for + inklusive API-Zugriff für - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Join now or check out the example account - Melde dich jetzt an oder probiere die Live Demo aus + + Data Gathering is off + Finanzmarktdaten synchronisieren ist deaktiviert - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Oops! There was an error setting up biometric authentication. - Ups! Beim Einrichten der biometrischen Authentifizierung ist ein Fehler aufgetreten. + + Performance Calculation + Performance Berechnung - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Show more - Mehr anzeigen + + someone + jemand - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Benchmarks - Benchmarks + + Add asset to watchlist + Anlage zur Beobachtungsliste hinzufügen - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Delete Profiles - Profile löschen + + Watchlist + Beobachtungsliste - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Do you really want to delete these profiles? - Möchtest du diese Profile wirklich löschen? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/pages/features/features-page.html + 197 - - - Oops! Could not delete profiles. - Ups! Die Profile konnten nicht gelöscht werden. - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + libs/common/src/lib/routes/routes.ts + 110 - - Table - Tabelle + + Do you really want to delete this item? + Möchtest du diesen Eintrag wirklich löschen? - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Chart - Diagramm + + Log out + Ausloggen - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/header/header.component.html + 329 - - Would you like to refine your personal investment strategy? - Möchtest du deine persönliche Anlagestrategie verfeinern? + + Calculations are based on delayed market data and may not be displayed in real-time. + Berechnungen basieren auf verzögerten Marktdaten und werden nicht in Echtzeit angezeigt. - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/components/home-market/home-market.html + 44 - - - Alternative - Alternative - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/markets/markets.html + 53 - - App - App + + changelog + changelog + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + libs/common/src/lib/routes/routes.ts + 180 - - - Budgeting - Budgetierung - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 183 - - Community - Community + + Demo user account has been synced. + Demo Benutzerkonto wurde synchronisiert. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Family Office - Family Office + + Sync Demo User Account + Synchronisiere Demo Benutzerkonto - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Investor - Investor + + Set up + Einrichtung - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Open Source - Open Source + + No emergency fund has been set up + Es wurde kein Notfallfonds eingerichtet - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Personal Finance - Persönliche Finanzen + + An emergency fund has been set up + Ein Notfallfonds wurde eingerichtet - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Privacy - Datenschutz + + Fee Ratio + Gebührenverhältnis - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Software - Software + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Die Gebühren übersteigen ${thresholdMax}% deiner ursprünglichen Investition (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Tool - Tool + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Die Gebühren übersteigen ${thresholdMax}% deiner ursprünglichen Investition (${feeRatio}%) nicht - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - User Experience - User Experience + + Name + Name - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth - Vermögen + + Find holding or page... + Position oder Seite finden... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Wealth Management - Vermögensverwaltung + + Quick Links + Schnellzugriff - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 56 - - Australia - Australien + + Asset Profiles + Anlageprofile - libs/ui/src/lib/i18n.ts - 73 + libs/ui/src/lib/assistant/assistant.html + 112 - - Austria - Österreich + + Live Demo + Live Demo - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Belgium - Belgien - libs/ui/src/lib/i18n.ts - 75 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Bulgaria - Bulgarien - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 231 - - Canada - Kanada + + Open Source Alternative to + Open Source Alternative zu - libs/ui/src/lib/i18n.ts - 77 + libs/common/src/lib/routes/routes.ts + 326 - - Czech Republic - Tschechien + + Single Account + Einzelkonto - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Finland - Finnland + + Your net worth is managed by a single account + Dein Gesamtvermögen wird von einem einzigen Konto verwaltet - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - France - Frankreich + + Your net worth is managed by ${accountsLength} accounts + Dein Gesamtvermögen wird von ${accountsLength} Konten verwaltet - libs/ui/src/lib/i18n.ts - 80 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - Germany - Deutschland + + personal-finance-tools + tools-fuer-persoenliche-finanzen + kebab-case - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 312 - - - India - Indien - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 315 + + + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italien + + markets + maerkte + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 + + + libs/common/src/lib/routes/routes.ts + 307 - - Netherlands - Niederlande + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Erweitere dein selbst gehostetes Ghostfolio durch einen leistungsstarken Datenanbieter mit Zugriff auf über 80’000 Ticker von mehr als 50 Börsen weltweit. - libs/ui/src/lib/i18n.ts - 85 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - New Zealand - Neuseeland + + Get Access + Zugang erhalten - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Poland - Polen + + Learn more + Mehr erfahren - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - Romania - Rumänien + + Limited Offer! + Begrenztes Angebot! - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - South Africa - Südafrika + + Get extra + Erhalte extra - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Thailand - Thailand + + Available + Verfügbar - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - United States - USA + + Unavailable + Nicht verfügbar - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Error - Fehler + + new + neu - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Deactivate - Deaktivieren - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Activate - Aktivieren + + Investment + Investition - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Inactive - Inaktiv + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Über ${thresholdMax}% deiner aktuellen Investition ist bei ${maxAccountName} (${maxInvestmentRatio}%) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Cancel - Abbrechen + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + Der Hauptteil deiner aktuellen Investition ist bei ${maxAccountName} (${maxInvestmentRatio}%) und übersteigt ${thresholdMax}% nicht - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Close - Schliessen + + Equity + Beteiligungskapital - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Yes - Ja + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + Der Beteiligungskapitalanteil deiner aktuellen Investition (${equityValueRatio}%) übersteigt ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Copy link to clipboard - Link in die Zwischenablage kopieren + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + Der Beteiligungskapitalanteil deiner aktuellen Investition (${equityValueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Beteiligungskapitalanteil deiner aktuellen Investition (${equityValueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Change with currency effect Change - Änderung mit Währungseffekt Change + + Fixed Income + Feste Einkünfte - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Performance with currency effect Performance - Performance mit Währungseffekt Performance + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + Der Anteil der festen Einkünfte deiner aktuellen Investition (${fixedIncomeValueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Min - Schwellenwert (Minimum) + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + Der Anteil der festen Einkünfte deiner aktuellen Investition (${fixedIncomeValueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Threshold Max - Schwellenwert (Maximum) + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil der festen Einkünfte deiner aktuellen Investition (${fixedIncomeValueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Close - Schliessen + + Investment: Base Currency + Investition: Basiswährung - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - Customize - Anpassen + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + Der Hauptteil deiner aktuellen Investition ist nicht in deiner Basiswährung (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - No auto-renewal. - Keine automatische Erneuerung. + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + Der Hauptteil deiner aktuellen Investition ist in deiner Basiswährung (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - Today - Heute + + Investment + Investition - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - This year - Dieses Jahr + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Über ${thresholdMax}% deiner aktuellen Investition ist in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - From the beginning - Seit Beginn + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + Der Hauptteil deiner aktuellen Investition ist in ${currency} (${maxValueRatio}%) und übersteigt ${thresholdMax}% nicht - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - Oops! Invalid currency. - Ups! Ungültige Währung. + + start + start + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + libs/common/src/lib/routes/routes.ts + 336 - - - This page has been archived. - Diese Seite wurde archiviert. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 337 - - is Open Source Software - ist Open Source Software + + Do you really want to generate a new security token? + Möchtest du wirklich ein neues Sicherheits-Token generieren? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is not Open Source Software - ist keine Open Source Software + + Generate + Generieren - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is Open Source Software - ist Open Source Software + + Stocks + Aktien - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - is not Open Source Software - ist keine Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/pages/features/features-page.html + 15 - - can be self-hosted - kann selbst gehostet werden + + Cryptocurrencies + Kryptowährungen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - cannot be self-hosted - kann nicht selbst gehostet werden - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - kann selbst gehostet werden + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - kann nicht selbst gehostet werden + + Manage Asset Profile + Anlageprofil verwalten - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - kann anonym genutzt werden + + Alternative Investment + Alternative Investition - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - kann nicht anonym genutzt werden + + Collectible + Sammlerobjekt - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - kann anonym genutzt werden + + Average Unit Price + Ø Preis pro Einheit - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - kann nicht anonym genutzt werden - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - hat ein kostenloses Angebot + + Account Cluster Risks + Kontoklumpenrisiken - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - hat kein kostenloses Angebot - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + + Asset Class Cluster Risks + Anlageklasseklumpenrisiken + + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - hat ein kostenloses Angebot + + Currency Cluster Risks + Währungsklumpenrisiken - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - hat kein kostenloses Angebot + + Economic Market Cluster Risks + Wirtschaftsraumklumpenrisiken - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Ups! Es konnten leider keine Assets gefunden werden. + + Emergency Fund + Notfallfonds - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Datenanbieter + + Fees + Gebühren - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEU + + Regional Market Cluster Risks + Regionale Marktklumpenrisiken - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - API-Schlüssel setzen + + No results found... + Keine Ergebnisse gefunden... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Möchtest du auf dem Laufenden bleiben? Dann klicke unten, um benachrichtigt zu werden, sobald es verfügbar ist. + + Developed Markets + Entwickelte Länder - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Erhalte Zugang zu 100’000+ Tickern von über 50 Handelsplätzen + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + Der Anteil entwickelter Länder deiner aktuellen Investition (${developedMarketsValueRatio}%) übersteigt ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + Der Anteil entwickelter Länder deiner aktuellen Investition (${developedMarketsValueRatio}%) liegt unter ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Überspringen + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil entwickelter Länder deiner aktuellen Investition (${developedMarketsValueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Jetzt teilnehmen + + Emerging Markets + Schwellenländer - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Lexikon + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${emergingMarketsValueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${emergingMarketsValueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Ratgeber + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${emergingMarketsValueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + Es wurden noch keine Konten eingerichtet - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - ratgeber - snake-case + + Your net worth is managed by 0 accounts + Dein Gesamtvermögen wird von 0 Konten verwaltet - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asien-Pazifik - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - lexikon - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + Der Anteil des Asien-Pazifik-Marktes deiner aktuellen Investition (${valueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + Der Anteil des Asien-Pazifik-Marktes deiner aktuellen Investition (${valueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Schwellenwertbereich + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil des Asien-Pazifik-Marktes deiner aktuellen Investition (${valueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray nutzt statische Analysen, um potenzielle Probleme und Risiken in deinem Portfolio aufzudecken. Passe die untenstehenden Regeln an und lege individuelle Schwellenwerte fest, um sie mit deiner persönlichen Anlagestrategie abzustimmen. + + Emerging Markets + Schwellenländer - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Wirtschaftsraumklumpenrisiken + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${valueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - von + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${valueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - täglichen Anfragen + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil der Schwellenländer deiner aktuellen Investition (${valueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - API-Schlüssel löschen + + Europe + Europa - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Möchtest du den API-Schlüssel wirklich löschen? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + Der Anteil des europäischen Marktes deiner aktuellen Investition (${valueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Bitte gib den API-Schlüssel ein: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + Der Anteil des europäischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil des europäischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Benachrichtige mich + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - Ich habe einen API-Schlüssel + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + Der Anteil des japanischen Marktes deiner aktuellen Investition (${valueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - Heutige API Anfragen + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + Der Anteil des japanischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - API-Schlüssel konnte nicht erstellt werden + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil des japanischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Setze diesen API-Schlüssel in deiner selbst gehosteten Umgebung: + + North America + Nordamerika - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - API-Schlüssel für den Ghostfolio Premium Datenanbieter + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + Der Anteil des nordamerikanischen Marktes deiner aktuellen Investition (${valueRatio}%) übersteigt ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Möchtest du wirklich einen neuen API-Schlüssel erstellen? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + Der Anteil des nordamerikanischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt unter ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Der Anteil des nordamerikanischen Marktes deiner aktuellen Investition (${valueRatio}%) liegt im Bereich zwischen ${thresholdMin}% und ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API-Schlüssel + + Find Ghostfolio on GitHub + Finde Ghostfolio auf GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Ghostfolio Premium Datenanbieter API-Schlüssel für selbst gehostete Umgebungen erstellen... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - von + + Join the Ghostfolio Slack community + Tritt der Ghostfolio Slack Community bei - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - Regeln werden von Ihrem Portfolio erfüllt. + + Follow Ghostfolio on X (formerly Twitter) + Folge Ghostfolio auf X (ehemals Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Speichern + + Send an e-mail + E-Mail senden - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Anlageklasseklumpenrisiken + + Follow Ghostfolio on LinkedIn + Folge Ghostfolio auf LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Ich + + Ghostfolio is an independent & bootstrapped business + Ghostfolio ist ein unabhängiges & selbstfinanziertes Unternehmen - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Erhaltene Zugangsberechtigung + + Support Ghostfolio + Unterstütze Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 4eb127ccc..1f42c964b 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -2,7 +2,7 @@ - + Create Account Crear una cuenta @@ -17,16 +17,20 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. El riesgo de pérdida en trading puede ser sustancial. No es aconsejable invertir dinero que puedas necesitar a corto plazo. apps/client/src/app/app.component.html - 200 + 221 - + Grantee Beneficiario @@ -34,7 +38,7 @@ 11 - + Type Tipo @@ -54,7 +58,7 @@ 161 - + Details Detalles @@ -62,7 +66,7 @@ 33 - + Revoke Revoca @@ -75,50 +79,10 @@ ¿Quieres revocar el acceso concedido? apps/client/src/app/components/access-table/access-table.component.ts - 67 - - - - Activities - Operaciones - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + 108 - + Name Nombre @@ -127,23 +91,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -155,7 +123,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -174,7 +142,7 @@ 88 - + Total Total @@ -182,7 +150,7 @@ 55 - + Value Valor @@ -199,31 +167,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -250,64 +202,56 @@ 102 - + Edit Edita apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Elimina apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -317,16 +261,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? ¿Estás seguro de eliminar esta cuenta? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + 148 - + Delete Jobs Elimina los trabajos @@ -334,31 +282,7 @@ 151 - - Symbol - Símbolo - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 - - - + Data Source Fuente de datos @@ -367,18 +291,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Intentos @@ -386,7 +310,7 @@ 83 - + Created Creado @@ -394,7 +318,7 @@ 92 - + Finished Finalizado @@ -402,31 +326,39 @@ 101 - + Status Estado apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Asset Profiles Perfiles de activos. - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data Datos históricos del mercado apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Visualiza los datos @@ -434,7 +366,7 @@ 166 - + View Stacktrace Visualiza Stacktrace @@ -442,7 +374,7 @@ 173 - + Delete Job Elimina el trabajo @@ -450,7 +382,7 @@ 180 - + Details for Detalles para @@ -458,12 +390,12 @@ 2 - + Date Fecha apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -478,127 +410,43 @@ 6 - + Market Price Precio de mercado apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Cancela - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 - - - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 - - - - Save - Guarda - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 - - - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - + First Activity Primera actividad apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + 148 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + 198 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + 214 libs/ui/src/lib/holdings-table/holdings-table.component.html 50 - + Activity Count Recuento de actividad @@ -606,48 +454,32 @@ 19 - + Historical Data Datos históricos apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + 166 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html 44 - - Please add a currency: - Por favor, añade una divisa: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 - - Do you really want to delete this coupon? ¿Estás seguro de eliminar este cupón? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + 194 - - Do you really want to delete this currency? - ¿Estás seguro de eliminar esta divisa? + + Do you really want to flush the cache? + ¿Estás seguro de limpiar la caché? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 - - - - Do you really want to flush the cache? - ¿Estás seguro de limpiar la caché? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + 231 @@ -655,10 +487,10 @@ Por favor, establece tu mensaje del sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + 251 - + User Count Número de usuarios @@ -666,7 +498,7 @@ 13 - + per User por usario @@ -674,112 +506,84 @@ 28 - - Gather Recent Data - Recoger datos recientes - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 - - - - Gather All Data - Recoger todos los datos - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 - - - + Gather Profile Data Recoger los datos del perfil apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + 235 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Exchange Rates - Tipos de cambio - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + 44 - + Add Currency Añadir divisa apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + System Message Mensaje del sistema apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Establecer mensaje apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Read-only Mode Modo de solo lectura apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + Coupons Cupones apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Añadir apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Tareas domésticas apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Limpiar caché apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -787,46 +591,38 @@ ¿Estás seguro de eliminar este usuario? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Usuario apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + 31 apps/client/src/app/components/header/header.component.html - 229 - - - - Registration - Registro - - apps/client/src/app/components/admin-users/admin-users.html - 97 + 231 - + Engagement per Day Contratación diaria apps/client/src/app/components/admin-users/admin-users.html - 157 + 158 - + Last Request Última petición apps/client/src/app/components/admin-users/admin-users.html - 202 + 204 - + Current Market Mood Estado de ánimo del mercado @@ -834,383 +630,191 @@ 12 - - Overview - Visión general + + About Ghostfolio + Sobre Ghostfolio apps/client/src/app/components/header/header.component.html - 28 + 326 - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Portfolio - Cartera + + Get Started + Empezar - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 320 - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/public/public-page.html + 220 - - Accounts - Cuentas + + Sign in + Iniciar sesión - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/header/header.component.html - 263 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + libs/common/src/lib/routes/routes.ts + 157 + + + Oops! Incorrect Security Token. + Vaya! Token de seguridad incorrecto. - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/components/header/header.component.ts + 274 - - - Admin Control - Control de administrador - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 - - Resources - Recursos + + Manage Activities + Gestión de las operaciones - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Last Days + Últimos días - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/markets/markets.html + 17 + + + Security Token + Token de seguridad - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - - - Pricing - Precios - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - About - Sobre + + or + o - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/pages/landing/landing-page.html + 48 - - - Me - - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/landing/landing-page.html + 451 - - - My Ghostfolio - Mi Ghostfolio - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - - - About Ghostfolio - Sobre Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Features - Funcionalidades - - apps/client/src/app/app.component.html - 79 - + + Sign in with Internet Identity + Iniciar sesión con Internet Identity - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + Iniciar sesión con Google - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Markets - Mercados + + Stay signed in + Seguir conectado - apps/client/src/app/app.component.html + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html 61 + + + Time in Market + Tiempo en el mercado - apps/client/src/app/components/header/header.component.html - 398 - - - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + Rendimiento bruto absoluto - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 - - Get Started - Empezar - - apps/client/src/app/pages/features/features-page.html - 303 - - - apps/client/src/app/pages/public/public-page.html - 220 - - - - Sign in - Iniciar sesión - - apps/client/src/app/app-routing.module.ts - 150 - - - apps/client/src/app/components/header/header.component.ts - 230 - - - - Oops! Incorrect Security Token. - Vaya! Token de seguridad incorrecto. - - apps/client/src/app/components/header/header.component.ts - 245 - - - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 - - - - Manage Activities - Gestión de las operaciones - - apps/client/src/app/components/home-holdings/home-holdings.html - 63 - - - - Last Days - Últimos días - - apps/client/src/app/components/home-market/home-market.html - 7 - - - - Summary - Resumen - - apps/client/src/app/components/home-summary/home-summary.html - 2 - - - - Security Token - Token de seguridad - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 - - - - or - o - - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 - - - apps/client/src/app/pages/landing/landing-page.html - 47 - - - apps/client/src/app/pages/landing/landing-page.html - 450 - - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 - - - apps/client/src/app/pages/register/register-page.html - 30 - - - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 - - - - Sign in with Internet Identity - Iniciar sesión con Internet Identity - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 - - - - Sign in with Google - Iniciar sesión con Google - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 - - - - Stay signed in - Seguir conectado - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 - - - - Sign in - Iniciar sesión - - apps/client/src/app/components/header/header.component.html - 412 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 - - - - Time in Market - Tiempo en el mercado - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 - - - - Buy - Compra - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 - - - - Sell - Venta - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 - - - - Investment - Inversión - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - - Absolute Gross Performance - Rendimiento bruto absoluto - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 - - - + Absolute Net Performance Rendimiento neto absoluto @@ -1218,7 +822,7 @@ 102 - + Net Performance Rendimiento neto @@ -1226,7 +830,7 @@ 117 - + Total Assets Total de activos @@ -1234,153 +838,105 @@ 143 - - Valuables - Objetos de valor - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Fondo de emergencia - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Capacidad de compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Net Worth Patrimonio neto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Rendimiento anualizado apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividendo - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 Please set the amount of your emergency fund. - Por favor, ingresa la cantidad de tu fondo de emergencia: + Por favor, ingresa la cantidad de tu fondo de emergencia: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + 71 - + Sectors Sectores apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Países apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Tags Etiquetas apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + Report Data Glitch Reporta un anomalía de los datos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 - + Allocation Distribución + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -1394,19 +950,7 @@ 116 - - Performance - Rendimiento - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 - - - + Show all Mostrar todos @@ -1418,60 +962,44 @@ Today Hoy - apps/client/src/app/components/toggle/toggle.component.ts - 21 - + apps/client/src/app/pages/public/public-page.html + 24 + libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD Desde principio de año - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1 año - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5 años - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Máximo - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1479,191 +1007,75 @@ De acuerdo apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About Sobre - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Privacy Policy - Política de privacidad - - apps/client/src/app/app.component.html - 103 - - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 - - - - Blog - Blog apps/client/src/app/app.component.html - 73 - - - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 - - - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 - - - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 - - - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 - - - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 - - - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 - - - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 - - - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 - - - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 - - - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 - - - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 - - - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 70 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/header/header.component.html + 375 - - - Changelog - Registro de cambios - apps/client/src/app/app.component.html - 77 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/common/src/lib/routes/routes.ts + 220 - - License - Licencia de uso + + Privacy Policy + Política de privacidad apps/client/src/app/app.component.html - 88 + 105 - apps/client/src/app/pages/about/license/license-page.html + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 - - - Privacy Policy - Política de privacidad - - apps/client/src/app/pages/about/about-page.component.ts - 62 - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 209 My Ghostfolio Mi Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 - - Please enter your coupon code: + + Please enter your coupon code. Por favor, ingresa tu código de cupón: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1671,7 +1083,7 @@ No se puede canjear este código de cupón apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1679,7 +1091,7 @@ El codigo de cupón ha sido canjeado apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1687,7 +1099,7 @@ Refrescar apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1695,114 +1107,94 @@ ¿Estás seguro de eliminar este método de acceso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Cuenta - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Suscripción - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year por año apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Prueba Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Canjea el cupón apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Vista del presentador apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Divisa base apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Locale Ubicación + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Formato de fecha y número apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Zen Mode Modo Zen apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Sign in with fingerprint Iniciar sesión con huella digital apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + User ID ID usuario @@ -1811,18 +1203,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Acceso concedido apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Conceder acceso @@ -1830,7 +1222,7 @@ 7 - + Public Público @@ -1842,11 +1234,35 @@ Accounts Cuentas - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 + + + apps/client/src/app/components/admin-users/admin-users.html + 115 + + + apps/client/src/app/components/header/header.component.html + 58 + + + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 - + Update account Editar cuenta @@ -1854,7 +1270,7 @@ 8 - + Add account Añadir cuenta @@ -1862,15 +1278,7 @@ 10 - - Cash - Efectivo - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 - - - + Currency Divisa base @@ -1879,11 +1287,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1895,14 +1303,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Saldo en efectivo @@ -1918,7 +1326,7 @@ 34 - + Platform Plataforma @@ -1934,7 +1342,7 @@ 48 - + Account ID ID cuenta @@ -1946,16 +1354,116 @@ Admin Control Control de administrador - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 + + + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 Blog Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 + + + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 + + + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 + + + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 + + + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 + + + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 + + + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 + + + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 + + + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 + + + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 + + + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 + + + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 + + + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 + + + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 + + + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 + + + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 + + + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 + + + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 @@ -1970,91 +1478,135 @@ Frequently Asked Questions (FAQ) Preguntas más frecuentes (FAQ) - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Funcionalidades - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Overview Visión general - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 Markets Mercados - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 - - - Allocations - Distribución - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 - + Allocations Distribución apps/client/src/app/pages/portfolio/allocations/allocations-page.html 4 + + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 133 + - + By Account Por cuenta @@ -2062,7 +1614,7 @@ 286 - + By Currency Por divisa @@ -2070,7 +1622,7 @@ 63 - + By Asset Class Por tipo de activo @@ -2078,7 +1630,7 @@ 85 - + By Holding Por participación @@ -2086,7 +1638,7 @@ 107 - + By Sector Por sector @@ -2094,7 +1646,7 @@ 130 - + By Continent Por continente @@ -2102,7 +1654,7 @@ 153 - + By Country Por país @@ -2110,7 +1662,7 @@ 264 - + Regions Regiones @@ -2123,50 +1675,42 @@ - Analysis - Análisis - - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 - - - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 - - - Analysis Análisis apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 + + libs/common/src/lib/routes/routes.ts + 138 + - + Investment Timeline Cronología de la inversión apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + Top Lo mejor apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom Lo peor apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + FIRE FIRE @@ -2174,7 +1718,7 @@ 4 - + Calculator Calculadora @@ -2182,7 +1726,7 @@ 7 - + 4% Rule Regla del 4% @@ -2191,26 +1735,6 @@ - Holdings - Participaciones - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - Holdings Participaciones @@ -2225,12 +1749,24 @@ apps/client/src/app/pages/public/public-page.html 70 + + libs/common/src/lib/routes/routes.ts + 90 + + + libs/common/src/lib/routes/routes.ts + 167 + + + + Holdings + Participaciones libs/ui/src/lib/assistant/assistant.html - 46 + 82 - + Update activity Actualizar opereación @@ -2238,12 +1774,12 @@ 10 - + Add activity Añadir operación apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2253,77 +1789,69 @@ Sell Venta + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Nombre, símbolo o ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 124 - + Quantity Cantidad apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Unit Price Precio unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 214 libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Fee - Comisión - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 234 - - - + Note Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2331,47 +1859,51 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 275 - - Asset Class - Tipo de activo + + Activities + Operación - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + 207 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/admin-users/admin-users.html + 136 - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Activities - Operación - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 @@ -2379,7 +1911,7 @@ Importando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2387,42 +1919,66 @@ La importación se ha completado apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 Pricing Precios + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 + Portfolio Cartera apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + 124 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + 92 - - - Currencies - Divisas - apps/client/src/app/pages/public/public-page.html - 88 + libs/common/src/lib/routes/routes.ts + 151 - + Continents Continentes @@ -2430,23 +1986,27 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. Ghostfolio te permite hacer un seguimiento de tu riqueza. apps/client/src/app/pages/public/public-page.html - 215 + 216 Registration Registro - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Continue with Internet Identity Continuar con Internet Identity @@ -2454,7 +2014,7 @@ 42 - + Continue with Google Continuar con Google @@ -2462,39 +2022,39 @@ 53 - + Copy to clipboard Copiar al portapapeles apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Confirmo haber guardado mi Token de seguridad mostrado arriba en un lugar seguro. Si lo pierdo, no podré recuperar mi cuenta. + + Resources + Recursos - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Aceptar y continuar - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Recursos - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Vaya, la autenticación ha fallado. @@ -2502,7 +2062,7 @@ 19 - + Try again Prueba otra vez @@ -2510,15 +2070,15 @@ 27 - + Go back to Home Page Volver a la página principal apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 - + Draft Borrador @@ -2531,10 +2091,18 @@ Importar operaciones apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Exportar operaciones @@ -2546,7 +2114,7 @@ 396 - + Export Drafts as ICS Exportar borrador como ICS @@ -2558,7 +2126,7 @@ 409 - + Clone Clonar @@ -2566,7 +2134,7 @@ 436 - + Export Draft as ICS Exportar borrador como ICS @@ -2579,34 +2147,26 @@ ¿Estás seguro de eliminar esta operación? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Índice - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High Variación respecto al máximo histórico (ATH) libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH desde el máximo histórico (ATH) libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Tipo de interés anual @@ -2614,7 +2174,7 @@ 21 - + Time to add your first activity. Es momento de añadir tu primera operación. @@ -2622,20 +2182,20 @@ 12 - + Language Idioma apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + 56 - + Get started Comenzar apps/client/src/app/components/header/header.component.html - 422 + 432 @@ -2643,7 +2203,7 @@ Esta funcionalidad no está disponible actualmente. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -2651,11 +2211,11 @@ Vaya! Algo no funcionó bien. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 184 @@ -2663,26 +2223,18 @@ Por favor, prueba más tarde. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 - - - - Change - Modificar - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 186 - + Developed Markets Mercados desarrollados @@ -2694,47 +2246,15 @@ 160 - - Asset Sub Class - Subtipo de activo - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 - - - - Average Unit Price - Precio unitario medio - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 - - - + Maximum Price Precio máximo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 143 - + Other Markets Otros mercados @@ -2746,7 +2266,7 @@ 178 - + Emerging Markets Mercados emergentes @@ -2758,48 +2278,48 @@ 169 - + Sector Sector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + 242 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + 263 - + Country País apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Minimum Price Precio mínimo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Projected Total Amount Importe total previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2807,15 +2327,19 @@ Ahorros libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 Interest Interés + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + 370 libs/ui/src/lib/i18n.ts @@ -2827,7 +2351,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 @@ -2835,23 +2359,23 @@ Mensual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + 88 - + Sectors Count Número de sectores apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + 175 - + Countries Count Número de países apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + 184 @@ -2859,11 +2383,15 @@ Miedo apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -2871,11 +2399,15 @@ Codicia apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 @@ -2883,18 +2415,18 @@ Filtrar por... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + 379 - - Hello, has shared a Portfolio with you! - Hola, ha compartido una Cartera contigo! + + Hello, has shared a Portfolio with you! + Hola, ha compartido una Cartera contigo! apps/client/src/app/pages/public/public-page.html - 4 + 5 - + Alias Alias @@ -2906,23 +2438,27 @@ 11 - + Experimental Features Funcionalidades experimentales apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 Benchmark Benchmark - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 - + Compare with... Comparar con... @@ -2930,7 +2466,7 @@ 18 - + Proportion of Net Worth Porcentaje del patrimonio neto @@ -2938,12 +2474,12 @@ 12 - + Excluded from Analysis Excluido del análisis apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 @@ -2951,39 +2487,35 @@ Automático apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 - - - Appearance - Apariencia apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + 172 - - Auto - Automático + + Appearance + Apariencia apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Claro apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Oscuro apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 @@ -2991,15 +2523,15 @@ Importe total apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 - + Portfolio Evolution Evolución cartera apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 @@ -3007,12 +2539,24 @@ Tasa de ahorro apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 Account Cuenta + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3021,6 +2565,30 @@ Asset Class Tipo de activo + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3029,6 +2597,26 @@ Symbol Símbolo + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3037,6 +2625,10 @@ Tag Etiqueta + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3045,9 +2637,13 @@ Cash Efectivo + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3061,6 +2657,10 @@ Equity Capital + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + libs/ui/src/lib/i18n.ts 46 @@ -3095,7 +2695,7 @@ Criptomoneda libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3103,7 +2703,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3111,7 +2711,7 @@ Fondo de inversión libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3119,7 +2719,7 @@ Metal precioso libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3127,7 +2727,7 @@ Capital riesgo libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3135,12 +2735,24 @@ Acción libs/ui/src/lib/i18n.ts - 58 + 60 Emergency Fund Fondo de emergencia + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3155,19 +2767,35 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 No data available Sin datos disponibles + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 @@ -3175,7 +2803,7 @@ América del Norte libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3183,7 +2811,7 @@ África libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3191,7 +2819,7 @@ Asia libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3199,7 +2827,7 @@ Europa libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3207,7 +2835,7 @@ Oceanía libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3215,10 +2843,10 @@ América del Sur libs/ui/src/lib/i18n.ts - 70 + 72 - + The following file formats are supported: Los siguientes formatos de archivo están soportados: @@ -3226,7 +2854,7 @@ 90 - + Back Volver @@ -3238,112 +2866,100 @@ 178 - - Community - Comunidad - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 - - - + Activities Count Recuento de actividades apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + 157 - + Refresh Refrescar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + 17 - + Symbol Mapping Mapeo de símbolos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 Dividend Dividendo + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts 36 - + Dividend Timeline Calendario de dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 Asset Sub Class Subtipo de activo + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + libs/ui/src/lib/i18n.ts 7 - + User Signup Registro de usuario apps/client/src/app/components/admin-overview/admin-overview.html - 111 + 34 @@ -3351,10 +2967,10 @@ Validando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + Import Importar @@ -3367,58 +2983,54 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Market Data Datos del mercado - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Users Usuarios - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 61 Summary Resumen - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 - + Holding - Holding + Participación apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 32 libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Cargar dividendos @@ -3431,7 +3043,7 @@ Anual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3439,15 +3051,23 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Válido hasta apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3456,7 +3076,7 @@ Core - Core + Núcleo libs/ui/src/lib/i18n.ts 10 @@ -3502,39 +3122,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values Protección de información confidencial como rendimientos absolutos y valores cuantitativos apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times Experiencia sin distracciones para tiempos turbulentos apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality Un adelanto de las próximas funciones apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? ¿Es usted un inversor ambicioso que necesita una visión completa? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Resumen de la cartera @@ -3543,14 +3163,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Puntos de referencia de rendimiento @@ -3559,14 +3179,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator Calculadora FIRE @@ -3575,14 +3195,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... y más características... @@ -3591,175 +3211,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Saltar apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Mejorar plan apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Para inversores expertos en tecnología que prefieren ejecutar Ghostfolio en su propia infraestructura. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Transacciones ilimitadas apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Cuentas ilimitadas apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Rendimiento del Portfolio apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Auto alojado, actualiza manualmente. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Gratis apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Para nuevos inversores que estan empezando con el trading. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Oferta en la nube de Ghostfolio totalmente administrada. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Para inversores ambiciosos que necesitan una visión completa de sus activos financieros apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Pago único, sin renovación automática. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Empieza apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - + It’s free. Es gratis. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 353 - + Fees Comisiones apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3767,10 +3403,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Distribucion del Portfolio @@ -3783,14 +3419,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Tasa de Ahorro Mensual @@ -3798,20 +3434,20 @@ 10 - + Data Import and Export Importacion y exportacion de datos apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3822,20 +3458,20 @@ 13 - + Community Support Soporte de la comunidad apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support Soporte a Traves de Email y Chat apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3854,7 +3490,7 @@ 14 - + Market data provided by Datos de mercado proporcionados por @@ -3862,51 +3498,35 @@ 2 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - - Gather Historical Data - Gather Historical Data - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 - - - + Retirement Date - Retirement Date + Fecha de jubilación libs/ui/src/lib/fire-calculator/fire-calculator.component.html 32 - + Professional Data Provider - Professional Data Provider + Proveedor de datos profesional apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html 40 apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans - Pricing Plans + Planes de precios apps/client/src/app/pages/pricing/pricing-page.html 4 - + Renew Plan Renovar Plan @@ -3915,79 +3535,83 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Nuestra oferta oficial en la nube Ghostfolio Premium es la forma más fácil de comenzar. Debido al tiempo que ahorra, esta será la mejor opción para la mayoría de las personas. Los ingresos se utilizan para cubrir los costos operativos de la infraestructura de alojamiento y los proveedores de datos profesionales, y para financiar el desarrollo continuo. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User - Impersonate User + Suplantar usuario apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User - Delete User + Eliminar usuario apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 Do you really want to delete these activities? - Do you really want to delete these activities? + ¿Realmente deseas eliminar estas actividades? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider - By ETF Provider + Por proveedor de ETF apps/client/src/app/pages/portfolio/allocations/allocations-page.html 306 - + Update platform - Update platform + Actualizar plataforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 8 - + Add platform - Add platform + Agregar plataforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 10 - + Url - Url + ¿La URL? apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3996,199 +3620,159 @@ Do you really want to delete this platform? - Do you really want to delete this platform? + ¿Realmente deseas eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms - Platforms + Plataformas apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance - Update Cash Balance + Actualizar saldo en efectivo apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 112 - + By Platform - By Platform + Por plataforma apps/client/src/app/pages/portfolio/allocations/allocations-page.html 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + Actualiza a Ghostfolio Premium hoy y accede a características exclusivas para mejorar tu experiencia de inversión: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. - Get the tools to effectively manage your finances and refine your personal investment strategy. + Obtén las herramientas para gestionar eficazmente tus finanzas y perfeccionar tu estrategia de inversión personal. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform - Add Platform + Agregar plataforma apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings - Settings - - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - + Configuraciones - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Equity - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 This activity already exists. - This activity already exists. + Esta actividad ya existe. libs/ui/src/lib/i18n.ts 19 - + Manage Benchmarks - Manage Benchmarks + Gestionar puntos de referencia apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html 35 - + Select Holding - Select Holding + Seleccionar posición apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 20 - + Select File - Select File + Seleccionar archivo apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 22 - + Select Dividends - Select Dividends + Seleccionar dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 113 - + Select Activities - Select Activities + Seleccionar dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 115 - - Import Activities - Import Activities - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Import Dividends - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Personal Finance + + Frequently Asked Questions (FAQ) + Preguntas frecuentes (FAQ) - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Frequently Asked Questions (FAQ) - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak - Current Streak + Racha actual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak - Longest Streak + Racha más larga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 Months - Months + Meses libs/ui/src/lib/i18n.ts 22 @@ -4196,7 +3780,7 @@ Years - Years + Años libs/ui/src/lib/i18n.ts 31 @@ -4204,7 +3788,7 @@ Month - Month + Mes libs/ui/src/lib/i18n.ts 21 @@ -4212,18 +3796,18 @@ Year - Year + Año libs/ui/src/lib/i18n.ts 30 - + Liabilities - Liabilities + Pasivos apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4232,151 +3816,143 @@ Changelog - Changelog + Registro de cambios - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License - License + Licencia - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Stocks - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs - ETFs + ETFs apps/client/src/app/pages/features/features-page.html 25 - + Bonds - Bonds + Bonos apps/client/src/app/pages/features/features-page.html 38 - - Cryptocurrencies - Cryptocurrencies - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items - Wealth Items + Elementos de patrimonio apps/client/src/app/pages/features/features-page.html 76 - + Import and Export - Import and Export + Importar y exportar apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts - Multi-Accounts + Cuentas múltiples apps/client/src/app/pages/features/features-page.html 127 - + Portfolio Calculations - Portfolio Calculations + Cálculos de portafolio apps/client/src/app/pages/features/features-page.html 141 - + Dark Mode - Dark Mode + Modo oscuro apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood - Market Mood + Modo de mercado apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis - Static Analysis + Análisis estático apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language - Multi-Language + Multilenguaje apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software - Open Source Software + Software de código abierto apps/client/src/app/pages/features/features-page.html - 278 + 295 Liability - Liability + Responsabilidad libs/ui/src/lib/i18n.ts 40 - + Scraper Configuration - Scraper Configuration + Configuración del scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile - Add Asset Profile + Agregar perfil de activo apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 7 @@ -4384,21 +3960,25 @@ Personal Finance Tools - Personal Finance Tools + Herramientas de finanzas personales - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Descubra alternativas de software libre para herramientas de finanzas personales apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Fundada @@ -4406,7 +3986,7 @@ 77 - + Origin Origen @@ -4414,7 +3994,7 @@ 82 - + Region Región @@ -4422,15 +4002,15 @@ 87 - + Available in Disponible en apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Sí @@ -4466,7 +4046,7 @@ 274 - + ❌ No ❌ No @@ -4502,31 +4082,31 @@ 281 - + Self-Hosting - Self-Hosting + Autoalojamiento apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Uso anónimo apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Plan gratuito apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Notas @@ -4534,41 +4114,17 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Siga, analice y visualice su patrimonio sin esfuerzo con Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Personal Finance Tools - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Guides - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + 329 - - Glossary - Glossary - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 - - - + Stocks, ETFs, bonds, cryptocurrencies, commodities - Stocks, ETFs, bonds, cryptocurrencies, commodities + Acciones, ETFs, bonos, criptomonedas, materias primas apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 25 @@ -4578,17 +4134,17 @@ 65 - + Mortgages, personal loans, credit cards - Mortgages, personal loans, credit cards + Hipotecas, préstamos personales, tarjetas de crédito apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 57 - + Luxury items, real estate, private companies - Luxury items, real estate, private companies + Artículos de lujo, bienes raíces, empresas privadas apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 73 @@ -4596,7 +4152,11 @@ Buy - Buy + Comprar + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4604,7 +4164,7 @@ Valuable - Valuable + Valioso libs/ui/src/lib/i18n.ts 39 @@ -4612,39 +4172,39 @@ ETFs without Countries - ETFs without Countries + ETFs sin países apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 ETFs without Sectors - ETFs without Sectors + ETFs sin sectores apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets - Assets + Activos apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 Preset - Preset + Preestablecido libs/ui/src/lib/i18n.ts 25 - + By Market - By Market + Por mercado apps/client/src/app/pages/portfolio/allocations/allocations-page.html 175 @@ -4652,7 +4212,7 @@ Asia-Pacific - Asia-Pacific + Asia-Pacífico libs/ui/src/lib/i18n.ts 5 @@ -4660,123 +4220,103 @@ Japan - Japan + Japón libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio - Welcome to Ghostfolio + Bienvenido a Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts - Setup your accounts + Configura tus cuentas apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. - Get a comprehensive financial overview by adding your bank and brokerage accounts. + Obtén una visión financiera completa agregando tus cuentas bancarias y de corretaje. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities - Capture your activities + Captura tus actividades apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. - Record your investment activities to keep your portfolio up to date. + Registra tus actividades de inversión para mantener tu portafolio actualizado. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio - Monitor and analyze your portfolio + Monitorea y analiza tu portafolio apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. - Track your progress in real-time with comprehensive analysis and insights. + Sigue tu progreso en tiempo real con análisis e información detallada. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - No data available - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? - Ready to take control of your personal finances? + ¿Listo para tomar el control de tus finanzas personales? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts - Setup accounts + Configura tus cuentas apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication - Biometric Authentication + Autenticación biométrica apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + En Ghostfolio, la transparencia está en el centro de nuestros valores. Publicamos el código fuente como software de código abierto (OSS) bajo la licencia Licencia AGPL-3.0 y compartimos abiertamente métricas clave agregadas sobre el estado operativo de la plataforma. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users - Active Users + Usuarios activos apps/client/src/app/pages/open/open-page.html 40 @@ -4786,33 +4326,33 @@ 62 - + New Users - New Users + Nuevos usuarios apps/client/src/app/pages/open/open-page.html 51 - + Users in Slack community - Users in Slack community + Usuarios en la comunidad de Slack apps/client/src/app/pages/open/open-page.html 75 - + Contributors on GitHub - Contributors on GitHub + Colaboradores en GitHub apps/client/src/app/pages/open/open-page.html 89 - + Stars on GitHub - Stars on GitHub + Estrellas en GitHub apps/client/src/app/pages/landing/landing-page.html 88 @@ -4822,9 +4362,9 @@ 103 - + Pulls on Docker Hub - Pulls on Docker Hub + Descargas en Docker Hub apps/client/src/app/pages/landing/landing-page.html 106 @@ -4834,2803 +4374,3762 @@ 117 - + Uptime - Uptime + Tiempo de actividad apps/client/src/app/pages/open/open-page.html 132 - + Export Data - Export Data + Exportar datos apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 Currencies - Currencies + Monedas apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 - + Our - Our + Nuestro apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 6 - + Visit - Visit + Visitar apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 28 - + Discover other exciting Open Source Software projects - Discover other exciting Open Source Software projects + Descubre otros proyectos emocionantes de software de código abierto apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 9 - - Frequently Asked Questions (FAQ) - Frequently Asked Questions (FAQ) - - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 - - - apps/client/src/app/pages/faq/saas/saas-page.html - 4 - - - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 - - - + Check out the numerous features of Ghostfolio to manage your wealth - Check out the numerous features of Ghostfolio to manage your wealth + Descubra las numerosas funciones de Ghostfolio para gestionar su patrimonio apps/client/src/app/pages/features/features-page.html - 6 + 7 - + Discover the latest Ghostfolio updates and insights on personal finance - Discover the latest Ghostfolio updates and insights on personal finance + Conoce las últimas actualizaciones de Ghostfolio y obtén información sobre finanzas personales apps/client/src/app/pages/blog/blog-page.html 7 - + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Si prefieres ejecutar Ghostfolio en tu propia infraestructura, puedes encontrar el código fuente e instrucciones adicionales en GitHub. apps/client/src/app/pages/pricing/pricing-page.html - 26 + 14 - + Manage your wealth like a boss - Manage your wealth like a boss + Gestiona tu patrimonio como un jefe apps/client/src/app/pages/landing/landing-page.html - 5 + 6 - + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - - apps/client/src/app/pages/landing/landing-page.html - 9 - - - - Get Started - Empezar + Ghostfolio es un panel de control de código abierto y centrado en la privacidad para tus finanzas personales. Analiza la asignación de tus activos, conoce tu patrimonio neto y toma decisiones de inversión sólidas basadas en datos. apps/client/src/app/pages/landing/landing-page.html - 41 - - - apps/client/src/app/pages/pricing/pricing-page.html - 324 + 10 - + Monthly Active Users - Monthly Active Users + Usuarios activos mensuales apps/client/src/app/pages/landing/landing-page.html 70 - + As seen in - As seen in + Visto en apps/client/src/app/pages/landing/landing-page.html 115 - + Protect your assets. Refine your personal investment strategy. - Protect your assets. Refine your personal investment strategy. + Protege tus assets. Mejora tu estrategia de inversión personal. apps/client/src/app/pages/landing/landing-page.html - 225 + 226 - + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio permite a las personas ocupadas hacer un seguimiento de acciones, ETFs o criptomonedas sin ser rastreadas. apps/client/src/app/pages/landing/landing-page.html - 229 + 230 - + 360° View - 360° View + Vista 360° apps/client/src/app/pages/landing/landing-page.html 240 - + Web3 Ready - Web3 Ready + Preparado para Web3 apps/client/src/app/pages/landing/landing-page.html 251 - + Use Ghostfolio anonymously and own your financial data. - Use Ghostfolio anonymously and own your financial data. - - apps/client/src/app/pages/landing/landing-page.html - 253 - - - - Open Source - Open Source + Usa Ghostfolio de forma anónima y sé dueño de tus datos financieros. apps/client/src/app/pages/landing/landing-page.html - 261 + 254 - + Benefit from continuous improvements through a strong community. - Benefit from continuous improvements through a strong community. + Disfruta de mejoras continuas gracias a una comunidad sólida. apps/client/src/app/pages/landing/landing-page.html - 263 + 264 - + Why Ghostfolio? - Why Ghostfolio? + ¿Por qué Ghostfolio? apps/client/src/app/pages/landing/landing-page.html 272 - + Ghostfolio is for you if you are... - Ghostfolio is for you if you are... + Ghostfolio es para ti si estás... apps/client/src/app/pages/landing/landing-page.html - 273 + 274 - + trading stocks, ETFs or cryptocurrencies on multiple platforms - trading stocks, ETFs or cryptocurrencies on multiple platforms + operando con acciones, ETFs o criptomonedas en múltiples plataformas apps/client/src/app/pages/landing/landing-page.html 280 - + pursuing a buy & hold strategy - pursuing a buy & hold strategy + persiguiendo una compra & mantener estrategia apps/client/src/app/pages/landing/landing-page.html 286 - + interested in getting insights of your portfolio composition - interested in getting insights of your portfolio composition + interesado en obtener información sobre la composición de tu portafolio apps/client/src/app/pages/landing/landing-page.html 291 - + valuing privacy and data ownership - valuing privacy and data ownership + valorando la privacidad y la propiedad de tus datos apps/client/src/app/pages/landing/landing-page.html 296 - + into minimalism - into minimalism + en el minimalismo apps/client/src/app/pages/landing/landing-page.html 299 - + caring about diversifying your financial resources - caring about diversifying your financial resources + preocuparse por diversificar tus recursos financieros apps/client/src/app/pages/landing/landing-page.html 303 - + interested in financial independence - interested in financial independence + interesado en la independencia financiera apps/client/src/app/pages/landing/landing-page.html 307 - + saying no to spreadsheets in - saying no to spreadsheets in + diciendo no a las hojas de cálculo en apps/client/src/app/pages/landing/landing-page.html 311 - + still reading this list - still reading this list + todavía leyendo esta lista apps/client/src/app/pages/landing/landing-page.html 314 - + Learn more about Ghostfolio - Learn more about Ghostfolio + Más información sobre Ghostfolio apps/client/src/app/pages/landing/landing-page.html 319 - + What our users are saying - What our users are saying + Lo que nuestros usuarios están diciendo apps/client/src/app/pages/landing/landing-page.html - 327 + 328 - + Members from around the globe are using Ghostfolio Premium - Members from around the globe are using Ghostfolio Premium + Miembros de todo el mundo están usando Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 366 + 367 - + How does Ghostfolio work? - How does Ghostfolio work? + ¿Cómo Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 383 + 384 - + Sign up anonymously* - Sign up anonymously* + Regístrate de forma anónima* apps/client/src/app/pages/landing/landing-page.html 392 - + * no e-mail address nor credit card required - * no e-mail address nor credit card required + * no se requiere dirección de correo electrónico ni tarjeta de crédito apps/client/src/app/pages/landing/landing-page.html 394 - + Add any of your historical transactions - Add any of your historical transactions + Agrega cualquiera de tus transacciones históricas apps/client/src/app/pages/landing/landing-page.html - 405 + 406 - + Get valuable insights of your portfolio composition - Get valuable insights of your portfolio composition + Obtén información valiosa sobre la composición de tu portafolio apps/client/src/app/pages/landing/landing-page.html - 417 + 418 - + Are you ready? - Are you ready? - - apps/client/src/app/pages/landing/landing-page.html - 431 - - - - Live Demo - Live Demo - - apps/client/src/app/pages/landing/landing-page.html - 49 - + ¿Estás listo? apps/client/src/app/pages/landing/landing-page.html - 451 + 432 - + Get the full picture of your personal finances across multiple platforms. - Get the full picture of your personal finances across multiple platforms. + Obtén una visión completa de tus finanzas personales en múltiples plataformas. apps/client/src/app/pages/landing/landing-page.html - 242 + 243 - + Get started in only 3 steps - Get started in only 3 steps + Comienza en solo 3 pasos apps/client/src/app/pages/landing/landing-page.html 386 - + faq preguntas-mas-frecuentes - snake-case + kebab-case - apps/client/src/app/app.component.ts - 77 - - - apps/client/src/app/core/paths.ts - 3 - - - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 - - - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 245 - + features funcionalidades - snake-case + kebab-case - apps/client/src/app/app.component.ts - 78 - - - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 255 + + + about + sobre + kebab-case - apps/client/src/app/core/paths.ts - 4 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 214 + + + privacy-policy + politica-de-privacidad + kebab-case - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 207 + + + license + licencia + kebab-case - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + mercados + kebab-case - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 260 - - about - sobre - snake-case + + pricing + precios + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 270 + + + register + registro + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + recursos + kebab-case - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/about/about-page.component.ts - 63 - - - apps/client/src/app/pages/about/about-page.component.ts - 74 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 322 + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Esta página de resumen presenta una colección seleccionada de herramientas de finanzas personales, comparadas con la alternativa de código abierto Ghostfolio. Si valoras la transparencia, la privacidad de los datos y la colaboración comunitaria, Ghostfolio ofrece una excelente oportunidad para tomar el control de tu gestión financiera. - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Explora los siguientes enlaces para comparar una variedad de herramientas de finanzas personales con Ghostfolio. - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + Open Source Alternative to + Alternativa de software libre a - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + The Open Source Alternative to + La alternativa de software libre a - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + ¿Estás buscando una alternativa de código abierto a ? Ghostfolio es una potente herramienta de gestión de carteras que ofrece a los usuarios una plataforma integral para rastrear, analizar y optimizar sus inversiones. Ya seas un inversor con experiencia o estés comenzando, Ghostfolio ofrece una interfaz intuitiva y una amplia gama de funcionalidades para ayudarte a tomar decisiones informadas y tener el control de tu futuro financiero. - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio es un software de código abierto (OSS), que ofrece una alternativa rentable a lo que lo hace especialmente adecuado para personas con un presupuesto ajustado, como aquellas que buscan la Independencia Financiera y Jubilación Anticipada (FIRE). Al aprovechar los esfuerzos colectivos de una comunidad de desarrolladores y entusiastas de las finanzas personales, Ghostfolio mejora continuamente sus capacidades, seguridad y experiencia de usuario. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Analicemos en detalle la tabla comparativa entre Ghostfolio y que encontrarás a continuación, para obtener una comprensión completa de cómo se posiciona Ghostfolio en relación con . Exploraremos diversos aspectos como funcionalidades, privacidad de los datos, precios y más, lo que te permitirá tomar una decisión bien fundamentada según tus necesidades personales. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - privacy-policy - politica-de-privacidad - snake-case + + open-source-alternative-to + alternativa-de-software-libre-a + kebab-case - apps/client/src/app/app.component.ts - 75 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/core/paths.ts - 8 + libs/common/src/lib/routes/routes.ts + 324 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Ten en cuenta que la información proporcionada en la tabla comparativa entre Ghostfolio y se basa en nuestra investigación y análisis independientes. Este sitio web no está afiliado con ni con ningún otro producto mencionado en la comparación. Dado que el panorama de las herramientas de finanzas personales evoluciona constantemente, es fundamental verificar cualquier detalle específico o cambio directamente en la página oficial del producto correspondiente. ¿Los datos necesitan una actualización? Ayúdanos a mantener la información precisa en GitHub. - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - license - licencia - snake-case + + Ready to take your investments to the next level? + ¿Listo para llevar sus inversiones al siguiente nivel? - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Switzerland + Suiza - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/ui/src/lib/i18n.ts + 96 - - markets - mercados - snake-case + + Global + Global - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/components/header/header.component.ts - 83 + libs/ui/src/lib/i18n.ts + 16 + + + (Last 24 hours) + (Últimas 24 horas) - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/pages/open/open-page.html + 37 + + + (Last 30 days) + (Últimos 30 días) - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/open/open-page.html + 59 + + + (Last 90 days) + (Últimos 90 días) - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/open/open-page.html + 127 + + + Choose or drop a file here + Elige o suelta un archivo aquí - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + You are using the Live Demo. + Estás usando la demostración en vivo. - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/app.component.html + 12 + + + One-time fee, annual account fees + Tarifa única, tarifas anuales de la cuenta - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - pricing - precios - snake-case + + Distribution of corporate earnings + Distribución de ganancias corporativas - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Fee + Tarifa - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/components/header/header.component.ts - 84 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - apps/client/src/app/components/header/header.component.ts - 89 + libs/ui/src/lib/i18n.ts + 37 + + + Revenue for lending out money + Ingresos por prestar dinero - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + Add Tag + Agregar etiqueta - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + Do you really want to delete this tag? + ¿Realmente deseas eliminar esta etiqueta? - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Actualizar etiqueta - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Añadir etiqueta - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Currency Cluster Risks + Riesgos de clúster de divisas - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + Account Cluster Risks + Riesgos de clúster de cuentas - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Transfer Cash Balance + Transferir saldo de efectivo - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Version + Versión - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + From + Desde - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + To + A - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + Transfer + Transferir - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + Membership + Membresía - libs/ui/src/lib/membership-card/membership-card.component.ts + libs/common/src/lib/routes/routes.ts 31 - - - register - registro - snake-case - apps/client/src/app/app.component.ts - 81 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Acceso - apps/client/src/app/components/header/header.component.ts - 90 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Perfil de activo - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Do you really want to delete this asset profile? + ¿Realmente deseas eliminar este perfil de activo? - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Buscar - apps/client/src/app/pages/faq/saas/saas-page.component.ts + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 16 + + + Add Manually + Añadir manualmente - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio es un dashboard de finanzas personales para hacer un seguimiento de tus activos como acciones, ETFs o criptodivisas a través de múltiples plataformas. - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Último máximo histórico - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - resources - recursos - snake-case + + User + Usuario - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs tabla comparativa - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + Open Source Wealth Management Software + Software de gestión de patrimonio de código abierto - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + aplicación, activo, criptomoneda, panel, ETF, finanzas, gestión, rendimiento, cartera, software, acciones, comercio, riqueza, web3 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/i18n/i18n-page.html 10 + + + Oops, cash balance transfer has failed. + Oops, el saldo de efectivo no se ha transferido. - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Miedo extremo - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Avaricia extrema - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Neutral - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + ¡Ups! No se pudieron analizar los datos históricos. - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + ¿Realmente deseas eliminar este mensaje del sistema? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + Tendencia de 50 días - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + Tendencia de 200 días - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + Cash Balances + Saldos de efectivo - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + Starting from + A partir de - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + + Do you really want to delete this account balance? + ¿Realmente desea eliminar el saldo de esta cuenta? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Explore the links below to compare a variety of personal finance tools with Ghostfolio. + + If a translation is missing, kindly support us in extending it here. + Si falta una traducción, por favor ayúdenos a ampliarla. here. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Open Source Alternative to - Alternativa de software libre a + + The current market price is + El precio actual de mercado es - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Open Source Alternative to - Alternativa de software libre a + + Test + Prueba - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - The Open Source Alternative to - La alternativa de software libre a + + Date Range + Rango de fechas - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + libs/ui/src/lib/assistant/assistant.html + 143 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + + Permission + Permiso - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/access-table/access-table.component.html 18 - - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html 32 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + + Restricted view + Vista restringida - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/components/access-table/access-table.component.html + 26 - - - open-source-alternative-to - alternativa-de-software-libre-a - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 + + + Oops! Could not grant access. + ¡Ups! No se pudo otorgar acceso. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + + Private + Privado - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - Ready to take your investments to the next level? - ¿Listo para llevar sus inversiones al siguiente nivel? + + Job Queue + Cola de trabajos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + libs/common/src/lib/routes/routes.ts + 46 - - Get Started - Get Started + + Market data is delayed for + Los datos del mercado se retrasan por - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 - - Switzerland - Switzerland + + Investment + Inversión + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + 86 + + + Absolute Asset Performance + Rendimiento absoluto de los activos - libs/ui/src/lib/i18n.ts - 90 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Global - Global + + Asset Performance + Rendimiento de activos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + Absolute Currency Performance + Rendimiento absoluto de divisas - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 - - (Last 24 hours) - (Last 24 hours) + + Currency Performance + Rendimiento de la moneda - apps/client/src/app/pages/open/open-page.html - 37 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 - - (Last 30 days) - (Last 30 days) + + Absolute Net Performance + Rendimiento neto absoluto - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + Net Performance + Rendimiento neto - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 - - (Last 90 days) - (Last 90 days) + + Week to date + Semana hasta la fecha - apps/client/src/app/pages/open/open-page.html - 127 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Choose or drop a file here - Choose or drop a file here + + WTD + WTD - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - You are using the Live Demo. - You are using the Live Demo. + + Month to date + Mes hasta la fecha - apps/client/src/app/app.component.html - 12 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - One-time fee, annual account fees - One-time fee, annual account fees + + MTD + MTD - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Distribution of corporate earnings - Distribution of corporate earnings + + Year to date + El año hasta la fecha - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from + + View + Ver - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - Fee - Fee + + Oops! A data provider is experiencing the hiccups. + ¡Ups! Un proveedor de datos está experimentando problemas. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Si te jubilaras hoy, podrías retirar por año o por mes, basado en tus activos totales de y una tasa de retiro del 4%. + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + + Reset Filters + Reiniciar filtros + + libs/ui/src/lib/assistant/assistant.html + 238 + + + + year + año + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + años + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Apply Filters + Aplicar filtros + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + Data Gathering + Recopilación de datos + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + General + General + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Nube + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Autoalojamiento + + apps/client/src/app/pages/faq/faq-page.component.ts + 60 + + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + auto-alojado + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + ¡Vaya! Parece que estás haciendo demasiadas solicitudes. Por favor, reduce la velocidad un poco. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + My Account + Mi cuenta + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Active + Activo + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Cerrado + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Indonesia + Indonesia + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Actividad + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Dividend Yield + Rendimiento por dividendo + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Execute Job + Ejecutar Tarea + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Priority + Prioridad + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + This action is not allowed. + Esta acción no está permitida. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Liquidity + Liquidez + + libs/ui/src/lib/i18n.ts + 48 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Comprar y vender + + libs/ui/src/lib/i18n.ts + 8 + + + + Delete Activities + Eliminar actividades + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internacionalización + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + ¿Estás seguro de querer borrar tu cuenta de Ghostfolio? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Zona peligrosa + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Eliminar cuenta + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Por tenencia de ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Aproximación basada en las principales participaciones de cada ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Únete ahora o consulta la cuenta de ejemplo + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + ¡Ups! Hubo un error al configurar la autenticación biométrica. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Mostrar más + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Puntos de referencia + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Borrar Perfiles + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Estas seguro de borrar estos perfiles? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + ¡Ups! No se pudieron eliminar los perfiles. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + Tabla + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Grafico + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + ¿Te gustaría refinar tu estrategia de inversión personal? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternativa + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + Aplicación + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Presupuestación + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Comunidad + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Family Office + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Inversor + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Código abierto + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Finanzas personales + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Privacidad + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Software + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Herramienta + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Experiencia del usuario + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Riqueza + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Gestión de patrimonios + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Australia + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Austria + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Bélgica + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bulgaria + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Canadá + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + República Checa + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finlandia + + libs/ui/src/lib/i18n.ts + 83 + + + + France + Francia + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Alemania + + libs/ui/src/lib/i18n.ts + 85 + + + + India + India + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Italia + + libs/ui/src/lib/i18n.ts + 88 + + + + Netherlands + Países Bajos + + libs/ui/src/lib/i18n.ts + 90 + + + + New Zealand + Nueva Zelanda + + libs/ui/src/lib/i18n.ts + 91 + + + + Poland + Polonia + + libs/ui/src/lib/i18n.ts + 92 + + + + Romania + Rumanía + + libs/ui/src/lib/i18n.ts + 93 + + + + South Africa + Sudáfrica + + libs/ui/src/lib/i18n.ts + 95 + + + + Thailand + Tailandia + + libs/ui/src/lib/i18n.ts + 97 + + + + United States + Estados Unidos + + libs/ui/src/lib/i18n.ts + 100 + + + + Error + Error + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + + Deactivate + Desactivar + + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Activar + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Inactive + Inactiva + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Cancel + Cancelar + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 + + + + Close + Cerca + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 + + + + Yes + + + libs/ui/src/lib/i18n.ts + 32 + + + + Copy link to clipboard + Copiar enlace al portapapeles + + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + + Portfolio Snapshot + Instantánea de la cartera + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 + + + + Change with currency effect Change + Change with currency effect Change + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 + + + + Performance with currency effect Performance + Performance with currency effect Performance + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 + + + + Threshold Min + Umbral mínimo + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 + + + + Threshold Max + Umbral máximo + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 + + + + Customize + Personalizar + + apps/client/src/app/components/rule/rule.component.html + 67 + + + + No auto-renewal. + Sin renovación automática. + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 + + + + This year + Este año + + apps/client/src/app/pages/public/public-page.html + 42 + + + + From the beginning + Desde el principio + + apps/client/src/app/pages/public/public-page.html + 60 + + + + Oops! Invalid currency. + ¡Ups! Moneda inválida. + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 + + + + This page has been archived. + Esta página ha sido archivada. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 + + + + is Open Source Software + es software de código abierto + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 + - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Interest - Interest + + is not Open Source Software + no es software de código abierto - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Revenue for lending out money - Revenue for lending out money - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Add Tag - Add Tag + + can be self-hosted + se puede autoalojar - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - - - Do you really want to delete this tag? - Do you really want to delete this tag? - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Update tag - Update tag + + cannot be self-hosted + no se puede autoalojar - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Add tag - Add tag - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Currency Cluster Risks - Currency Cluster Risks + + can be used anonymously + se puede usar de forma anónima - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Account Cluster Risks - Account Cluster Risks - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Transfer Cash Balance - Transfer Cash Balance + + cannot be used anonymously + no se puede usar de forma anónima - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Benchmark - Benchmark + + offers a free plan + ofrece un plan gratuito - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Version - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Settings - Settings + + does not offer a free plan + no ofrece un plan gratuito - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - From - From - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - To - To + + Oops! Could not find any assets. + ¡Ups! No se pudieron encontrar activos. - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - Transfer - Transfer + + Data Providers + Proveedores de datos - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Membership - Membership + + Set API key + Configurar clave API - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 + + + Get access to 80’000+ tickers from over 50 exchanges + Accede a más de 80’000 tickers de más de 50 bolsas - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + libs/ui/src/lib/i18n.ts + 24 - - Access - Access + + Ukraine + Ucrania - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + libs/ui/src/lib/i18n.ts + 98 + + + Join now + Únete ahora - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Find holding... - Find holding... + + Glossary + Glosario - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - No entries... - No entries... - libs/ui/src/lib/assistant/assistant.html - 63 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - libs/ui/src/lib/assistant/assistant.html - 84 + libs/common/src/lib/routes/routes.ts + 293 - - Asset Profile - Asset Profile + + Guides + Guías - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Do you really want to delete this asset profile? - Do you really want to delete this asset profile? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Search - Search - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + libs/common/src/lib/routes/routes.ts + 301 - - Add Manually - Add Manually + + guides + guias + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + libs/common/src/lib/routes/routes.ts + 296 - - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio es un dashboard de finanzas personales para hacer un seguimiento de tus activos como acciones, ETFs o criptodivisas a través de múltiples plataformas. - apps/client/src/app/pages/i18n/i18n-page.html - 4 + libs/common/src/lib/routes/routes.ts + 299 - - Last All Time High - Last All Time High + + glossary + glosario + kebab-case - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + libs/common/src/lib/routes/routes.ts + 288 + + + libs/common/src/lib/routes/routes.ts + 291 - - User - User + + Threshold range + Rango umbral - apps/client/src/app/components/admin-users/admin-users.html - 29 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Ghostfolio vs comparison table - Ghostfolio vs tabla comparativa + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray utiliza análisis estático para descubrir posibles problemas y riesgos en tu cartera. Ajusta las reglas a continuación y define umbrales personalizados para alinearlos con tu estrategia de inversión personal. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Open Source Wealth Management Software - Open Source Wealth Management Software + + Economic Market Cluster Risks + Riesgos de clúster del mercado económico - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + + of + de - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Oops, cash balance transfer has failed. - Oops, cash balance transfer has failed. + + daily requests + solicitudes diarias - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Extreme Fear - Extreme Fear + + Remove API key + Eliminar clave API - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Extreme Greed - Extreme Greed + + Do you really want to delete the API key? + ¿Realmente deseas eliminar la clave API? - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Neutral - Neutral + + Please enter your Ghostfolio API key: + Ingrese su clave API de Ghostfolio: - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Oops! Could not parse historical data. - Oops! Could not parse historical data. + + API Requests Today + Solicitudes de API hoy - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Do you really want to delete this system message? - Do you really want to delete this system message? + + Could not generate an API key + No se pudo generar una clave API - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - 50-Day Trend - 50-Day Trend + + Set this API key in your self-hosted environment: + Configure esta clave API en su entorno autohospedado: - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - 200-Day Trend - 200-Day Trend + + Ghostfolio Premium Data Provider API Key + Clave API del proveedor de datos premium de Ghostfolio - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - Cash Balances - Cash Balances + + Do you really want to generate a new API key? + ¿Realmente desea generar una nueva clave API? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Starting from - Starting from + + API Key + Clave API - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 + + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Genere la clave API del proveedor de datos premium de Ghostfolio para entornos autohospedados... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - year - year + + out of + fuera de - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 + + + rules align with your portfolio. + Las reglas se alinean con su cartera. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Do you really want to delete this account balance? - Do you really want to delete this account balance? + + Save + Ahorrar - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - - - is an invalid currency! - is an invalid currency! - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - If a translation is missing, kindly support us in extending it here. - If a translation is missing, kindly support us in extending it here. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - The current market price is - The current market price is - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 - - - Test - Test - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Date Range - Date Range - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Permission - Permiso - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + 65 - - - Restricted view - Restricted view - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Oops! Could not grant access. - Oops! Could not grant access. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Private - Privado + + Asset Class Cluster Risks + Riesgos del grupo de clases de activos - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Job Queue - Job Queue + + Me + Me - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Market data is delayed for - Market data is delayed for + + Received Access + Acceso recibido - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Investment - Inversión + + Please enter your Ghostfolio API key. + Por favor, ingresa tu clave API de Ghostfolio. - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 + + + AI prompt has been copied to the clipboard + El aviso de IA ha sido copiado al portapapeles apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 197 + + + Link has been copied to the clipboard + El enlace ha sido copiado al portapapeles - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Absolute Asset Performance - Absolute Asset Performance + + Regional Market Cluster Risks + Riesgos del mercado regional agrupados - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Asset Performance - Asset Performance + + Lazy + Perezoso - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Absolute Currency Performance - Absolute Currency Performance + + Instant + Instantáneo - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Currency Performance - Currency Performance + + Default Market Price + Precio de mercado por defecto - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Absolute Net Performance - Absolute Net Performance + + Mode + Modo - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Net Performance - Net Performance + + Selector + Selector - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Week to date - Week to date + + HTTP Request Headers + Encabezados de solicitud HTTP - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - WTD - WTD + + end of day + final del día - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Month to date - Month to date + + real-time + en tiempo real - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - MTD - MTD + + Open Duck.ai + Abrir Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Year to date - Year to date + + Create + Crear - libs/ui/src/lib/assistant/assistant.component.ts - 231 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - View - Ver + + Change + Cambiar - apps/client/src/app/components/access-table/access-table.component.html - 23 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Oops! A data provider is experiencing the hiccups. - Oops! A data provider is experiencing the hiccups. + + Performance + Rendimiento - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Reset Filters - Reiniciar filtros - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - year - año - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - - years - años - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Apply Filters - Aplicar filtros + + Copy portfolio data to clipboard for AI prompt + Copiar los datos del portafolio al portapapeles para el aviso de IA - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - Data Gathering - Data Gathering + + Copy AI prompt to clipboard for analysis + Copiar el aviso de IA al portapapeles para análisis - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - General - General + + Armenia + Armenia - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/i18n.ts + 75 - - Cloud - Nube + + British Virgin Islands + Islas Vírgenes Británicas - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + Singapur - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Self-Hosting - Self-Hosting + + Terms and Conditions + Terminos y condiciones - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 + + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Por favor, mantén tu token de seguridad a salvo. Si lo pierdes, no podrás recuperar tu cuenta. - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - self-hosting - auto alojado + + I understand that if I lose my security token, I cannot recover my account + Entiendo que si pierdo mi token de seguridad, no podré recuperar mi cuenta - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - FAQ - Preguntas frequentes + + Continue + Continuar - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 + + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Aquí está tu token de seguridad. Solo es visible una vez, por favor guárdalo y mantenlo en un lugar seguro. - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! It looks like you’re making too many requests. Please slow down a bit. + + Security token + Token de seguridad - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - My Account - Mi cuenta - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Active - Activo + + Do you really want to generate a new security token for this user? + ¿Realmente deseas generar un nuevo token de seguridad para este usuario? - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - Closed - Closed + + Generate Security Token + Generar token de seguridad - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Activity - Activity + + United Kingdom + Reino Unido - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + libs/ui/src/lib/i18n.ts + 99 - - Dividend Yield - Dividend Yield + + Terms of Service + Términos de servicio - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Execute Job - Ejecutar Tarea + + terms-of-service + terminos-de-servicio + kebab-case - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + libs/common/src/lib/routes/routes.ts + 212 - - - Priority - Prioridad - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + libs/common/src/lib/routes/routes.ts + 215 - - This action is not allowed. - This action is not allowed. + + Terms of Service + Términos de servicio - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/app.component.html + 112 - - - Liquidity - Liquidez - libs/ui/src/lib/i18n.ts - 48 + libs/common/src/lib/routes/routes.ts + 217 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + and I agree to the Terms of Service. + and I agree to the Terms of Service. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Buy and sell - Comprar y vender + + () is already in use. + () is already in use. - libs/ui/src/lib/i18n.ts - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Delete Activities - Delete Activities + + An error occurred while updating to (). + An error occurred while updating to (). - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Internationalization - Internacionalización + + Apply + Aplicar - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Do you really want to close your Ghostfolio account? - ¿Estás seguro de querer borrar tu cuenta de Ghostfolio? + + with API access for + con acceso a la API para - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Danger Zone - Zona peligrosa + + Gather Recent Historical Market Data + Recopilar datos históricos recientes del mercado - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Close Account - Eliminar cuenta + + Gather All Historical Market Data + Recopilar todos los datos históricos del mercado - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - By ETF Holding - By ETF Holding + + Gather Historical Market Data + Recopilar datos históricos del mercado - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Data Gathering is off + La recopilación de datos está desactivada - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Join now or check out the example account - Join now or check out the example account + + Performance Calculation + Cálculo de rendimiento - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + someone + alguien - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Show more - Mostrar más + + Add asset to watchlist + Añadir activo a la lista de seguimiento - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Benchmarks - Benchmarks + + Watchlist + Lista de seguimiento - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Delete Profiles - Borrar Perfiles - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/pages/features/features-page.html + 197 - - - Do you really want to delete these profiles? - Estas seguro de borrar estos perfiles? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + libs/common/src/lib/routes/routes.ts + 110 - - Oops! Could not delete profiles. - Oops! Could not delete profiles. + + Do you really want to delete this item? + ¿Realmente deseas eliminar este elemento? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Table - Tabla + + Log out + Finalizar la sesión - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/header/header.component.html + 329 - - Chart - Grafico + + Calculations are based on delayed market data and may not be displayed in real-time. + Los cálculos se basan en datos de mercado retrasados ​​y es posible que no se muestren en tiempo real. - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-market/home-market.html + 44 - - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/components/markets/markets.html + 53 - - Alternative - Alternative + + changelog + registro-decambios + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + libs/common/src/lib/routes/routes.ts + 180 - - - App - App - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + libs/common/src/lib/routes/routes.ts + 183 - - Budgeting - Budgeting + + Demo user account has been synced. + La cuenta de usuario de demostración se ha sincronizado. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Community - Community + + Sync Demo User Account + Sincronizar cuenta de usuario de demostración - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Family Office - Family Office + + Set up + Fondo de Emergencia: Establecer - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Investor - Investor + + No emergency fund has been set up + No se ha creado ningún fondo de emergencia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Open Source - Open Source + + An emergency fund has been set up + Se ha creado un fondo de emergencia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Personal Finance - Personal Finance + + Fee Ratio + Relación de tarifas - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Privacy - Privacy + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Las tarifas superan el ${thresholdMax}% de su inversión inicial (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Software - Software + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Las tarifas no superan el ${thresholdMax}% de su inversión inicial (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - Tool - Tool + + Name + Nombre - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - User Experience - User Experience + + Find holding or page... + Buscar explotación o página... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Wealth - Wealth + + Quick Links + Enlaces rápidos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.html + 56 - - Wealth Management - Wealth Management + + Asset Profiles + Perfiles de activos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 112 - - Australia - Australia + + Live Demo + Demostración en vivo - libs/ui/src/lib/i18n.ts - 73 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Austria - Austria - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Belgium - Belgium - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bulgaria + + Open Source Alternative to + Alternativa de software libre a - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Canada + + Single Account + Cuenta única - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - Czech Republic + + Your net worth is managed by a single account + Tu patrimonio neto está gestionado por una única cuenta - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finland + + Your net worth is managed by ${accountsLength} accounts + Tu patrimonio neto está gestionado por ${accountsLength} cuentas - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - France + + personal-finance-tools + herramientas-financieras-personales + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 - - - Germany - Germany - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 315 - - - India - India - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italy + + markets + markets + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 - - - Netherlands - Netherlands - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 307 - - New Zealand - New Zealand + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Poland - Poland + + Get Access + Get Access - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Romania - Romania + + Learn more + Learn more - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - South Africa - South Africa + + Limited Offer! + Limited Offer! - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Thailand - Thailand + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - United States - United States + + Available + Available - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Error - Error + + Unavailable + Unavailable - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Deactivate - Deactivate + + new + new - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Activate - Activate - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Inactive - Inactive + + Investment + Investment - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Cancel - Cancel + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Close - Close + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Yes - Yes + + Equity + Equity - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Change with currency effect Change - Change with currency effect Change + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Performance with currency effect Performance - Performance with currency effect Performance + + Fixed Income + Fixed Income - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Close - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Customize - Customize + + Investment: Base Currency + Investment: Base Currency - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today - Today + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - This year - This year + + Investment + Investment - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - From the beginning - From the beginning + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - Oops! Invalid currency. - Oops! Invalid currency. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - This page has been archived. - This page has been archived. + + start + start + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 336 - - - is Open Source Software - is Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 337 - - is not Open Source Software - is not Open Source Software + + Do you really want to generate a new security token? + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is Open Source Software - is Open Source Software + + Generate + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is not Open Source Software - is not Open Source Software + + Stocks + Stocks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be self-hosted - cannot be self-hosted + + Cryptocurrencies + Cryptocurrencies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/markets/markets.component.ts + 53 + + + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - can be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - cannot be self-hosted + + Manage Asset Profile + Manage Asset Profile - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - can be used anonymously + + Alternative Investment + Alternative Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - cannot be used anonymously + + Collectible + Collectible - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - can be used anonymously + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - cannot be used anonymously - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Riesgos de los grupos de mercados regionales - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + No se encontraron resultados... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Mercados desarrollados - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Mercados emergentes - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No se han configurado cuentas - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Su patrimonio neto es administrado por 0 cuentas - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europe - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japón - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + La contribución al mercado japonés de su inversión actual (${valueRatio}%) supera el ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + La contribución al mercado japonés de su inversión actual (${valueRatio}%) es inferior a ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + La contribución al mercado japonés de su inversión actual (${valueRatio}%) está dentro del rango de ${thresholdMin}% y ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + Norteamérica - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + La contribución del mercado de América del Norte de su inversión actual (${valueRatio}%) supera el ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + La contribución al mercado de América del Norte de su inversión actual (${valueRatio}%) es inferior a ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + La contribución al mercado de América del Norte de su inversión actual (${valueRatio}%) está dentro del rango de ${thresholdMin}% y ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Encuentra Ghostfolio en GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Únete a la comunidad de Ghostfolio Slack - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Siga a Ghostfolio en X (anteriormente Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Enviar un correo electrónico - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Siga a Ghostfolio en LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio es una empresa independiente y autónoma - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Soporte Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index a01b96513..40f555f62 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -1,15 +1,15 @@ - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. Le risque de perte en investissant peut être important. Il est déconseillé d’investir de l’argent dont vous pourriez avoir besoin à court terme. apps/client/src/app/app.component.html - 200 + 221 - + Alias Alias @@ -21,7 +21,7 @@ 11 - + Grantee Bénéficiaire @@ -29,7 +29,7 @@ 11 - + Type Type @@ -49,7 +49,7 @@ 161 - + Details Détails @@ -57,7 +57,7 @@ 33 - + Revoke Révoquer @@ -70,10 +70,10 @@ Voulez-vous vraiment révoquer cet accès ? apps/client/src/app/components/access-table/access-table.component.ts - 67 + 108 - + Platform Plateforme @@ -89,47 +89,7 @@ 48 - - Activities - Activités - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 - - - + Name Nom @@ -138,23 +98,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -166,7 +130,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -185,7 +149,7 @@ 88 - + Total Total @@ -193,7 +157,7 @@ 55 - + Currency Devise @@ -202,11 +166,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -218,14 +182,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Balance Cash @@ -241,7 +205,7 @@ 34 - + Value Valeur @@ -258,31 +222,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -309,64 +257,56 @@ 102 - + Edit Modifier apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Supprimer apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -376,40 +316,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? Voulez-vous vraiment supprimer ce compte ? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 - - - - Symbol - Symbole - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + 148 - + Data Source Source Données @@ -418,18 +338,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Tentatives @@ -437,7 +357,7 @@ 83 - + Created Créé @@ -445,7 +365,7 @@ 92 - + Finished Terminé @@ -453,15 +373,19 @@ 101 - + Status Statut apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Delete Jobs Supprimer Tâches @@ -469,23 +393,27 @@ 151 - + Asset Profiles - Profil d’Actifs + Profils d’Actifs - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data - Données de Marché Historiques + Données historiques du marché apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Voir Données @@ -493,7 +421,7 @@ 166 - + View Stacktrace Voir la Stacktrace @@ -501,7 +429,7 @@ 173 - + Delete Job Supprimer Tâche @@ -509,7 +437,7 @@ 180 - + Details for Détails pour @@ -517,12 +445,12 @@ 2 - + Date Date apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -537,336 +465,184 @@ 6 - + Market Price - Prix du Marché + Prix du marché apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Annuler + + Filter by... + Filtrer par... - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + Première Activité - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 + + + Activities Count + Nombre d’Activités - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + Historical Data + Données Historiques - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 + + + Sectors Count + Nombre de Secteurs - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + Countries Count + Nombre de Pays - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 - - Save - Sauvegarder + + Gather Profile Data + Obtenir les Données du Profil + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 44 + + + Refresh + Rafraîchir - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 + + + Sector + Secteur - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 + + + Country + Pays - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - - Filter by... - Filtrer par... - - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 - - - - Asset Class - Classe d’Actifs - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 - - - libs/ui/src/lib/assistant/assistant.html - 166 - - - - Asset Sub Class - Sous-classe d’Actifs - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 - - - - First Activity - Première Activité - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 - - - - Activities Count - Nombre d’Activités - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 - - - - Historical Data - Données Historiques - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 - - - - Sectors Count - Nombre de Secteurs - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 - - - - Countries Count - Nombre de Pays - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 - - - - Gather Recent Data - Obtenir les Données Récentes - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 - - - - Gather All Data - Obtenir toutes les Données - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 - - - - Gather Profile Data - Obtenir les Données du Profil - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Refresh - Rafraîchir - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 - - - - Sector - Secteur - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 - - - - Country - Pays - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Sectors Secteurs apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Pays apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Symbol Mapping Équivalence de Symboles apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 - + Note Note apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -874,15 +650,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 - - - - Please add a currency: - Veuillez ajouter une devise : - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + 275 @@ -890,15 +658,7 @@ Voulez-vous vraiment supprimer ce code promotionnel ? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 - - - - Do you really want to delete this currency? - Voulez-vous vraiment supprimer cette devise ? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + 194 @@ -906,7 +666,7 @@ Voulez-vous vraiment vider le cache ? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + 231 @@ -914,10 +674,10 @@ Veuillez définir votre message système : apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + 251 - + User Count Nombre d’Utilisateurs @@ -925,7 +685,7 @@ 13 - + Activity Count Nombre d’Activités @@ -933,7 +693,7 @@ 19 - + per User par Utilisateur @@ -941,112 +701,96 @@ 28 - - Exchange Rates - Taux de Conversion - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 - - - + Add Currency Ajouter Devise apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + Tags Étiquettes apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + User Signup Inscription de Nouveaux Utilisateurs apps/client/src/app/components/admin-overview/admin-overview.html - 111 + 34 - + Read-only Mode Mode Lecture Seule apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + System Message Message Système apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Définir Message apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Coupons Codes promotionnels apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Ajouter apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Maintenance apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Vider le Cache apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -1054,86 +798,38 @@ Voulez-vous vraiment supprimer cet·te utilisateur·rice ? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Utilisateur apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + 31 apps/client/src/app/components/header/header.component.html - 229 + 231 - - Registration - Inscription + + Engagement per Day + Engagement par Jour apps/client/src/app/components/admin-users/admin-users.html - 97 + 158 - - Accounts - Comptes - - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 - + + Last Request + Dernière Requête apps/client/src/app/components/admin-users/admin-users.html - 114 - - - apps/client/src/app/components/header/header.component.html - 54 - - - apps/client/src/app/components/header/header.component.html - 263 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 - - - apps/client/src/app/pages/accounts/accounts-page.html - 4 - - - - Engagement per Day - Engagement par Jour - - apps/client/src/app/components/admin-users/admin-users.html - 157 - - - - Last Request - Dernière Requête - - apps/client/src/app/components/admin-users/admin-users.html - 202 - - - - Performance - Performance - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + 204 - + Compare with... Comparer avec... @@ -1146,223 +842,87 @@ Portefeuille apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 - - - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 - - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 - - - - Benchmark - Référence - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 - - - - Current Market Mood - Sentiment Actuel du Marché - - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 - - - - Overview - Aperçu - - apps/client/src/app/components/header/header.component.html - 28 - - - apps/client/src/app/components/header/header.component.html - 245 - - - - Portfolio - Portefeuille - - apps/client/src/app/components/header/header.component.html - 41 - - - apps/client/src/app/components/header/header.component.html - 255 - - - - Admin Control - Contrôle Administrateur - - apps/client/src/app/components/header/header.component.html - 68 - - - apps/client/src/app/components/header/header.component.html - 279 - - - - Resources - Ressources - - apps/client/src/app/app.component.html - 64 - - - apps/client/src/app/components/header/header.component.html - 82 - - - apps/client/src/app/components/header/header.component.html - 291 - - - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 - - - - Pricing - Prix - - apps/client/src/app/app.component.html - 97 + 124 apps/client/src/app/components/header/header.component.html - 99 + 44 apps/client/src/app/components/header/header.component.html - 303 + 258 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + libs/common/src/lib/routes/routes.ts + 151 - - About - À propos - - apps/client/src/app/app.component.html - 70 - - - apps/client/src/app/components/header/header.component.html - 117 - + + Benchmark + Référence - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 - - - Me - Moi - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 - - My Ghostfolio - Mon Ghostfolio + + Current Market Mood + Sentiment actuel du marché - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 - + About Ghostfolio À propos de Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 326 apps/client/src/app/pages/about/overview/about-overview-page.html 5 - - Features - Fonctionnalités - - apps/client/src/app/app.component.html - 79 - - - apps/client/src/app/components/header/header.component.html - 351 - - - apps/client/src/app/pages/features/features-page.html - 5 - - - - Markets - Marchés - - apps/client/src/app/app.component.html - 61 - + + Get started + Démarrer apps/client/src/app/components/header/header.component.html - 398 - - - apps/client/src/app/components/home-market/home-market.html - 2 - - - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + 432 - + Sign in Se connecter apps/client/src/app/components/header/header.component.html - 412 + 422 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + apps/client/src/app/components/header/header.component.ts + 259 - - - Get started - Démarrer - apps/client/src/app/components/header/header.component.html - 422 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - - - Sign in - Se connecter - apps/client/src/app/app-routing.module.ts - 150 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/header/header.component.ts - 230 + libs/common/src/lib/routes/routes.ts + 157 @@ -1370,19 +930,23 @@ Oups! Jeton de Sécurité Incorrect. apps/client/src/app/components/header/header.component.ts - 245 + 274 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + 191 - + Manage Activities Gérer les Activités apps/client/src/app/components/home-holdings/home-holdings.html - 63 + 66 @@ -1390,11 +954,15 @@ Peur apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -1402,27 +970,27 @@ Avidité apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 - + Last Days derniers jours apps/client/src/app/components/home-market/home-market.html 7 - - - Summary - Résumé - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/components/markets/markets.html + 17 @@ -1430,7 +998,7 @@ Montant Total apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 @@ -1438,10 +1006,10 @@ Taux d’Épargne apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 - + Security Token Jeton de Sécurité @@ -1449,32 +1017,44 @@ 11 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - + or ou - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + 32 apps/client/src/app/pages/landing/landing-page.html - 47 + 48 apps/client/src/app/pages/landing/landing-page.html - 450 + 451 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1482,14 +1062,14 @@ apps/client/src/app/pages/register/register-page.html - 30 + 31 apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + 30 - + Sign in with Internet Identity Se connecter avec Internet Identity @@ -1497,7 +1077,7 @@ 42 - + Sign in with Google Se connecter avec Google @@ -1505,7 +1085,7 @@ 52 - + Stay signed in Rester connecté @@ -1513,43 +1093,15 @@ 61 - + Time in Market - Temps sur le Marché + Temps sur le marché apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html 3 - - Buy - Achat - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 - - - - Sell - Vente - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 - - - - Investment - Investissement - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - + Absolute Gross Performance Performance Absolue Brute @@ -1557,7 +1109,7 @@ 70 - + Absolute Net Performance Performance Absolue Nette @@ -1565,7 +1117,7 @@ 102 - + Net Performance Performance nette @@ -1573,7 +1125,7 @@ 117 - + Total Assets Actifs Totaux @@ -1581,208 +1133,128 @@ 143 - - Valuables - Biens - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Fonds d’Urgence - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Pouvoir d’Achat apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Excluded from Analysis Exclus de l’Analyse apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 - + Net Worth Fortune apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Performance annualisée apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividende - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 Please set the amount of your emergency fund. - Veuillez entrer le montant de votre fonds d’urgence : + Veuillez entrer le montant de votre fonds d’urgence : apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 - - - - Change - Différence - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 - - - - Average Unit Price - Prix Unitaire Moyen - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + 71 - + Minimum Price Prix Minimum apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Maximum Price Prix Maximum apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 143 - + Quantity Quantité apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Report Data Glitch Signaler une Erreur de Données apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 Today Aujourd’hui - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/public/public-page.html + 24 libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD CDA - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1A - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5A - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1790,7 +1262,7 @@ Cette fonctionnalité est momentanément indisponible. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -1798,15 +1270,15 @@ Veuillez réessayer plus tard. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + 186 @@ -1814,11 +1286,11 @@ Oups! Quelque chose s’est mal passé. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 184 @@ -1826,86 +1298,66 @@ D’accord apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About À propos - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Changelog - Historique des modifications apps/client/src/app/app.component.html - 77 - - - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + 70 - - - License - License - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/header/header.component.html + 375 - - - Privacy Policy - Politique de Vie Privée - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 220 - + Privacy Policy Politique de Vie Privée apps/client/src/app/app.component.html - 103 + 105 apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 + + libs/common/src/lib/routes/routes.ts + 209 + My Ghostfolio Mon Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 @@ -1914,15 +1366,19 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 - - Please enter your coupon code: - Veuillez entrer votre code promotionnel : + + Please enter your coupon code. + Veuillez entrer votre code promotionnel. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1930,7 +1386,7 @@ Le code promotionnel n’a pas pu être appliqué apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1938,7 +1394,7 @@ Le code promotionnel a été appliqué apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1946,7 +1402,7 @@ Rafraîchir apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1954,210 +1410,134 @@ Voulez-vous vraiment supprimer cette méthode de connexion ? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Compte - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Adhésion - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year par an apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Essayer Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Utiliser un Code Promotionnel apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Vue de Présentation apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Devise de Base apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Language Langue apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 - - - - Community - Communauté - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 + 56 - + Locale Paramètres régionaux + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Format de date et d’heure apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Appearance Apparence apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 - - - - Auto - Auto - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Clair apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Sombre apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 - + Zen Mode Mode Zen apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Sign in with fingerprint Se connecter avec empreinte apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + Experimental Features Fonctionnalités expérimentales apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 - + User ID ID d’utilisateur @@ -2166,18 +1546,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Accès donné apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Donner accès @@ -2185,7 +1565,7 @@ 7 - + Public Public @@ -2197,11 +1577,35 @@ Accounts Comptes - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 + + + apps/client/src/app/components/admin-users/admin-users.html + 115 + + + apps/client/src/app/components/header/header.component.html + 58 + + + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 - + Update account Mettre à jour compte @@ -2209,7 +1613,7 @@ 8 - + Add account Ajouter compte @@ -2217,15 +1621,7 @@ 10 - - Cash - Cash - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 - - - + Account ID ID du compte @@ -2235,139 +1631,139 @@ Market Data - Données de Marché + Données du marché - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Admin Control Contrôle Admin - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 - - - Users - Utilisateurs - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/components/header/header.component.html + 289 - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 64 - - Blog - Blog + + Users + Utilisateurs - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 61 - + Blog Blog apps/client/src/app/app.component.html - 73 + 74 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + 205 apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + 210 apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + 197 apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + 182 apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + 142 apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + 169 apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + 179 apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + 203 apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + 254 apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + 234 apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + 244 apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + 155 apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + 274 apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + 184 apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + 149 apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + 271 apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 190 apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + 168 apps/client/src/app/pages/blog/blog-page.html 5 + + libs/common/src/lib/routes/routes.ts + 225 + As you are already logged in, you cannot access the demo account. @@ -2381,91 +1777,167 @@ Frequently Asked Questions (FAQ) Questions Fréquentes (FAQ) - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Fonctionnalités - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Holdings Positions - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - apps/client/src/app/pages/home/home-page.component.ts - 42 + apps/client/src/app/pages/public/public-page.html + 70 - apps/client/src/app/pages/zen/zen-page.component.ts - 39 + libs/common/src/lib/routes/routes.ts + 90 + + + libs/common/src/lib/routes/routes.ts + 167 Summary Résumé - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 Markets Marchés - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 - - - Activities - Activités - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 + + + + Activities + Activités + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 + + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 + + + apps/client/src/app/components/admin-users/admin-users.html + 136 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 + + + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 - + Update activity Mettre à jour Activité @@ -2473,12 +1945,12 @@ 10 - + Add activity Ajouter Activité apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2488,61 +1960,53 @@ Sell Vente + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Nom, symbole, ou ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 124 - + Unit Price Prix Unitaire apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 214 libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Fee - Frais - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 234 - - Importing data... Import des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2550,7 +2014,7 @@ L’import est terminé apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 @@ -2558,10 +2022,10 @@ Validation des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + The following file formats are supported: Les formats de fichier suivants sont supportés : @@ -2569,7 +2033,7 @@ 90 - + Back Retour @@ -2581,7 +2045,7 @@ 178 - + Import Importer @@ -2594,30 +2058,26 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Allocations Répartitions - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - - - Allocations - Répartitions - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + libs/common/src/lib/routes/routes.ts + 133 - + Proportion of Net Worth Proportion de votre Fortune @@ -2625,7 +2085,7 @@ 12 - + By Account Par Compte @@ -2633,7 +2093,7 @@ 286 - + By Currency Par Devise @@ -2641,7 +2101,7 @@ 63 - + By Asset Class Par Classe d’Actifs @@ -2649,7 +2109,7 @@ 85 - + By Holding Par Position @@ -2657,7 +2117,7 @@ 107 - + By Sector Par Secteur @@ -2665,7 +2125,7 @@ 130 - + By Continent Par Continent @@ -2673,7 +2133,7 @@ 153 - + By Country Par Pays @@ -2681,7 +2141,7 @@ 264 - + Regions Régions @@ -2693,9 +2153,9 @@ 143 - + Developed Markets - Marchés Développés + Marchés développés apps/client/src/app/pages/portfolio/allocations/allocations-page.html 222 @@ -2705,9 +2165,9 @@ 160 - + Emerging Markets - Marchés Émergents + Marchés émergents apps/client/src/app/pages/portfolio/allocations/allocations-page.html 231 @@ -2717,7 +2177,7 @@ 169 - + Other Markets Autres marchés @@ -2733,20 +2193,36 @@ Analysis Analyse - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 138 Dividend Dividende + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts @@ -2758,7 +2234,7 @@ Dépôt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 @@ -2766,58 +2242,50 @@ Mensuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 - - - - Analysis - Analyse - - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + 88 - + Top Haut apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom Bas apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + Portfolio Evolution Évolution du Portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 - + Investment Timeline Historique des Investissements apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + Dividend Timeline Historique des Dividendes apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 - + FIRE FIRE @@ -2825,7 +2293,7 @@ 4 - + Calculator Calculatrice @@ -2833,7 +2301,7 @@ 7 - + 4% Rule Règle des 4% @@ -2841,51 +2309,55 @@ 40 - - Holdings - Positions + + Holdings + Positions - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + libs/ui/src/lib/assistant/assistant.html + 82 + + + Pricing + Prix - apps/client/src/app/components/home-holdings/home-holdings.html - 4 + apps/client/src/app/app.component.html + 99 - apps/client/src/app/pages/public/public-page.html - 70 + apps/client/src/app/components/header/header.component.html + 105 - libs/ui/src/lib/assistant/assistant.html - 46 + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 - - - Pricing - Prix apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 - - - Hello, has shared a Portfolio with you! - Bonjour, a partagé un Portefeuille avec vous ! - apps/client/src/app/pages/public/public-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 - - Currencies - Devises + + Hello, has shared a Portfolio with you! + Bonjour, a partagé un Portefeuille avec vous ! apps/client/src/app/pages/public/public-page.html - 88 + 5 - + Continents Continents @@ -2893,20 +2365,20 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. Ghostfolio vous aide à garder un aperçu de votre patrimoine. apps/client/src/app/pages/public/public-page.html - 215 + 216 - + Get Started Démarrer apps/client/src/app/pages/features/features-page.html - 303 + 320 apps/client/src/app/pages/public/public-page.html @@ -2917,11 +2389,15 @@ Registration Enregistrement - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Create Account Creér Compte @@ -2936,8 +2412,12 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + Continue with Internet Identity Continue avec Internet Identity @@ -2945,7 +2425,7 @@ 42 - + Continue with Google Continuer avec Google @@ -2953,39 +2433,39 @@ 53 - + Copy to clipboard Copier vers le presse-papier apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Je certifie avoir sauvé mon Jeton de Sécurité ci-dessus dans un endroit sûr. Si je le perds, je ne pourrai pas récupérer mon compte. + + Resources + Ressources - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Accepter et continuer - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Ressources - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Oups, l’identification a échoué. @@ -2993,7 +2473,7 @@ 19 - + Try again Essayer à nouveau @@ -3001,39 +2481,47 @@ 27 - + Go back to Home Page Retour à la Page d’Accueil apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 Overview Aperçu - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 - + Draft Brouillon @@ -3046,10 +2534,18 @@ Importer Activités apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Exporter Activités @@ -3061,7 +2557,7 @@ 396 - + Export Drafts as ICS Exporter Brouillons sous ICS @@ -3073,7 +2569,7 @@ 409 - + Clone Dupliquer @@ -3081,7 +2577,7 @@ 436 - + Export Draft as ICS Exporter Brouillon sous ICS @@ -3094,34 +2590,26 @@ Voulez-vous vraiment supprimer cette activité ? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Indice - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High Différence avec le Record Historique libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH par rapport au record historique libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Taux d’Intérêt Annuel @@ -3129,20 +2617,24 @@ 21 - + Projected Total Amount Montant Total Prévu libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 Interest Intérêt + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + 370 libs/ui/src/lib/i18n.ts @@ -3154,12 +2646,16 @@ Épargne libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 - + Allocation Part + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -3173,7 +2669,7 @@ 116 - + Show all Montrer tout @@ -3184,6 +2680,18 @@ Account Compte + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3192,6 +2700,30 @@ Asset Class Classe d’Actifs + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3200,6 +2732,26 @@ Asset Sub Class Sous-classe d’Actifs + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + libs/ui/src/lib/i18n.ts 7 @@ -3208,6 +2760,18 @@ Emergency Fund Fonds d’Urgence + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3222,12 +2786,32 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 Symbol Symbole + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3236,6 +2820,10 @@ Tag Étiquette + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3244,9 +2832,13 @@ Cash Cash + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3260,6 +2852,10 @@ Equity Capital + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + libs/ui/src/lib/i18n.ts 46 @@ -3294,7 +2890,7 @@ Cryptomonnaie libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3302,7 +2898,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3310,7 +2906,7 @@ SICAV libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3318,7 +2914,7 @@ Métal Précieux libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3326,7 +2922,7 @@ Capital Propre libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3334,7 +2930,7 @@ Action libs/ui/src/lib/i18n.ts - 58 + 60 @@ -3342,7 +2938,7 @@ Afrique libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3350,7 +2946,7 @@ Asie libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3358,7 +2954,7 @@ Europe libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3366,7 +2962,7 @@ Amérique du Nord libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3374,7 +2970,7 @@ Océanie libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3382,10 +2978,10 @@ Amérique du Sud libs/ui/src/lib/i18n.ts - 70 + 72 - + Time to add your first activity. Il est temps d’ajouter votre première activité. @@ -3396,16 +2992,32 @@ No data available Pas de données disponibles + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - + Holding Position @@ -3414,10 +3026,10 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Charger Dividendes @@ -3430,7 +3042,7 @@ Annuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3438,15 +3050,23 @@ Importer Dividendes apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Valide jusqu’au apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3501,39 +3121,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values Protection pour les informations sensibles telles que la performance absolue et les montants apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times Expérience sans distraction pour les périodes tumultueuses apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality Avant-première de fonctionnalités futures apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? Êtes-vous un investisseur ambitieux qui a besoin d’une vue complète ? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Résumé du Portefeuille @@ -3542,14 +3162,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Référence de Performance @@ -3558,14 +3178,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator Calculateur FIRE @@ -3574,14 +3194,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... et d’autres fonctionnalités... @@ -3590,175 +3210,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Passer apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Mettre à niveau l’Abonnement apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Pour les investisseurs à l’aise avec la technologie qui préfèrent héberger Ghostfolio sur leur propre infrastructure. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Transactions Illimitées apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Comptes illimités apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Performance du Portefeuille apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Hébergé localement, mises à jour manuelles. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Gratuit apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Pour les nouveaux investisseurs qui débutent en Bourse. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Offre Ghostfolio cloud complètement administrée. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Pour les investisseurs ambitieux qui ont besoin d’une vue complète de leurs actifs financiers. apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Paiement unique, sans auto-renouvellement. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Démarrer apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 - - - It’s free. - C’est gratuit. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 + + + + It’s free. + C’est gratuit. + + apps/client/src/app/pages/pricing/pricing-page.html + 353 - + Fees Frais apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3766,10 +3402,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Allocations du Portefeuille @@ -3782,14 +3418,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Taux d’Épargne mensuel @@ -3797,20 +3433,20 @@ 10 - + Data Import and Export Import et Export de Données apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3821,20 +3457,20 @@ 13 - + Community Support Support de la Communauté apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support Support par E-mail et Tchat apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3853,7 +3489,7 @@ 14 - + Market data provided by Données de marché fournies par @@ -3861,23 +3497,7 @@ 2 - - Oops! Could not get the historical exchange rate from - Oups ! Nous n’avons pas pu obtenir le taux de change historique à partir de - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - - Gather Historical Data - Obtenir les Données Historiques - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 - - - + Retirement Date Date de Retraite @@ -3885,7 +3505,7 @@ 32 - + Professional Data Provider Fournisseur de Données Professionnel @@ -3894,10 +3514,10 @@ apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans Abonnements @@ -3905,7 +3525,7 @@ 4 - + Renew Plan Renouveler l’Abonnement @@ -3914,35 +3534,35 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Notre offre Ghostfolio Premium cloud est la manière la plus simple de débuter. Grâce au temps qu’elle économise, ce sera la meilleure option pour la plupart des gens. Les revenus sont utilisés pour couvrir les frais d’infrastructures et financer le développement continu de Ghostfolio. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Notre offre Ghostfolio Premium cloud est la manière la plus simple de débuter. Grâce au temps qu’elle économise, ce sera la meilleure option pour la plupart des gens. Les revenus sont utilisés pour couvrir les frais d’infrastructures et financer le développement continu de Ghostfolio. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User Voir en tant que ... apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User Supprimer l’Utilisateur apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 @@ -3950,10 +3570,10 @@ Voulez-vous vraiment supprimer toutes vos activités ? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider Par Émetteur d’ETF @@ -3961,7 +3581,7 @@ 306 - + Update platform Mettre à jour la Plateforme @@ -3969,7 +3589,7 @@ 8 - + Add platform Ajouter une Plateforme @@ -3977,16 +3597,20 @@ 10 - + Url Lien apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3998,18 +3622,18 @@ Voulez-vous vraiment supprimer cette plateforme ? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms Platformes apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance Mettre à jour le Solde @@ -4017,7 +3641,7 @@ 112 - + By Platform Par Plateforme @@ -4025,56 +3649,44 @@ 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: Mettez à niveau vers Ghostfolio Premium aujourd’hui et gagnez accès à des fonctionnalités exclusives pour améliorer votre expérience d’investissement: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. Obtenez les outils pour gérer efficacement vos finances et affinez votre stratégie d’investissement personnelle. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform Ajoutez une Plateforme apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings Paramètres - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Capital - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 @@ -4085,7 +3697,7 @@ 19 - + Manage Benchmarks Gérer les Références @@ -4093,7 +3705,7 @@ 35 - + Select Holding Selectionner une Position @@ -4101,7 +3713,7 @@ 20 - + Select File Selectionner un Fichier @@ -4109,7 +3721,7 @@ 22 - + Select Dividends Selectionner les Dividendes @@ -4117,7 +3729,7 @@ 113 - + Select Activities Selectionner les Activités @@ -4125,64 +3737,36 @@ 115 - - Import Activities - Importer les Activités - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Importer les Dividendes - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Finance Personnelle + + Frequently Asked Questions (FAQ) + Questions Fréquentes (FAQ) - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Questions Fréquentes (FAQ) - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak Série en cours apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak Série la plus longue apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 @@ -4217,12 +3801,12 @@ 30 - + Liabilities Dettes apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4231,37 +3815,37 @@ Changelog - Historique des Modifications + Historique des modifications - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License Licence - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Actions - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs ETFs @@ -4269,7 +3853,7 @@ 25 - + Bonds Obligations @@ -4277,15 +3861,7 @@ 38 - - Cryptocurrencies - Cryptomonnaies - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items Biens de luxe @@ -4293,15 +3869,15 @@ 76 - + Import and Export Importer et Exporter apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts Multi-Comptes @@ -4309,7 +3885,7 @@ 127 - + Portfolio Calculations Calculs de portefeuille @@ -4317,44 +3893,44 @@ 141 - + Dark Mode Mode Sombre apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood - Sentiment du Marché + Sentiment du marché apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis Analyse statique apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language Multi-Langue apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software Logiciel Open Source apps/client/src/app/pages/features/features-page.html - 278 + 295 @@ -4365,17 +3941,17 @@ 40 - + Scraper Configuration Configuration du Scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile - Ajouter un Profil d'Actif + Ajouter un Profil d’Actif apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 7 @@ -4385,19 +3961,23 @@ Personal Finance Tools Outils de Gestion de Patrimoine - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Découvrez les alternatives Open Source pour les outils de Gestion de Patrimoine apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Fondée @@ -4405,7 +3985,7 @@ 77 - + Origin L’origine @@ -4413,7 +3993,7 @@ 82 - + Region La région @@ -4421,15 +4001,15 @@ 87 - + Available in Disponible en apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Oui @@ -4465,7 +4045,7 @@ 274 - + ❌ No ❌ Non @@ -4501,31 +4081,31 @@ 281 - + Self-Hosting Self-Hosting apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Utilisation anonyme apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Plan gratuit apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Notes @@ -4533,39 +4113,15 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Suivez, analysez et visualisez sans effort votre patrimoine avec Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Outils de Gestion de Patrimoine - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Guides - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 - - - - Glossary - Glossaire - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + 329 - + Stocks, ETFs, bonds, cryptocurrencies, commodities Actions, ETFs, Obligations, Cryptomonnaies, Matières Premières @@ -4577,7 +4133,7 @@ 65 - + Mortgages, personal loans, credit cards Hypothèques, Prêts personnels, Cartes de crédit @@ -4585,7 +4141,7 @@ 57 - + Luxury items, real estate, private companies Bien de luxes, Immobilier, sociétées privées @@ -4596,6 +4152,10 @@ Buy Achat + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4614,7 +4174,7 @@ ETF sans Pays apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 @@ -4622,15 +4182,15 @@ ETF sans Secteurs apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets Actifs apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 @@ -4641,9 +4201,9 @@ 25 - + By Market - par Marchés + par marché apps/client/src/app/pages/portfolio/allocations/allocations-page.html 175 @@ -4662,118 +4222,98 @@ Japon libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio Bienvenue sur Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts Configurer votre compte apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. Obtenir un aperçu de vos comptes financiers en ajoutant vos comptes bancaires et de courtages. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities Capture vos activitées apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. Enregistrez vos activités immobilières pour maintenir votre portfolio à jour. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio Monitorer et analyser votre portfolio apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. Suivez votre évolution en temps réel grâce à une analyse approfondie et complète. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - Pas de données disponible - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? Prêt à reprendre le contrôle de votre patrimoine ? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts Configurer le compte apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication Authentication biométrique apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - Chez Ghostfolio, la transparence est le centre de notre attention. Nous publions le code source sous open source software (OSS) sous la licence AGPL-3.0 et nous partageons ouvertement les indicateurs clés agrégés sur l'état opérationnel de la plateforme. + Chez Ghostfolio, la transparence est le centre de notre attention. Nous publions le code source sous open source software (OSS) sous la licence AGPL-3.0 et nous partageons ouvertement les indicateurs clés agrégés sur l’état opérationnel de la plateforme. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users Utilisateurs actifs @@ -4785,7 +4325,7 @@ 62 - + New Users Nouvel Utilisateur @@ -4793,7 +4333,7 @@ 51 - + Users in Slack community Membres de la communauté Slack @@ -4801,7 +4341,7 @@ 75 - + Contributors on GitHub Contributeurs GitHub @@ -4809,7 +4349,7 @@ 89 - + Stars on GitHub Etoiles sur GitHub @@ -4821,7 +4361,7 @@ 103 - + Pulls on Docker Hub Téléchargement depuis Docker Hub @@ -4833,20 +4373,20 @@ 117 - + Uptime - Temps d'activité des serveurs + Temps d’activité des serveurs apps/client/src/app/pages/open/open-page.html 132 - + Export Data Exporter les Data apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 @@ -4854,10 +4394,14 @@ Devises apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 - + Our Notre @@ -4865,7 +4409,7 @@ 6 - + Visit Voir @@ -4873,39 +4417,23 @@ 28 - + Discover other exciting Open Source Software projects - Découvrez d'autres projets passionnants de logiciels Open Source + Découvrez d’autres projets passionnants de logiciels Open Source apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 9 - - Frequently Asked Questions (FAQ) - Frequently Asked Questions (FAQ) - - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 - - - apps/client/src/app/pages/faq/saas/saas-page.html - 4 - - - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 - - - + Check out the numerous features of Ghostfolio to manage your wealth Découvrez les nombreuses fonctionnalités de Ghostfolio pour gérer votre patrimoine apps/client/src/app/pages/features/features-page.html - 6 + 7 - + Discover the latest Ghostfolio updates and insights on personal finance Découvrez les dernières mises à jour et informations de Ghostfolio sur la gestion de patrimoine @@ -4913,43 +4441,31 @@ 7 - + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. Si vous préférez exécuter Ghostfolio sur votre propre infrastructure, veuilez trouver le code source ainsi que des instructions supplémentaires sur GitHub. apps/client/src/app/pages/pricing/pricing-page.html - 26 + 14 - + Manage your wealth like a boss Gérez votre patrimoine comme un chef apps/client/src/app/pages/landing/landing-page.html - 5 + 6 - + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio est un tableau de bord open-source axé sur la confidentialité pour votre Gestion de Patrimoine. Décomposez votre répartition d'actifs, connaissez votre valeur nette et prenez des décisions d'investissement solides et basées sur des données. - - apps/client/src/app/pages/landing/landing-page.html - 9 - - - - Get Started - Démarrer + Ghostfolio est un tableau de bord open-source axé sur la confidentialité pour votre Gestion de Patrimoine. Décomposez votre répartition d’actifs, connaissez votre valeur nette et prenez des décisions d’investissement solides et basées sur des données. apps/client/src/app/pages/landing/landing-page.html - 41 - - - apps/client/src/app/pages/pricing/pricing-page.html - 324 + 10 - + Monthly Active Users Utilisateurs actifs mensuels @@ -4957,7 +4473,7 @@ 70 - + As seen in Médias @@ -4965,23 +4481,23 @@ 115 - + Protect your assets. Refine your personal investment strategy. - Protégez vos actifs. Affinez votre stratégie d'investissement personnelle.. + Protégez vos actifs. Affinez votre stratégie d’investissement personnelle.. apps/client/src/app/pages/landing/landing-page.html - 225 + 226 - + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. Ghostfolio permet aux personnes occupées de suivre ses actions, ETF ou cryptomonnaies sans être pistées. apps/client/src/app/pages/landing/landing-page.html - 229 + 230 - + 360° View Vision 360° @@ -4989,7 +4505,7 @@ 240 - + Web3 Ready Compatible Web3 @@ -4997,31 +4513,23 @@ 251 - + Use Ghostfolio anonymously and own your financial data. Utilisez Ghostfolio de manière anonyme et soyez propriétaire de vos données financières. apps/client/src/app/pages/landing/landing-page.html - 253 - - - - Open Source - Open Source - - apps/client/src/app/pages/landing/landing-page.html - 261 + 254 - + Benefit from continuous improvements through a strong community. - Bénéficiez d'améliorations continues grâce à une communauté impliquée. + Bénéficiez d’améliorations continues grâce à une communauté impliquée. apps/client/src/app/pages/landing/landing-page.html - 263 + 264 - + Why Ghostfolio? Pourquoi Ghostfolio? @@ -5029,15 +4537,15 @@ 272 - + Ghostfolio is for you if you are... Ghostfolio est pour vous si vous ... apps/client/src/app/pages/landing/landing-page.html - 273 + 274 - + trading stocks, ETFs or cryptocurrencies on multiple platforms tradez des actions, ETFs or crypto-monnaies sur plusieurs plateforme. @@ -5045,7 +4553,7 @@ 280 - + pursuing a buy & hold strategy adoptez une stratégie Buy & and Hold @@ -5053,15 +4561,15 @@ 286 - + interested in getting insights of your portfolio composition - êtes intéressés d'avoir un aperçu de la composition de votre portefeuille + êtes intéressés d’avoir un aperçu de la composition de votre portefeuille apps/client/src/app/pages/landing/landing-page.html 291 - + valuing privacy and data ownership valorisez la confidentialité et la propriété de vos données @@ -5069,7 +4577,7 @@ 296 - + into minimalism êtes minimaliste @@ -5077,7 +4585,7 @@ 299 - + caring about diversifying your financial resources vous souciez de diversifier vos ressources financières @@ -5085,15 +4593,15 @@ 303 - + interested in financial independence - êtes intéressés d'atteindre l'indépendance financière + êtes intéressés d’atteindre l’indépendance financière apps/client/src/app/pages/landing/landing-page.html 307 - + saying no to spreadsheets in dites non aux feuilles de calcul en @@ -5101,7 +4609,7 @@ 311 - + still reading this list continuez à lire cette liste @@ -5109,7 +4617,7 @@ 314 - + Learn more about Ghostfolio En appendre plus sur Ghostfolio @@ -5117,31 +4625,31 @@ 319 - + What our users are saying - Qu'en pensent nos utilisateurs + Qu’en pensent nos utilisateurs apps/client/src/app/pages/landing/landing-page.html - 327 + 328 - + Members from around the globe are using Ghostfolio Premium Les utilisateurs du monde entier utilisent Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 366 + 367 - + How does Ghostfolio work? Comment fonctionne Ghostfolio ? apps/client/src/app/pages/landing/landing-page.html - 383 + 384 - + Sign up anonymously* Inscrivez-vous de manière anonyme* @@ -5149,7 +4657,7 @@ 392 - + * no e-mail address nor credit card required * aucune adresse mail ni carte de crédit requise @@ -5157,51 +4665,39 @@ 394 - + Add any of your historical transactions - Ajoutez l'une de vos transactions historiques + Ajoutez l’une de vos transactions historiques apps/client/src/app/pages/landing/landing-page.html - 405 + 406 - + Get valuable insights of your portfolio composition Obtenez de précieuses informations sur la composition de votre portefeuille apps/client/src/app/pages/landing/landing-page.html - 417 + 418 - + Are you ready? Êtes- vous prêts ? apps/client/src/app/pages/landing/landing-page.html - 431 - - - - Live Demo - Démo en Live - - apps/client/src/app/pages/landing/landing-page.html - 49 - - - apps/client/src/app/pages/landing/landing-page.html - 451 + 432 - + Get the full picture of your personal finances across multiple platforms. - Obtenez une vue d'ensemble de vos finances personnelles sur plusieurs plateformes. + Obtenez une vue d’ensemble de vos finances personnelles sur plusieurs plateformes. apps/client/src/app/pages/landing/landing-page.html - 242 + 243 - + Get started in only 3 steps Démarrer en seulement 3 étapes @@ -5209,2427 +4705,3430 @@ 386 - + faq foire-aux-questions - snake-case - - apps/client/src/app/app.component.ts - 77 - - - apps/client/src/app/core/paths.ts - 3 - - - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 - + kebab-case - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 245 - + features fonctionnalites - snake-case - - apps/client/src/app/app.component.ts - 78 - + kebab-case - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 255 + + + about + a-propos + kebab-case - apps/client/src/app/core/paths.ts - 4 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 214 + + + privacy-policy + politique-de-confidentialite + kebab-case - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 207 + + + license + licence + kebab-case - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + marches + kebab-case - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 260 - - about - a-propos - snake-case + + pricing + prix + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 270 + + + register + enregistrement + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + ressources + kebab-case - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 322 + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Cette page d’aperçu présente une collection d’outils de finances personnelles comparés à la solution open source alternative Ghostfolio. Si vous accordez de l’importance à la transparence, à la confidentialité des données et à la collaboration communautaire, Ghostfolio vous offre une excellente occasion de prendre le contrôle de votre gestion financière. - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Explorez les liens ci-dessous pour comparer une variété d’outils de finances personnelles avec Ghostfolio. - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + Open Source Alternative to + Solutions open source alternatives à - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + The Open Source Alternative to + L’alternative open source à - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Cherchez-vous des alternatives open source à ? Ghostfolio est un outil de gestion de portefeuille puissant offrant aux particuliers une plateforme complète pour suivre, analyser et optimiser ses investissements. Que vous soyez un investisseur expérimenté ou que vous débutiez, Ghostfolio offre une interface utilisateur intuitive et une large gamme de fonctionnalités pour vous aider à prendre des décisions éclairées et à prendre le contrôle de votre avenir financier. - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio est un logiciel open source (OSS), offrant une alternative économique, le rendant particulièrement adaptée aux personnes disposant d’un budget serré, telles que celles qui cherchent à atteindre le mouvement Financial Independence, Retire Early (FIRE). En s’appuyant sur les efforts collectifs d’une communauté de développeurs et de passionnés de finances personnelles, Ghostfolio améliore continuellement ses fonctionnalités, sa sécurité et son expérience utilisateur. - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Regardons plus en détails ce que proposent Ghostfolio vs via la table de comparaison ci-dessous pour comprendre comment Ghostfolio se positionne par rapport à . Nous examinerons divers aspects tels que les fonctionnalités, la confidentialité des données, le prix, etc., afin de vous permettre de faire un choix éclairé en fonction de vos besoins personnels. - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + open-source-alternative-to + alternative-open-source-a + kebab-case - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 324 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Veuillez noter que les informations fournies dans le Ghostfolio vs via la table de comparaison se basent de nos recherches et analyses indépendantes. Ce site n’est pas affilié à ou tout autre produit mentionné dans la comparaison. Le paysage des outils de finances personnelles évoluant, il est essentiel de vérifier tout détail ou changement spécifique directement sur la page du produit concerné. Certaines données doivent être mises à jour ? Aidez-nous à maintenir les données exactes sur GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - privacy-policy - politique-de-confidentialite - snake-case + + Ready to take your investments to the next level? + Prêt à prendre vos investissements au niveau supérieur? - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Switzerland + Suisse - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/ui/src/lib/i18n.ts + 96 - - license - licence - snake-case + + Global + Mondial - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/core/paths.ts - 5 + libs/ui/src/lib/i18n.ts + 16 + + + (Last 24 hours) + (Derniers 24 heures) - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/open/open-page.html + 37 - - markets - marches - snake-case + + (Last 30 days) + (Derniers 30 jours) - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/components/header/header.component.ts - 83 - - - apps/client/src/app/components/header/header.component.ts - 88 - - - apps/client/src/app/core/paths.ts - 6 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/open/open-page.html + 59 + + + (Last 90 days) + (Derniers 90 jours) - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/open/open-page.html + 127 + + + Choose or drop a file here + Choisissez ou déposez un fichier ici - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + You are using the Live Demo. + Vous utilisez la Démo en Live. - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/app.component.html + 12 + + + One-time fee, annual account fees + Paiement unique, Paiement annuel - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - pricing - prix - snake-case + + Distribution of corporate earnings + Distribution des bénéfices de la société - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Fee + Frais - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/components/header/header.component.ts - 84 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - apps/client/src/app/components/header/header.component.ts - 89 + libs/ui/src/lib/i18n.ts + 37 + + + Revenue for lending out money + Revenue lié au prêt d’argent - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + Add Tag + Ajouter un Tag - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + Do you really want to delete this tag? + Confirmez la suppression de ce tag ? - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Mettre à jour le tag - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Ajouter un tag - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Currency Cluster Risks + Risques de change - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + Account Cluster Risks + Risques liés aux regroupements de comptes - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Transfer Cash Balance + Transfert de Cash Balance - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Version + Version - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + From + De - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + To + A - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + Transfer + Transférer - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + Membership + Statut - libs/ui/src/lib/membership-card/membership-card.component.ts + libs/common/src/lib/routes/routes.ts 31 - - - register - enregistrement - snake-case - apps/client/src/app/app.component.ts - 81 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Accès - apps/client/src/app/components/header/header.component.ts - 90 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Profil d’Actif - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Do you really want to delete this asset profile? + Confirmez la suppressoion de ce profil d’actif? - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Chercher - apps/client/src/app/pages/faq/saas/saas-page.component.ts + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 16 + + + Add Manually + Ajouter manuellement - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio est un dashboard de finances personnelles qui permet de suivre vos actifs comme les actions, les ETF ou les crypto-monnaies sur plusieurs plateformes. - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Dernier All Time High - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - resources - ressources - snake-case + + User + Utilisateurs - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs tableau comparatif - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + Open Source Wealth Management Software + Logiciel libre de Gestion de Patrimoine - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + application, actif, cryptomonnaies, dashboard, etf, finance, gestion, performance, portefeuille, logiciel, action, trading, patrimoine, web3 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/i18n/i18n-page.html 10 + + + Oops, cash balance transfer has failed. + Oops, échec du transfert de la cash balance. - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Extreme Peur - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Extreme Cupidité - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Neutre - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + Oops! Echec du parsing des données historiques. - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + Confirmer la suppresion de ce message système? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + Tendance 50 jours - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 - + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + + 200-Day Trend + Tendance 200 jours - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + Cash Balances + Cash Balances - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + + Starting from + A partir de + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 + + + + Do you really want to delete this account balance? + Voulez-vous vraiment supprimer ce solde de compte ? + + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 + + + + If a translation is missing, kindly support us in extending it here. + Si une traduction est manquante, veuillez nous aider à compléter la traduction here. + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 + + + + The current market price is + Le prix actuel du marché est + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 + + + + Test + Test + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 + + + + Date Range + Intervalle de Date + + libs/ui/src/lib/assistant/assistant.html + 143 + + + + Permission + Autorisation + + apps/client/src/app/components/access-table/access-table.component.html + 18 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 + + + + Restricted view + Vue restreinte + + apps/client/src/app/components/access-table/access-table.component.html + 26 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 + + + + Oops! Could not grant access. + Oops! Impossible d’accorder l’accès. + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + + Private + Privée + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 + + + + Job Queue + File d’attente + + libs/common/src/lib/routes/routes.ts + 46 + + + + Market data is delayed for + Les données du marché sont retardées de + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Investment + Investissement + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + 86 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Cette page d'aperçu présente une collection d'outils de finances personnelles comparés à la solution open source alternative Ghostfolio. Si vous accordez de l'importance à la transparence, à la confidentialité des données et à la collaboration communautaire, Ghostfolio vous offre une excellente occasion de prendre le contrôle de votre gestion financière. + + Absolute Asset Performance + Performance des Actifs en valeur absolue - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + + Asset Performance + Performance des Actifs + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + + Absolute Currency Performance + Performance des devises en valeur absolue + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + + Currency Performance + Performance des devises + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + + Absolute Net Performance + Performance nette absolue + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + + Net Performance + Performance nette + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + + Week to date + Week to date + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + WTD + WTD + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + Month to date + Month to date + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + MTD + MTD + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + Year to date + Year to date + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + View + Vue + + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + + Oops! A data provider is experiencing the hiccups. + Oops! Un fournisseur de données rencontre des difficultés. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html 8 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Explorez les liens ci-dessous pour comparer une variété d'outils de finances personnelles avec Ghostfolio. + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Si vous prenez votre retraite aujourd’hui, vous pourrez retirer par an ou par mois, sur la base de vos actifs totaux de et un taux de retrait de 4 %. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 - - Open Source Alternative to - Solutions open source alternatives à + + Reset Filters + Réinitialiser les Filtres - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + libs/ui/src/lib/assistant/assistant.html + 238 + + + + year + année + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + années + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Apply Filters + Appliquer les Filtres + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + Data Gathering + Collecter les données + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + General + Général + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Cloud + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Self-Hosting + + apps/client/src/app/pages/faq/faq-page.component.ts + 60 + + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + self-hosting + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Oops! Il semble que vous fassiez trop de requêtes. Veuillez ralentir un peu. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + My Account + Mon Compte + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Active + Actif + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Clôturé + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Indonesia + Indonesia + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Activitées + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Dividend Yield + Rendement en Dividende + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Execute Job + Execute la tâche + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Priority + Priorité + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + This action is not allowed. + Cette action n’est pas autorisée. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Liquidity + Liquiditées + + libs/ui/src/lib/i18n.ts + 48 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} autres {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Achat et Vente + + libs/ui/src/lib/i18n.ts + 8 + + + + Delete Activities + Supprimer les Activitées + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internationalisation + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + Confirmer la suppresion de votre compte Ghostfolio ? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Zone de danger + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Supprimer le compte + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Par détention ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Approximation basée sur les principaux titres de chaque ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Rejoindre ou voir un compte démo + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + Oops! Une erreur s’est produite lors de la configuration de l’authentification biométrique. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Voir plus + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Benchmarks + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Supprimer des Profils + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Confirmer la suppression de ces Profils? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + Oops! Echec de la suppression de Profils. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + Table + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Tableau + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + Souhaitez-vous affiner votre stratégie d’investissement personnelle? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternative + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + App + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Budget + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Communauté + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Family Office + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Investisseur + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Open Source + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Gestion de Patrimoine + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Confidentialité + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Logiciels + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Outils + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Expérience Utilisateur + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Patrimoine + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Gestion de Patrimoine + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Australie + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Autriche + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Belgique + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bulgarie + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Canada + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + République Tchèque + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finlande + + libs/ui/src/lib/i18n.ts + 83 + + + + France + France + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Allemagne + + libs/ui/src/lib/i18n.ts + 85 + + + + India + Inde + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Italie + + libs/ui/src/lib/i18n.ts + 88 + + + + Netherlands + Pays-Bas + + libs/ui/src/lib/i18n.ts + 90 + + + + New Zealand + Nouvelle-Zélande + + libs/ui/src/lib/i18n.ts + 91 + + + + Poland + Pologne + + libs/ui/src/lib/i18n.ts + 92 + + + + Romania + Roumanie + + libs/ui/src/lib/i18n.ts + 93 + + + + South Africa + Afrique du Sud + + libs/ui/src/lib/i18n.ts + 95 + + + + Thailand + Thaïlande + + libs/ui/src/lib/i18n.ts + 97 + + + + United States + Etats-Unis + + libs/ui/src/lib/i18n.ts + 100 + + + + Error + Erreur + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + + Deactivate + Désactiver + + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Activer + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Inactive + Inactif + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Cancel + Annuler + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - Open Source Alternative to - Solutions open source alternatives à - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - - - The Open Source Alternative to - L’alternative open source à - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Cherchez-vous des alternatives open source à ? Ghostfolio est un outil de gestion de portefeuille puissant offrant aux particuliers une plateforme complète pour suivre, analyser et optimiser ses investissements. Que vous soyez un investisseur expérimenté ou que vous débutiez, Ghostfolio offre une interface utilisateur intuitive et une large gamme de fonctionnalités pour vous aider à prendre des décisions éclairées et à prendre le contrôle de votre avenir financier. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 - - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio est un logiciel open source (OSS), offrant une alternative économique, le rendant particulièrement adaptée aux personnes disposant d'un budget serré, telles que celles qui cherchent à atteindre le mouvement Financial Independence, Retire Early (FIRE). En s'appuyant sur les efforts collectifs d'une communauté de développeurs et de passionnés de finances personnelles, Ghostfolio améliore continuellement ses fonctionnalités, sa sécurité et son expérience utilisateur. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 - - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Regardons plus en détails ce que proposent Ghostfolio vs via la table de comparaison ci-dessous pour comprendre comment Ghostfolio se positionne par rapport à . Nous examinerons divers aspects tels que les fonctionnalités, la confidentialité des données, le prix, etc., afin de vous permettre de faire un choix éclairé en fonction de vos besoins personnels. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 - - - open-source-alternative-to - alternative-open-source-a - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 - - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Veuillez noter que les informations fournies dans le Ghostfolio vs via la table de comparaison se basent de nos recherches et analyses indépendantes. Ce site n'est pas affilié à ou tout autre produit mentionné dans la comparaison. Le paysage des outils de finances personnelles évoluant, il est essentiel de vérifier tout détail ou changement spécifique directement sur la page du produit concerné. Certaines données doivent être mises à jour ? Aidez-nous à maintenir les données exactes sur GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 - - - Ready to take your investments to the next level? - Prêt à prendre vos investissements au niveau supérieur? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 - - - Get Started - Démarrer - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 - - - Switzerland - Suisse - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 libs/ui/src/lib/i18n.ts - 90 + 9 - - Global - Mondial + + Close + Fermer - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 libs/ui/src/lib/i18n.ts - 16 + 11 - - (Last 24 hours) - (Derniers 24 heures) + + Yes + Oui - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/i18n.ts + 32 - - (Last 30 days) - (Derniers 30 jours) + + Copy link to clipboard + Copier le lien dans le presse-papiers - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + Portfolio Snapshot + Résumé du portefeuille - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - (Last 90 days) - (Derniers 90 jours) + + Change with currency effect Change + Variation avec taux de change appliqué Variation - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Choose or drop a file here - Choisissez ou déposez un fichier ici + + Performance with currency effect Performance + Performance avec taux de change appliqué Performance - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - You are using the Live Demo. - Vous utilisez la Démo en Live. + + Threshold Min + Seuil Min - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - One-time fee, annual account fees - Paiement unique, Paiement annuel + + Threshold Max + Seuil Max - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Distribution of corporate earnings - Distribution des bénéfices de la société + + Customize + Personnaliser - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/rule/rule.component.html + 67 - - Oops! Could not get the historical exchange rate from - Oops! Echec de la récupération des données historiques depuis + + No auto-renewal. + Pas de renouvellement automatique. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Fee - Frais + + This year + Cette année - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/public/public-page.html + 42 - - Interest - Intérêts + + From the beginning + Depuis le début - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/public/public-page.html + 60 - - Revenue for lending out money - Revenue lié au prêt d'argent + + Oops! Invalid currency. + Oups! Devise non valide. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 49 - - Add Tag - Ajouter un Tag + + This page has been archived. + Cette page a été archivée. - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Do you really want to delete this tag? - Confirmez la suppression de ce tag ? + + is Open Source Software + est un logiciel open source - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - - - Update tag - Mettre à jour le tag - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Add tag - Ajouter un tag + + is not Open Source Software + n’est pas un logiciel open source - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Currency Cluster Risks - Risques de change - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Account Cluster Risks - Risques liés aux regroupements de comptes + + can be self-hosted + peut être auto-hébergé - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Transfer Cash Balance - Transfert de Cash Balance + + cannot be self-hosted + ne peut pas être auto-hébergé - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Benchmark - Benchmark + + can be used anonymously + peut être utilisé de manière anonyme - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Version - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Settings - Paramètres + + cannot be used anonymously + ne peut pas être utilisé de manière anonyme - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - From - De - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - To - A + + offers a free plan + propose un plan gratuit - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Transfer - Transférer - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Membership - Statut + + does not offer a free plan + ne propose pas de plan gratuit - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Access - Accès + + Oops! Could not find any assets. + Oups! Aucun actif n’a été trouvé. - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 + + + Data Providers + Fournisseurs de données - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Find holding... - Chercher un actif... + + Set API key + Définir clé API - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - No entries... - Pas d'entrées ... + + Get access to 80’000+ tickers from over 50 exchanges + Accédez à plus de 80 000 symboles financiers issus de plus de 50 marchés boursiers. - libs/ui/src/lib/assistant/assistant.html - 63 + libs/ui/src/lib/i18n.ts + 24 + + + Ukraine + Ukraine - libs/ui/src/lib/assistant/assistant.html - 84 + libs/ui/src/lib/i18n.ts + 98 - - Asset Profile - Profil d'Actif + + Join now + Rejoindre maintenant - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Do you really want to delete this asset profile? - Confirmez la suppressoion de ce profil d'actif? + + Glossary + Glossaire - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - Search - Chercher - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Add Manually - Ajouter manuellement - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + libs/common/src/lib/routes/routes.ts + 293 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio est un dashboard de finances personnelles qui permet de suivre vos actifs comme les actions, les ETF ou les crypto-monnaies sur plusieurs plateformes. + + Guides + Guides - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/resources/guides/resources-guides.component.html 4 - - - Last All Time High - Dernier All Time High - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - User - Utilisateurs - apps/client/src/app/components/admin-users/admin-users.html - 29 + libs/common/src/lib/routes/routes.ts + 301 - - Ghostfolio vs comparison table - Ghostfolio vs tableau comparatif + + guides + guides + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + libs/common/src/lib/routes/routes.ts + 296 - - - Open Source Wealth Management Software - Logiciel libre de Gestion de Patrimoine - apps/client/src/app/pages/i18n/i18n-page.html - 14 + libs/common/src/lib/routes/routes.ts + 299 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - application, actif, cryptomonnaies, dashboard, etf, finance, gestion, performance, portefeuille, logiciel, action, trading, patrimoine, web3 + + glossary + glossaire + kebab-case - apps/client/src/app/pages/i18n/i18n-page.html - 9 + libs/common/src/lib/routes/routes.ts + 288 - - - Oops, cash balance transfer has failed. - Oops, échec du transfert de la cash balance. - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + libs/common/src/lib/routes/routes.ts + 291 - - Extreme Fear - Extreme Peur + + Threshold range + Plage de seuil - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Extreme Greed - Extreme Cupidité + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray utilise l’analyse statique pour détecter d’éventuels problèmes et risques dans votre portefeuille. Ajustez les règles ci-dessous et définissez des seuils personnalisés afin de les adapter à votre stratégie d’investissement. - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Neutral - Neutre + + Economic Market Cluster Risks + Risques liés aux zones économiques du marché - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - Oops! Could not parse historical data. - Oops! Echec du parsing des données historiques. + + of + sur - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Do you really want to delete this system message? - Confirmer la suppresion de ce message système? + + daily requests + requêtes journalières - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - 50-Day Trend - Tendance 50 jours + + Remove API key + Retirer la clé API - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - 200-Day Trend - Tendance 200 jours + + Do you really want to delete the API key? + Voulez-vous vraiment supprimer la clé API? - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Cash Balances - Cash Balances + + Please enter your Ghostfolio API key: + Veuillez saisir votre clé API Ghostfolio : - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Starting from - A partir de + + API Requests Today + Requêtes API aujourd’hui - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/admin-users/admin-users.html + 179 + + + Could not generate an API key + Impossible de générer une clé API - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - year - années + + Set this API key in your self-hosted environment: + Définissez cette clé API dans votre environnement auto-hébergé : - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 + + + Ghostfolio Premium Data Provider API Key + Clé API du fournisseur de données Ghostfolio Premium - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - Do you really want to delete this account balance? - Voulez-vous vraiment supprimer ce solde de compte ? + + Do you really want to generate a new API key? + Voulez-vous vraiment générer une nouvelle clé API ? - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - is an invalid currency! - est une devise non valide ! + + API Key + Clé API - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - If a translation is missing, kindly support us in extending it here. - Si une traduction est manquante, veuillez nous aider à compléter la traduction here. + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Générer la clé API du fournisseur de données Ghostfolio Premium pour les environnements auto-hébergés... - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - The current market price is - Le prix actuel du marché est + + out of + sur - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - Test - Test + + rules align with your portfolio. + règles sont en accord avec votre portefeuille. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Date Range - Intervalle de Date + + Save + Sauvegarder - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - - - Permission - Autorisation - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Restricted view - Vue restreinte - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Oops! Could not grant access. - Oops! Impossible d'accorder l'accès. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Private - Privée apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + 65 - - - Job Queue - File d'attente - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Market data is delayed for - Les données du marché sont retardées de - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Investment - Investissement + + Asset Class Cluster Risks + Risques liés aux regroupements de classes d’actifs - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + Me + Moi - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Absolute Asset Performance - Performance des Actifs en valeur absolue + + Received Access + Accès reçu - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Asset Performance - Performance des Actifs + + Please enter your Ghostfolio API key. + Veuillez saisir votre clé API Ghostfolio. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Absolute Currency Performance - Performance des devises en valeur absolue + + AI prompt has been copied to the clipboard + Le prompt IA a été copié dans le presse-papiers - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Currency Performance - Performance des devises + + Link has been copied to the clipboard + Le lien a été copié dans le presse-papiers - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Absolute Net Performance - Performance nette absolue + + Regional Market Cluster Risks + Risques liés aux regroupements de marchés régionaux - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Net Performance - Performance nette + + Lazy + Paresseux - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Week to date - Week to date + + Instant + Instantané - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - WTD - WTD + + Default Market Price + Prix du marché par défaut - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Month to date - Month to date + + Mode + Mode - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - MTD - MTD + + Selector + Selecteur - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Year to date - Year to date + + HTTP Request Headers + En-têtes de requête HTTP - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - View - Vue - - apps/client/src/app/components/access-table/access-table.component.html - 23 - + + end of day + fin de journée - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Oops! A data provider is experiencing the hiccups. - Oops! Un fournisseur de données rencontre des difficultés. + + real-time + temps réel - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Si vous prenez votre retraite aujourd'hui, vous pourrez retirer par an ou par mois, sur la base de vos actifs totaux de et un taux de retrait de 4 %. + + Open Duck.ai + Ouvrir Duck.ai - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Reset Filters - Réinitialiser les Filtres + + Create + Créer - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - year - année + + Change + Variation - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - years - années - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Apply Filters - Appliquer les Filtres + + Performance + Performance - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - Data Gathering - Collecter les données - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - General - Général - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Cloud - Cloud - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Self-Hosting - Self-Hosting + + Copy portfolio data to clipboard for AI prompt + Copier les données du portefeuille dans le presse-papiers pour le prompt IA - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 + + + Copy AI prompt to clipboard for analysis + Copier le prompt IA dans le presse-papiers pour analyse - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - self-hosting - self-hosting + + Armenia + Arménie - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/ui/src/lib/i18n.ts + 75 - - FAQ - FAQ + + British Virgin Islands + Îles Vierges britanniques - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + Singapour - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! Il semble que vous fassiez trop de requêtes. Veuillez ralentir un peu. + + Terms and Conditions + Conditions générales - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - My Account - Mon Compte + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Veuillez garder votre jeton de sécurité en lieu sûr. Si vous le perdez, vous ne pourrez pas récupérer votre compte. - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Active - Actif + + I understand that if I lose my security token, I cannot recover my account + Je comprends que si je perds mon jeton de sécurité, je ne pourrai pas récupérer mon compte - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Closed - Clôturé + + Continue + Continuer - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Activity - Activitées + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Voici votre jeton de sécurité. Il n’est visible qu’une seule fois, veuillez le conserver en lieu sûr. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Dividend Yield - Rendement en Dividende + + Security token + Jeton de sécurité - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Execute Job - Execute la tâche - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Priority - Priorité + + Do you really want to generate a new security token for this user? + Voulez-vous vraiment générer un nouveau jeton de sécurité pour cet utilisateur ? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - This action is not allowed. - Cette action n'est pas autorisée. + + Generate Security Token + Générer un jeton de sécurité - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Liquidity - Liquiditées + + United Kingdom + Royaume-Uni libs/ui/src/lib/i18n.ts - 48 + 99 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} autres {activities}} + + Terms of Service + Conditions d’utilisation - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Buy and sell - Achat et Vente + + terms-of-service + conditions-d-utilisation + kebab-case - libs/ui/src/lib/i18n.ts - 8 + libs/common/src/lib/routes/routes.ts + 212 - - - Delete Activities - Supprimer les Activitées - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + libs/common/src/lib/routes/routes.ts + 215 - - Internationalization - Internationalisation + + Terms of Service + Conditions d’utilisation - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/app.component.html + 112 - - - Do you really want to close your Ghostfolio account? - Confirmer la suppresion de votre compte Ghostfolio ? - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + libs/common/src/lib/routes/routes.ts + 217 - - Danger Zone - Zone de danger + + and I agree to the Terms of Service. + et j’accepte les conditions d’utilisation. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Close Account - Supprimer le compte + + () is already in use. + () est déjà utilisé. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - By ETF Holding - Par détention ETF + + An error occurred while updating to (). + Une erreur s’est produite lors de la mise à jour vers (). - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Approximation based on the top holdings of each ETF - Approximation basée sur les principaux titres de chaque ETF + + Apply + Appliquer - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Join now or check out the example account - Rejoindre ou voir un compte démo + + with API access for + avec accès API pour - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Oops! There was an error setting up biometric authentication. - Oops! Une erreur s'est produite lors de la configuration de l'authentification biométrique. + + Gather Recent Historical Market Data + Collecter les données récentes du marché historique - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Show more - Voir plus + + Gather All Historical Market Data + Collecter toutes les données du marché historique - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Benchmarks - Benchmarks + + Gather Historical Market Data + Collecter les données du marché historique - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Delete Profiles - Supprimer des Profils + + Data Gathering is off + La collecte de données est désactivée apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + 38 - - Do you really want to delete these profiles? - Confirmer la suppression de ces Profils? + + Performance Calculation + Calcul de performance - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! Could not delete profiles. - Oops! Echec de la suppression de Profils. + + someone + quelqu’un - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Table - Table + + Add asset to watchlist + Ajouter un actif à la liste de suivi - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Chart - Tableau + + Watchlist + Liste de suivi - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 + + + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 - - Would you like to refine your personal investment strategy? - Souhaitez-vous affiner votre stratégie d'investissement personnelle? + + Do you really want to delete this item? + Voulez-vous vraiment supprimer cet élément? - apps/client/src/app/pages/public/public-page.html - 211 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Alternative - Alternative + + Log out + Se déconnecter - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/header/header.component.html + 329 - - App - App + + Calculations are based on delayed market data and may not be displayed in real-time. + Les calculs sont basés sur des données de marché retardées et peuvent ne pas être affichés en temps réel. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 - - Budgeting - Budget + + changelog + journal-des-modifications + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - Community - Communauté + + Demo user account has been synced. + Le compte utilisateur de démonstration a été synchronisé. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Family Office - Family Office + + Sync Demo User Account + Synchroniser le compte utilisateur de démonstration - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Investor - Investisseur + + Set up + Fonds d’urgence : Mise en place - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Open Source - Open Source + + No emergency fund has been set up + Aucun fonds d’urgence n’a été mis en place - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Personal Finance - Gestion de Patrimoine + + An emergency fund has been set up + Un fonds d’urgence a été mis en place - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Privacy - Confidentialité + + Fee Ratio + Ratio de frais - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Software - Logiciels + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Les frais dépassent ${thresholdMax}% de votre investissement initial (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Tool - Outils + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Les frais ne dépassent pas ${thresholdMax}% de votre investissement initial (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - User Experience - Expérience Utilisateur + + Name + Nom - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth - Patrimoine + + Find holding or page... + Rechercher une position ou une page... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Wealth Management - Gestion de Patrimoine + + Quick Links + Liens rapides - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 56 - - Australia - Australie + + Asset Profiles + Profils d’Actifs - libs/ui/src/lib/i18n.ts - 73 + libs/ui/src/lib/assistant/assistant.html + 112 - - Austria - Autriche + + Live Demo + Démo Live + + apps/client/src/app/pages/landing/landing-page.html + 49 + - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Belgium - Belgique - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bulgarie + + Open Source Alternative to + Solutions open source alternatives à - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Canada + + Single Account + Compte Unique - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - République Tchèque + + Your net worth is managed by a single account + Votre patrimoine est géré par un compte unique - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finlande + + Your net worth is managed by ${accountsLength} accounts + Votre patrimoine est géré par ${accountsLength} comptes - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - France + + personal-finance-tools + outils-finance-personnelle + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 - - - Germany - Allemagne - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 315 - - - India - Inde - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italie + + markets + marches + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 - - - Netherlands - Pays-Bas - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 307 - - New Zealand - Nouvelle-Zélande + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Alimentez votre Ghostfolio auto-hébergé avec un fournisseur de données puissant pour accéder à plus de 80 000 tickers issus de plus de 50 bourses dans le monde entier. - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Poland - Pologne + + Get Access + Obtenir l’accès - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Romania - Roumanie + + Learn more + En savoir plus - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - South Africa - Afrique du Sud + + Limited Offer! + Offre Limitée ! - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Thailand - Thaïlande + + Get extra + Obtenez supplémentaires - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - United States - Etats-Unis + + Available + Disponible - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Error - Erreur + + Unavailable + Indisponible - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Deactivate - Désactiver + + new + new - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Activate - Activer - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Inactive - Inactif + + Investment + Investment - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Cancel - Annuler + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Close - Fermer + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Yes - Oui + + Equity + Equity - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Change with currency effect Change - Change with currency effect Change + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Performance with currency effect Performance - Performance with currency effect Performance + + Fixed Income + Fixed Income - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Close - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Customize - Customize + + Investment: Base Currency + Investment: Base Currency - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today - Today + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - This year - This year + + Investment + Investissement - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - From the beginning - From the beginning + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Plus de ${thresholdMax}% de votre investissement actuel est en ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - Oops! Invalid currency. - Oops! Invalid currency. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + La majeure partie de votre investissement actuel est en ${currency} (${maxValueRatio}%) et n’excède pas ${thresholdMax}% - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - This page has been archived. - This page has been archived. + + start + commencer + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 336 - - - is Open Source Software - is Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 337 - - is not Open Source Software - is not Open Source Software + + Do you really want to generate a new security token? + Voulez-vous vraiment générer un nouveau jeton de sécurité? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is Open Source Software - is Open Source Software + + Generate + Générer - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is not Open Source Software - is not Open Source Software + + Stocks + Actions - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be self-hosted - cannot be self-hosted + + Cryptocurrencies + Crypto-monnaies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/markets/markets.component.ts + 53 + + + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - can be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - cannot be self-hosted + + Manage Asset Profile + Gérer le profil d’actif - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - can be used anonymously + + Alternative Investment + Investissement alternatif - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - cannot be used anonymously + + Collectible + Objet de collection - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - can be used anonymously + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - cannot be used anonymously - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + No results found... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Emerging Markets - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Your net worth is managed by 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europe - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + North America - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Find Ghostfolio on GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Join the Ghostfolio Slack community - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Follow Ghostfolio on X (formerly Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Send an e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Follow Ghostfolio on LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Support Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 172909d0d..97b9b2c23 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -2,7 +2,7 @@ - + Create Account Crea un account @@ -17,16 +17,20 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. Il rischio di perdita nel trading può essere notevole. Non è consigliabile investire denaro di cui potresti avere bisogno a breve termine. apps/client/src/app/app.component.html - 200 + 221 - + Grantee Beneficiario @@ -34,7 +38,7 @@ 11 - + Type Tipo @@ -54,7 +58,7 @@ 161 - + Details Dettagli @@ -62,7 +66,7 @@ 33 - + Revoke Revoca @@ -75,50 +79,10 @@ Vuoi davvero revocare l’accesso concesso? apps/client/src/app/components/access-table/access-table.component.ts - 67 - - - - Activities - Attività - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + 108 - + Name Nome @@ -127,23 +91,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -155,7 +123,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -174,7 +142,7 @@ 88 - + Total Totale @@ -182,7 +150,7 @@ 55 - + Value Valore @@ -199,31 +167,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -250,64 +202,56 @@ 102 - + Edit Modifica apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Elimina apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -317,16 +261,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? Vuoi davvero eliminare questo account? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + 148 - + Delete Jobs Elimina i lavori @@ -334,31 +282,7 @@ 151 - - Symbol - Simbolo - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 - - - + Data Source Sorgente dei dati @@ -367,18 +291,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Tentativi @@ -386,7 +310,7 @@ 83 - + Created Creato @@ -394,7 +318,7 @@ 92 - + Finished Finito @@ -402,31 +326,39 @@ 101 - + Status Stato apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Asset Profiles Profilo dell’asset - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data Dati storici del mercato apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Visualizza i dati @@ -434,7 +366,7 @@ 166 - + View Stacktrace Visualizza Stacktrace @@ -442,7 +374,7 @@ 173 - + Delete Job Elimina il lavoro @@ -450,7 +382,7 @@ 180 - + Details for Dettagli per @@ -458,12 +390,12 @@ 2 - + Date Data apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -478,127 +410,43 @@ 6 - + Market Price Prezzo di mercato apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Annulla - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 - - - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 - - - - Save - Salva - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 - - - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - + First Activity Prima attività apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + 148 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + 198 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + 214 libs/ui/src/lib/holdings-table/holdings-table.component.html 50 - + Activity Count Conteggio attività @@ -606,40 +454,24 @@ 19 - + Historical Data Dati storici apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + 166 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html 44 - - Please add a currency: - Aggiungi una valuta: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 - - Do you really want to delete this coupon? Vuoi davvero eliminare questo buono? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 - - - - Do you really want to delete this currency? - Vuoi davvero eliminare questa valuta? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + 194 @@ -647,7 +479,7 @@ Vuoi davvero svuotare la cache? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + 231 @@ -655,10 +487,10 @@ Imposta il messaggio di sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + 251 - + User Count Numero di utenti @@ -666,7 +498,7 @@ 13 - + per User per utente @@ -674,112 +506,84 @@ 28 - - Gather Recent Data - Raccogli dati recenti - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 - - - - Gather All Data - Raccogli tutti i dati - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 - - - + Gather Profile Data Raccogli i dati del profilo apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + 235 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Exchange Rates - Tassi di cambio - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + 44 - + Add Currency Aggiungi valuta apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + System Message Messaggio di sistema apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Imposta messaggio apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Read-only Mode Modalità di sola lettura apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + Coupons Buoni sconto apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Aggiungi apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Bilancio domestico apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Svuota la cache apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -787,46 +591,38 @@ Vuoi davvero eliminare questo utente? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Utente apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + 31 apps/client/src/app/components/header/header.component.html - 229 - - - - Registration - Iscrizione - - apps/client/src/app/components/admin-users/admin-users.html - 97 + 231 - + Engagement per Day Partecipazione giornaliera apps/client/src/app/components/admin-users/admin-users.html - 157 + 158 - + Last Request Ultima richiesta apps/client/src/app/components/admin-users/admin-users.html - 202 + 204 - + Current Market Mood Stato d’animo attuale del mercato @@ -834,391 +630,199 @@ 12 - - Overview - Panoramica + + About Ghostfolio + Informazioni su Ghostfolio apps/client/src/app/components/header/header.component.html - 28 + 326 - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Portfolio - Portafoglio + + Get Started + Inizia - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 320 - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/public/public-page.html + 220 - - Accounts - Account + + Sign in + Accedi - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/header/header.component.html - 263 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + libs/common/src/lib/routes/routes.ts + 157 + + + Oops! Incorrect Security Token. + Ops! Token di sicurezza errato. - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/components/header/header.component.ts + 274 - - - Admin Control - Controllo amministrativo - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 - - Resources - Risorse + + Manage Activities + Gestione delle attività - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Last Days + Ultimi giorni - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/markets/markets.html + 17 + + + Security Token + Token di sicurezza - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - - - Pricing - Prezzi - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - About - Informazioni su + + or + oppure - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/pages/landing/landing-page.html + 48 - - - Me - Io - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/landing/landing-page.html + 451 - - - My Ghostfolio - Il mio Ghostfolio - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - - - About Ghostfolio - Informazioni su Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Features - Funzionalità - - apps/client/src/app/app.component.html - 79 - + + Sign in with Internet Identity + Accedi con Internet Identity - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + Accedi con Google - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Markets - Mercati + + Stay signed in + Rimani connesso - apps/client/src/app/app.component.html + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html 61 + + + Time in Market + Tempo nel mercato - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + Prestazioni lorde assolute - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Absolute Net Performance + Prestazioni nette assolute - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 - - Get Started - Inizia - - apps/client/src/app/pages/features/features-page.html - 303 - - - apps/client/src/app/pages/public/public-page.html - 220 - - - - Sign in - Accedi - - apps/client/src/app/app-routing.module.ts - 150 - - - apps/client/src/app/components/header/header.component.ts - 230 - - - - Oops! Incorrect Security Token. - Ops! Token di sicurezza errato. - - apps/client/src/app/components/header/header.component.ts - 245 - - - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 - - - - Manage Activities - Gestione delle attività - - apps/client/src/app/components/home-holdings/home-holdings.html - 63 - - - - Last Days - Ultimi giorni - - apps/client/src/app/components/home-market/home-market.html - 7 - - - - Summary - Riepilogo - - apps/client/src/app/components/home-summary/home-summary.html - 2 - - - - Security Token - Token di sicurezza - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 - - - - or - oppure - - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 - - - apps/client/src/app/pages/landing/landing-page.html - 47 - - - apps/client/src/app/pages/landing/landing-page.html - 450 - - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 - - - apps/client/src/app/pages/register/register-page.html - 30 - - - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 - - - - Sign in with Internet Identity - Accedi con Internet Identity - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 - - - - Sign in with Google - Accedi con Google - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 - - - - Stay signed in - Rimani connesso - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 - - - - Sign in - Accedi - - apps/client/src/app/components/header/header.component.html - 412 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 - - - - Time in Market - Tempo nel mercato - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 - - - - Buy - Compra - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 - - - - Sell - Vendi - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 - - - - Investment - Investimento - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - - Absolute Gross Performance - Prestazioni lorde assolute - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 - - - - Absolute Net Performance - Prestazioni nette assolute - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 - - - + Net Performance Prestazioni nette @@ -1226,7 +830,7 @@ 117 - + Total Assets Asset totali @@ -1234,153 +838,105 @@ 143 - - Valuables - Oggetti di valore - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Fondo di emergenza - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Potere d’acquisto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Net Worth Patrimonio netto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Prestazioni annualizzate apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividendo - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 Please set the amount of your emergency fund. - Inserisci l’importo del tuo fondo di emergenza: + Inserisci l’importo del tuo fondo di emergenza: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + 71 - + Sectors Settori apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Paesi apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Tags Tag apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + Report Data Glitch Segnala un’anomalia dei dati apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 - + Allocation Allocazione + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -1394,21 +950,9 @@ 116 - - Performance - Prestazioni - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 - - - - Show all - Mostra tutti + + Show all + Mostra tutti libs/ui/src/lib/holdings-table/holdings-table.component.html 197 @@ -1418,60 +962,44 @@ Today Oggi - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/public/public-page.html + 24 libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD anno corrente - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1 anno - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5 anni - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Massimo - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1479,191 +1007,75 @@ Bene apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About Informazioni su - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Privacy Policy - Informativa sulla privacy - - apps/client/src/app/app.component.html - 103 - - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 - - - - Blog - Blog apps/client/src/app/app.component.html - 73 - - - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 - - - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 - - - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 - - - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 - - - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 - - - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 - - - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 - - - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 - - - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 - - - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 - - - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 - - - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 70 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/header/header.component.html + 375 - - - Changelog - Registro delle modifiche - apps/client/src/app/app.component.html - 77 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/common/src/lib/routes/routes.ts + 220 - - License - Licenza d’uso + + Privacy Policy + Informativa sulla privacy apps/client/src/app/app.component.html - 88 + 105 - apps/client/src/app/pages/about/license/license-page.html + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 - - - Privacy Policy - Informativa sulla privacy - - apps/client/src/app/pages/about/about-page.component.ts - 62 - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 209 My Ghostfolio Il mio Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 - - Please enter your coupon code: + + Please enter your coupon code. Inserisci il tuo codice del buono: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1671,7 +1083,7 @@ Impossibile riscattare il codice del buono apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1679,7 +1091,7 @@ Il codice del buono è stato riscattato apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1687,7 +1099,7 @@ Ricarica apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1695,114 +1107,94 @@ Vuoi davvero rimuovere questo metodo di accesso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Account - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Iscrizione - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year per anno apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Prova Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Riscatta il buono apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Vista presentatore apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Valuta base apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Locale Locale + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Formato data e numero apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Zen Mode Modalità Zen apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Sign in with fingerprint Accesso con impronta digitale apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + User ID ID utente @@ -1811,18 +1203,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Accesso concesso apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Concedi l’accesso @@ -1830,7 +1222,7 @@ 7 - + Public Pubblico @@ -1842,35 +1234,51 @@ Accounts Account - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - Update account - Aggiorna account - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/components/admin-users/admin-users.html + 115 - - - Add account - Aggiungi un account - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/components/header/header.component.html + 58 - - - Cash - Contanti - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 + + + + Update account + Aggiorna account + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 + + + + Add account + Aggiungi un account + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - + Currency Valuta @@ -1879,11 +1287,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1895,14 +1303,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Saldo di cassa @@ -1918,7 +1326,7 @@ 34 - + Platform Piattaforma @@ -1934,7 +1342,7 @@ 48 - + Account ID ID account @@ -1946,16 +1354,116 @@ Admin Control Controllo amministrativo - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 + + + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 Blog Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 + + + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 + + + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 + + + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 + + + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 + + + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 + + + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 + + + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 + + + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 + + + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 + + + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 + + + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 + + + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 + + + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 + + + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 + + + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 + + + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 + + + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 @@ -1970,91 +1478,135 @@ Frequently Asked Questions (FAQ) Domande più frequenti (FAQ) - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Funzionalità - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Overview Panoramica - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 Markets Mercati - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 - - - Allocations - Allocazioni - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 - + Allocations Allocazioni apps/client/src/app/pages/portfolio/allocations/allocations-page.html 4 + + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 133 + - + By Account Per account @@ -2062,7 +1614,7 @@ 286 - + By Currency Per valuta @@ -2070,7 +1622,7 @@ 63 - + By Asset Class Per classe asset @@ -2078,7 +1630,7 @@ 85 - + By Holding Per partecipazione @@ -2086,7 +1638,7 @@ 107 - + By Sector Per settore @@ -2094,7 +1646,7 @@ 130 - + By Continent Per continente @@ -2102,7 +1654,7 @@ 153 - + By Country Per paese @@ -2110,7 +1662,7 @@ 264 - + Regions Regioni @@ -2123,50 +1675,42 @@ - Analysis - Analisi - - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 - - - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 - - - Analysis Analisi apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 + + libs/common/src/lib/routes/routes.ts + 138 + - + Investment Timeline Cronologia degli investimenti apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + Top In alto apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom In basso apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + FIRE FIRE @@ -2174,7 +1718,7 @@ 4 - + Calculator Calcolatrice @@ -2182,7 +1726,7 @@ 7 - + 4% Rule Regola del 4% @@ -2191,26 +1735,6 @@ - Holdings - Partecipazioni - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - Holdings Partecipazioni @@ -2226,24 +1750,36 @@ 70 - libs/ui/src/lib/assistant/assistant.html - 46 + libs/common/src/lib/routes/routes.ts + 90 - - - Update activity - Aggiorna l’attività + + libs/common/src/lib/routes/routes.ts + 167 + + + + Holdings + Partecipazioni + + libs/ui/src/lib/assistant/assistant.html + 82 + + + + Update activity + Aggiorna l’attività apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 10 - + Add activity Aggiungi un’attività apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2253,77 +1789,69 @@ Sell Vendi + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Nome, simbolo o ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 124 - + Quantity Quantità apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Unit Price Prezzo unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 214 libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Fee - Commissione - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 234 - - - + Note Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2331,47 +1859,51 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 275 - - Asset Class - Classe asset + + Activities + Attività - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + 207 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/admin-users/admin-users.html + 136 - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Activities - Attività - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 @@ -2379,7 +1911,7 @@ Importazione dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2387,42 +1919,66 @@ L’importazione è stata completata apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 Pricing Prezzi + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 + Portfolio Portafoglio apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + 124 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + 92 - - - Currencies - Valute - apps/client/src/app/pages/public/public-page.html - 88 + libs/common/src/lib/routes/routes.ts + 151 - + Continents Continenti @@ -2430,23 +1986,27 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. Ghostfolio ti permette di tenere traccia della tua ricchezza. apps/client/src/app/pages/public/public-page.html - 215 + 216 Registration Iscrizione - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Continue with Internet Identity Continua con Internet Identity @@ -2454,7 +2014,7 @@ 42 - + Continue with Google Continua con Google @@ -2462,39 +2022,39 @@ 53 - + Copy to clipboard Copia negli appunti apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Accetto di aver memorizzato il mio Token di sicurezza sopra citato in un luogo sicuro. Se lo perdo, non posso recuperare il mio account. + + Resources + Risorse - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Accetta e continua - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Risorse - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Ops, l’autenticazione non è riuscita. @@ -2502,7 +2062,7 @@ 19 - + Try again Riprova @@ -2510,15 +2070,15 @@ 27 - + Go back to Home Page Torna alla pagina iniziale apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 - + Draft Bozza @@ -2531,10 +2091,18 @@ Importa le attività apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Esporta le attività @@ -2546,7 +2114,7 @@ 396 - + Export Drafts as ICS Esporta le bozze come ICS @@ -2558,7 +2126,7 @@ 409 - + Clone Clona @@ -2566,7 +2134,7 @@ 436 - + Export Draft as ICS Esporta la bozza come ICS @@ -2579,34 +2147,26 @@ Vuoi davvero eliminare questa attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Indice - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High Variazione rispetto al massimo storico (ATH) libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH dal massimo storico (ATH) libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Tasso di interesse annuo @@ -2614,7 +2174,7 @@ 21 - + Time to add your first activity. È il momento di aggiungere la tua prima attività. @@ -2622,20 +2182,20 @@ 12 - + Language Lingua apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + 56 - + Get started Inizia apps/client/src/app/components/header/header.component.html - 422 + 432 @@ -2643,7 +2203,7 @@ Questa funzionalità non è attualmente disponibile. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -2651,11 +2211,11 @@ Ops! Qualcosa è andato storto. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 184 @@ -2663,26 +2223,18 @@ Riprova più tardi. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 - - - - Change - Modifica - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 186 - + Developed Markets Mercati sviluppati @@ -2694,47 +2246,15 @@ 160 - - Asset Sub Class - Sottoclasse asset - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 - - - - Average Unit Price - Prezzo unitario medio - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 - - - + Maximum Price Prezzo massimo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 143 - + Other Markets Altri mercati @@ -2746,7 +2266,7 @@ 178 - + Emerging Markets Mercati emergenti @@ -2758,48 +2278,48 @@ 169 - + Sector Settore apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + 242 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + 263 - + Country Paese apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Minimum Price Prezzo minimo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Projected Total Amount Importo totale previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2807,15 +2327,19 @@ Risparmio libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 Interest Interesse + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + 370 libs/ui/src/lib/i18n.ts @@ -2827,7 +2351,7 @@ Deposito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 @@ -2835,23 +2359,23 @@ Mensile apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + 88 - + Sectors Count Numero di settori apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + 175 - + Countries Count Numero di paesi apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + 184 @@ -2859,11 +2383,15 @@ Paura apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -2871,11 +2399,15 @@ Avidità apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 @@ -2883,18 +2415,18 @@ Filtra per... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + 379 - - Hello, has shared a Portfolio with you! - Salve, ha condiviso un Portafoglio con te! + + Hello, has shared a Portfolio with you! + Salve, ha condiviso un Portafoglio con te! apps/client/src/app/pages/public/public-page.html - 4 + 5 - + Alias Alias @@ -2906,23 +2438,27 @@ 11 - + Experimental Features Funzionalità sperimentali apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 Benchmark Benchmark + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + 136 - + Compare with... Confronta con... @@ -2930,7 +2466,7 @@ 18 - + Proportion of Net Worth Percentuale del patrimonio netto @@ -2938,12 +2474,12 @@ 12 - + Excluded from Analysis Escluso dall’analisi apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 @@ -2951,39 +2487,35 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 - - - Appearance - Aspetto apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + 172 - - Auto - Auto + + Appearance + Aspetto apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Chiaro apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Scuro apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 @@ -2991,15 +2523,15 @@ Importo totale apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 - + Portfolio Evolution Evoluzione del portafoglio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 @@ -3007,12 +2539,24 @@ Tasso di risparmio apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 Account Account + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3021,6 +2565,30 @@ Asset Class Classe asset + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3029,6 +2597,26 @@ Symbol Simbolo + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3037,6 +2625,10 @@ Tag Etichetta + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3045,9 +2637,13 @@ Cash Contanti + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3061,6 +2657,10 @@ Equity Azione ordinaria + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + libs/ui/src/lib/i18n.ts 46 @@ -3095,7 +2695,7 @@ Criptovaluta libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3103,7 +2703,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3111,7 +2711,7 @@ Fondo comune di investimento libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3119,7 +2719,7 @@ Metalli preziosi libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3127,7 +2727,7 @@ Azione ordinaria privata libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3135,12 +2735,24 @@ Azione libs/ui/src/lib/i18n.ts - 58 + 60 Emergency Fund Fondo di emergenza + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3155,19 +2767,35 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 No data available Nessun dato disponibile + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 @@ -3175,7 +2803,7 @@ Nord America libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3183,7 +2811,7 @@ Africa libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3191,7 +2819,7 @@ Asia libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3199,7 +2827,7 @@ Europa libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3207,7 +2835,7 @@ Oceania libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3215,10 +2843,10 @@ Sud America libs/ui/src/lib/i18n.ts - 70 + 72 - + The following file formats are supported: Sono supportati i seguenti formati di file: @@ -3226,7 +2854,7 @@ 90 - + Back Indietro @@ -3238,112 +2866,100 @@ 178 - - Community - Comunità - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 - - - + Activities Count Conteggio attività apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + 157 - + Refresh Aggiorna apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + 17 - + Symbol Mapping Mappatura dei simboli apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 Dividend Dividendi + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts 36 - + Dividend Timeline Cronologia dei dividendi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 Asset Sub Class Sottoclasse asset + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + libs/ui/src/lib/i18n.ts 7 - + User Signup Registrazione utente apps/client/src/app/components/admin-overview/admin-overview.html - 111 + 34 @@ -3351,10 +2967,10 @@ Convalida dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + Import Importa @@ -3367,46 +2983,42 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Market Data Dati del mercato - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Users Utenti - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 61 Summary Summario - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 - + Holding Partecipazione @@ -3415,10 +3027,10 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Carica i dividendi @@ -3431,7 +3043,7 @@ Annuale apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3439,15 +3051,23 @@ Importa i dividendi apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Valido fino a apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3502,39 +3122,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values Protezione delle informazioni sensibili come le prestazioni assolute e i valori quantitativi apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times Esperienza priva di distrazioni per i periodi più turbolenti apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality Un’anteprima delle funzionalità in arrivo apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? Sei un investitore ambizioso che ha bisogno di un quadro completo? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Riepilogo del portafoglio @@ -3543,14 +3163,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Benchmark delle prestazioni @@ -3559,14 +3179,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator Calcolatore FIRE @@ -3575,14 +3195,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... e altre funzionalità... @@ -3591,175 +3211,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Salta apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Aggiorna il piano apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Per gli investitori esperti di tecnologia che preferiscono gestire Ghostfolio sulla propria infrastruttura. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Transazioni illimitate apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Account illimitati apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Prestazioni del portafoglio apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Self-hosted, aggiornamento manuale. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Free apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Per i nuovi investitori che hanno appena iniziato a fare trading. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Offerta cloud Ghostfolio completamente gestita. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Per gli investitori ambiziosi che hanno bisogno di un quadro completo dei propri asset finanziari. apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Pagamento una tantum, senza rinnovo automatico. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Inizia apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - + It’s free. È gratuito. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 353 - + Fees Commissioni apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3767,10 +3403,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Allocazioni del portafoglio @@ -3783,14 +3419,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Tasso di risparmio al mese @@ -3798,20 +3434,20 @@ 10 - + Data Import and Export Importazione ed esportazione dei dati apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3822,20 +3458,20 @@ 13 - + Community Support Supporto della comunità apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support Supporto via email e chat apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3854,7 +3490,7 @@ 14 - + Market data provided by Dati del mercato forniti da @@ -3862,23 +3498,7 @@ 2 - - Oops! Could not get the historical exchange rate from - Ops! Impossibile ottenere il tasso di cambio storico da - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - - Gather Historical Data - Raccogli dati storici - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 - - - + Retirement Date Data di pensionamento @@ -3886,7 +3506,7 @@ 32 - + Professional Data Provider Fornitore di dati professionale @@ -3895,10 +3515,10 @@ apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans Piani tariffari @@ -3906,7 +3526,7 @@ 4 - + Renew Plan Rinnova il piano @@ -3915,35 +3535,35 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - La nostra offerta cloud ufficiale Ghostfolio Premium è il modo più semplice per iniziare. Grazie al risparmio di tempo, questa è l’opzione migliore per la maggior parte delle persone. I ricavi vengono utilizzati per coprire l’infrastruttura di hosting e per finanziare lo sviluppo continuo di Ghostfolio. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + La nostra offerta cloud ufficiale Ghostfolio Premium è il modo più semplice per iniziare. Grazie al risparmio di tempo, questa è l’opzione migliore per la maggior parte delle persone. I ricavi vengono utilizzati per coprire l’infrastruttura di hosting e per finanziare lo sviluppo continuo di Ghostfolio. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User Imita l’utente apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User Elimina l’utente apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 @@ -3951,10 +3571,10 @@ Vuoi davvero eliminare tutte le tue attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider Per fornitore di ETF @@ -3962,7 +3582,7 @@ 306 - + Update platform Aggiorna la piattaforma @@ -3970,7 +3590,7 @@ 8 - + Add platform Aggiungi la piattaforma @@ -3978,16 +3598,20 @@ 10 - + Url Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3999,18 +3623,18 @@ Vuoi davvero eliminare questa piattaforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms Piattaforme apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance Aggiornamento del saldo di cassa @@ -4018,7 +3642,7 @@ 112 - + By Platform Per piattaforma @@ -4026,56 +3650,44 @@ 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: Effettua oggi stesso l’aggiornamento a Ghostfolio Premium e ottieni l’accesso a funzionalità esclusive per migliorare la tua esperienza di investimento: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. Ottieni gli strumenti per gestire efficacemente le tue finanze e perfezionare la tua strategia di investimento personale. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform Aggiungi la piattaforma apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings Impostazioni - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Azione ordinaria - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 @@ -4086,7 +3698,7 @@ 19 - + Manage Benchmarks Gestisci i benchmark @@ -4094,7 +3706,7 @@ 35 - + Select Holding Seleziona la partecipazione @@ -4102,7 +3714,7 @@ 20 - + Select File Seleziona il file @@ -4110,7 +3722,7 @@ 22 - + Select Dividends Seleziona i dividendi @@ -4118,7 +3730,7 @@ 113 - + Select Activities Seleziona le attività @@ -4126,64 +3738,36 @@ 115 - - Import Activities - Importa le attività - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Importa i dividendi - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Finanza personale + + Frequently Asked Questions (FAQ) + Domande più frequenti (FAQ) - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Domande più frequenti (FAQ) - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak Serie attuale apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak Serie più lunga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 @@ -4218,12 +3802,12 @@ 30 - + Liabilities Passività apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4234,35 +3818,35 @@ Changelog Changelog - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License Licenza - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Azioni - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs ETF @@ -4270,7 +3854,7 @@ 25 - + Bonds Obbligazioni @@ -4278,15 +3862,7 @@ 38 - - Cryptocurrencies - Criptovalute - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items Oggetti della ricchezza @@ -4294,15 +3870,15 @@ 76 - + Import and Export Importazione ed esportazione apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts Account multipli @@ -4310,7 +3886,7 @@ 127 - + Portfolio Calculations Calcoli del portafoglio @@ -4318,44 +3894,44 @@ 141 - + Dark Mode Modalità scura apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood Umore del mercato apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis Analisi statica apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language Multilingue apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software Software open source apps/client/src/app/pages/features/features-page.html - 278 + 295 @@ -4366,15 +3942,15 @@ 40 - + Scraper Configuration Configurazione dello scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile Aggiungi il profilo dell’asset @@ -4386,19 +3962,23 @@ Personal Finance Tools Strumenti di finanza personale - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Scopri le alternative open source per gli strumenti di finanza personale apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Fondato @@ -4406,7 +3986,7 @@ 77 - + Origin Origine @@ -4414,7 +3994,7 @@ 82 - + Region Regione @@ -4422,15 +4002,15 @@ 87 - + Available in Disponibile in apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Si @@ -4466,7 +4046,7 @@ 274 - + ❌ No ❌ No @@ -4502,31 +4082,31 @@ 281 - + Self-Hosting Self-hosting apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Usalo in modo anonimo apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Piano gratuito apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Note @@ -4534,39 +4114,15 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Monitora, analizza e visualizza facilmente la tua ricchezza con Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Strumenti di finanza personale - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Guide - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 - - - - Glossary - Glossario - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + 329 - + Stocks, ETFs, bonds, cryptocurrencies, commodities Azioni, ETF, obbligazioni, criptovalute e materie prime @@ -4578,7 +4134,7 @@ 65 - + Mortgages, personal loans, credit cards Mutui, prestiti personali, carte di credito @@ -4586,7 +4142,7 @@ 57 - + Luxury items, real estate, private companies Articoli di lusso, immobili, aziende private @@ -4597,6 +4153,10 @@ Buy Compra + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4615,7 +4175,7 @@ ETF senza paesi apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 @@ -4623,15 +4183,15 @@ ETF senza settori apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets Asset apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 @@ -4642,7 +4202,7 @@ 25 - + By Market Per mercato @@ -4663,118 +4223,98 @@ Giappone libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio Benvenuto su Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts Configura i tuoi account apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. Ottieni una panoramica finanziaria completa aggiungendo i tuoi conti bancari e di trading. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities Cattura le tue attività apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. Registra le tue attività di investimento per tenere aggiornato il tuo portafoglio. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio Monitora e analizza il tuo portafoglio apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. Monitora i tuoi progressi in tempo reale, con analisi e approfondimenti completi. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - Nessun dato disponibile - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? Sei pronto a prendere il controllo delle tue finanze personali? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts Configura gli account apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication Autenticazione biometrica apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. Per Ghostfolio la trasparenza è al centro dei propri valori. Pubblichiamo il codice sorgente come software open source (OSS) sotto la licenza AGPL-3.0 e condividiamo apertamente le metriche chiave aggregate dello stato operativo della piattaforma. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users Utenti attivi @@ -4786,7 +4326,7 @@ 62 - + New Users Nuovi utenti @@ -4794,7 +4334,7 @@ 51 - + Users in Slack community Utenti nella comunità Slack @@ -4802,7 +4342,7 @@ 75 - + Contributors on GitHub Contributori su GitHub @@ -4810,7 +4350,7 @@ 89 - + Stars on GitHub Stelle su GitHub @@ -4822,7 +4362,7 @@ 103 - + Pulls on Docker Hub Estrazioni su Docker Hub @@ -4834,7 +4374,7 @@ 117 - + Uptime Tempo di attività @@ -4842,12 +4382,12 @@ 132 - + Export Data Esporta dati apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 @@ -4855,10 +4395,14 @@ Valute apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 - + Our Nostri @@ -4866,7 +4410,7 @@ 6 - + Visit Visita @@ -4874,7 +4418,7 @@ 28 - + Discover other exciting Open Source Software projects Scopri altri interessanti progetti di software open source @@ -4882,31 +4426,15 @@ 9 - - Frequently Asked Questions (FAQ) - Domande più frequenti (FAQ) - - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 - - - apps/client/src/app/pages/faq/saas/saas-page.html - 4 - - - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 - - - + Check out the numerous features of Ghostfolio to manage your wealth Scopri le numerose funzionalità di Ghostfolio per gestire la tua ricchezza apps/client/src/app/pages/features/features-page.html - 6 + 7 - + Discover the latest Ghostfolio updates and insights on personal finance Scopri gli ultimi aggiornamenti e approfondimenti di Ghostfolio sulla finanza personale @@ -4914,43 +4442,31 @@ 7 - + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. Se preferisci eseguire Ghostfolio sulla tua infrastruttura, puoi trovare il codice sorgente e ulteriori istruzioni su GitHub. apps/client/src/app/pages/pricing/pricing-page.html - 26 + 14 - + Manage your wealth like a boss Gestisci la tua ricchezza come un capo apps/client/src/app/pages/landing/landing-page.html - 5 + 6 - + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. Ghostfolio è uno strumento open source e rispettoso della privacy per la gestione delle tue finanze personali. Analizza la tua allocazione degli asset, conosci il tuo patrimonio netto e prendi decisioni di investimento solide e basate sui dati. apps/client/src/app/pages/landing/landing-page.html - 9 - - - - Get Started - Inizia - - apps/client/src/app/pages/landing/landing-page.html - 41 - - - apps/client/src/app/pages/pricing/pricing-page.html - 324 + 10 - + Monthly Active Users Utenti attivi mensili @@ -4958,7 +4474,7 @@ 70 - + As seen in Come si vede su @@ -4966,23 +4482,23 @@ 115 - + Protect your assets. Refine your personal investment strategy. Proteggi i tuoi asset. Perfeziona la tua strategia di investimento personale. apps/client/src/app/pages/landing/landing-page.html - 225 + 226 - + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. Ghostfolio permette alle persone impegnate di tenere traccia di azioni, ETF o criptovalute senza essere tracciate. apps/client/src/app/pages/landing/landing-page.html - 229 + 230 - + 360° View Vista a 360° @@ -4990,7 +4506,7 @@ 240 - + Web3 Ready Pronto per il Web3 @@ -4998,31 +4514,23 @@ 251 - + Use Ghostfolio anonymously and own your financial data. Usa Ghostfolio in modo anonimo e possiedi i tuoi dati finanziari. apps/client/src/app/pages/landing/landing-page.html - 253 - - - - Open Source - Open source - - apps/client/src/app/pages/landing/landing-page.html - 261 + 254 - + Benefit from continuous improvements through a strong community. Beneficia dei continui miglioramenti grazie a una forte comunità. apps/client/src/app/pages/landing/landing-page.html - 263 + 264 - + Why Ghostfolio? Perché Ghostfolio? @@ -5030,15 +4538,15 @@ 272 - + Ghostfolio is for you if you are... Ghostfolio è per te se... apps/client/src/app/pages/landing/landing-page.html - 273 + 274 - + trading stocks, ETFs or cryptocurrencies on multiple platforms fai trading di azioni, ETF o criptovalute su più piattaforme @@ -5046,7 +4554,7 @@ 280 - + pursuing a buy & hold strategy persegui una strategia buy & hold @@ -5054,7 +4562,7 @@ 286 - + interested in getting insights of your portfolio composition sei interessato a conoscere la composizione del tuo portafoglio @@ -5062,7 +4570,7 @@ 291 - + valuing privacy and data ownership valorizzi la privacy e la proprietà dei dati @@ -5070,7 +4578,7 @@ 296 - + into minimalism sei per il minimalismo @@ -5078,7 +4586,7 @@ 299 - + caring about diversifying your financial resources ti interessa diversificare le tue risorse finanziarie @@ -5086,7 +4594,7 @@ 303 - + interested in financial independence sei interessato all’indipendenza finanziaria @@ -5094,7 +4602,7 @@ 307 - + saying no to spreadsheets in non vuoi utilizzare il foglio elettronico nel @@ -5102,7 +4610,7 @@ 311 - + still reading this list stai ancora leggendo questo elenco @@ -5110,7 +4618,7 @@ 314 - + Learn more about Ghostfolio Ulteriori informazioni su Ghostfolio @@ -5118,31 +4626,31 @@ 319 - + What our users are saying Cosa dicono i nostri utenti apps/client/src/app/pages/landing/landing-page.html - 327 + 328 - + Members from around the globe are using Ghostfolio Premium Membri da tutto il mondo utilizzano Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 366 + 367 - + How does Ghostfolio work? Come funziona Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 383 + 384 - + Sign up anonymously* Iscriviti in modo anonimo* @@ -5150,7 +4658,7 @@ 392 - + * no e-mail address nor credit card required * non è richiesto alcun indirizzo email né la carta di credito @@ -5158,51 +4666,39 @@ 394 - + Add any of your historical transactions Aggiungi le tue transazioni storiche apps/client/src/app/pages/landing/landing-page.html - 405 + 406 - + Get valuable insights of your portfolio composition Ottieni informazioni preziose sulla composizione del tuo portafoglio apps/client/src/app/pages/landing/landing-page.html - 417 + 418 - + Are you ready? Sei pronto? apps/client/src/app/pages/landing/landing-page.html - 431 - - - - Live Demo - Demo in tempo reale - - apps/client/src/app/pages/landing/landing-page.html - 49 - - - apps/client/src/app/pages/landing/landing-page.html - 451 + 432 - + Get the full picture of your personal finances across multiple platforms. Ottieni un quadro completo delle tue finanze personali su più piattaforme. apps/client/src/app/pages/landing/landing-page.html - 242 + 243 - + Get started in only 3 steps Inizia in soli 3 passi @@ -5210,2427 +4706,3430 @@ 386 - + faq domande-piu-frequenti - snake-case - - apps/client/src/app/app.component.ts - 77 - - - apps/client/src/app/core/paths.ts - 3 - - - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 - + kebab-case - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 245 - + features funzionalita - snake-case + kebab-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 255 + + + about + informazioni-su + kebab-case - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/core/paths.ts - 4 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 214 + + + privacy-policy + informativa-sulla-privacy + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 207 + + + license + licenza + kebab-case - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 - - - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + mercati + kebab-case - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 260 - - about - informazioni-su - snake-case + + pricing + prezzi + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 270 + + + register + iscrizione + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + risorse + kebab-case - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 322 + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Questa pagina panoramica presenta una raccolta curata di strumenti di finanza personale confrontati con l’alternativa open source Ghostfolio. Se apprezzi la trasparenza, la privacy dei dati e la collaborazione con la comunità, Ghostfolio ti offre un’ottima opportunità per prendere il controllo della tua gestione finanziaria. - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Esplora i link qui sotto per confrontare una serie di strumenti di finanza personale con Ghostfolio. - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + Open Source Alternative to + L’alternativa open source a - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + The Open Source Alternative to + L’alternativa open source a - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Stai cercando un’alternativa open source a ? Ghostfolio è un potente strumento di gestione del portafoglio che fornisce alle persone una piattaforma completa per monitorare, analizzare e ottimizzare i propri investimenti. Che tu sia un investitore esperto o alle prime armi, Ghostfolio offre un’interfaccia utente intuitiva e un’ampia gamma di funzionalità per aiutarti a prendere decisioni informate e il controllo del tuo futuro finanziario. - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio è un software open source (OSS) che offre un’alternativa economicamente vantaggiosa a particolarmente adatta a persone con un budget limitato, come quelle che perseguono l’indipendenza finanziaria e il pensionamento anticipato (FIRE). Grazie agli sforzi collettivi di una comunità di sviluppatori e di appassionati di finanza personale, Ghostfolio migliora continuamente le sue capacità, la sua sicurezza e la sua esperienza utente. - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Analizziamo nel dettaglio la tabella di confronto qui sotto per comprendere a fondo come Ghostfolio si posiziona rispetto a . Esploreremo vari aspetti come le caratteristiche, la privacy dei dati, il prezzo e altro ancora, permettendoti di fare una scelta ben informata per le tue esigenze personali. - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + open-source-alternative-to + alternativa-open-source-a + kebab-case - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 324 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Nota bene: le informazioni fornite si basano sulle nostre ricerche e analisi indipendenti. Questo sito web non è affiliato con o a qualsiasi altro prodotto citato nel confronto. Poiché il panorama degli strumenti di finanza personale si evolve, è essenziale verificare qualsiasi dettaglio o modifica specifica direttamente nella pagina del prodotto in questione. I dati hanno bisogno di essere aggiornati? Aiutaci a mantenere i dati accurati su GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - privacy-policy - informativa-sulla-privacy - snake-case + + Ready to take your investments to the next level? + Sei pronto a portare il tuo investimento al livello successivo? - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Switzerland + Svizzera - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/ui/src/lib/i18n.ts + 96 - - license - licenza - snake-case + + Global + Globale - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/core/paths.ts - 5 + libs/ui/src/lib/i18n.ts + 16 + + + (Last 24 hours) + (Ultime 24 ore) - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/open/open-page.html + 37 - - markets - mercati - snake-case + + (Last 30 days) + (Ultimi 30 giorni) - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/pages/open/open-page.html + 59 + + + (Last 90 days) + (Ultimi 90 giorni) - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/pages/open/open-page.html + 127 + + + Choose or drop a file here + Seleziona o trascina qui un file - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + You are using the Live Demo. + Stai usando la Live Demo. - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/app.component.html + 12 + + + One-time fee, annual account fees + Commissione una tantum, commissioni annuali per l’account - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 + + + Distribution of corporate earnings + A distribuzione dei dividendi - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Fee + Commissione - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - - - pricing - prezzi - snake-case - apps/client/src/app/app.component.ts - 80 + libs/ui/src/lib/i18n.ts + 37 + + + Revenue for lending out money + Ricavi dal prestito di soldi - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + Add Tag + Aggiungi un Tag - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + Do you really want to delete this tag? + Sei sicuro di voler eliminare questo tag? - apps/client/src/app/components/header/header.component.ts - 89 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Aggiorna il tag - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Aggiungi un tag - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Currency Cluster Risks + Rischio di Concentrazione Valutario - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + Account Cluster Risks + Rischi di Concentrazione dei Conti - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Transfer Cash Balance + Trasferisci il saldo di cassa - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Version + Versione - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + From + Da - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + To + A - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 - - - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + Transfer + Trasferisci - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + Membership + Iscrizione - libs/ui/src/lib/membership-card/membership-card.component.ts + libs/common/src/lib/routes/routes.ts 31 - - - register - iscrizione - snake-case - apps/client/src/app/app.component.ts - 81 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Accesso - apps/client/src/app/components/header/header.component.ts - 90 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Profilo dell’asset - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Do you really want to delete this asset profile? + Vuoi veramente eliminare il profilo di questo asset? - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Cerca - apps/client/src/app/pages/faq/saas/saas-page.component.ts + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 16 + + + Add Manually + Aggiungi manualmente - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio è un dashboard di finanza personale per tenere traccia delle vostre attività come azioni, ETF o criptovalute su più piattaforme. - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Ultimo massimo storico - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - resources - risorse - snake-case + + User + Utente - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs tabella di comparazione - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + Open Source Wealth Management Software + Software Open Source per la gestione della tua ricchezza - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + app, asset, crypto, dashboard, etf, finanza, gestione patrimoniale, rendimenti, portafoglio, software, stock, azioni, titoli, obbligazioni, trading, ricchezza, web3 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/i18n/i18n-page.html 10 + + + Oops, cash balance transfer has failed. + Ops, il trasferimento del saldo di cassa è fallito. - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Paura estrema - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Avidità estrema - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Neutrale - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + Ops! Impossibile elaborare i dati storici. - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + Confermi di voler cancellare questo messaggio di sistema? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + Trend a 50 giorni - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + Trend a 200 giorni - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + Cash Balances + Saldi di cassa - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + Starting from + Inizia da - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Questa pagina panoramica presenta una raccolta curata di strumenti di finanza personale confrontati con l’alternativa open source Ghostfolio. Se apprezzi la trasparenza, la privacy dei dati e la collaborazione con la comunità, Ghostfolio ti offre un’ottima opportunità per prendere il controllo della tua gestione finanziaria. + + Do you really want to delete this account balance? + Vuoi veramente elimnare il saldo di questo conto? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Esplora i link qui sotto per confrontare una serie di strumenti di finanza personale con Ghostfolio. + + If a translation is missing, kindly support us in extending it here. + Se manca una traduzione, puoi aiutarci modificando questo file: here. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Open Source Alternative to - L’alternativa open source a + + The current market price is + L’attuale prezzo di mercato è - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Open Source Alternative to - L’alternativa open source a + + Test + Prova - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - The Open Source Alternative to - L’alternativa open source a + + Date Range + Intervallo di date - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + libs/ui/src/lib/assistant/assistant.html + 143 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Stai cercando un’alternativa open source a ? Ghostfolio è un potente strumento di gestione del portafoglio che fornisce alle persone una piattaforma completa per monitorare, analizzare e ottimizzare i propri investimenti. Che tu sia un investitore esperto o alle prime armi, Ghostfolio offre un’interfaccia utente intuitiva e un’ampia gamma di funzionalità per aiutarti a prendere decisioni informate e il controllo del tuo futuro finanziario. + + Permission + Permessi - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/access-table/access-table.component.html 18 - - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio è un software open source (OSS) che offre un’alternativa economicamente vantaggiosa a particolarmente adatta a persone con un budget limitato, come quelle che perseguono l’indipendenza finanziaria e il pensionamento anticipato (FIRE). Grazie agli sforzi collettivi di una comunità di sviluppatori e di appassionati di finanza personale, Ghostfolio migliora continuamente le sue capacità, la sua sicurezza e la sua esperienza utente. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html 32 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Analizziamo nel dettaglio la tabella di confronto qui sotto per comprendere a fondo come Ghostfolio si posiziona rispetto a . Esploreremo vari aspetti come le caratteristiche, la privacy dei dati, il prezzo e altro ancora, permettendoti di fare una scelta ben informata per le tue esigenze personali. - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 - - - - open-source-alternative-to - alternativa-open-source-a + + Restricted view + Vista limitata - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts + apps/client/src/app/components/access-table/access-table.component.html 26 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Nota bene: le informazioni fornite si basano sulle nostre ricerche e analisi indipendenti. Questo sito web non è affiliato con o a qualsiasi altro prodotto citato nel confronto. Poiché il panorama degli strumenti di finanza personale si evolve, è essenziale verificare qualsiasi dettaglio o modifica specifica direttamente nella pagina del prodotto in questione. I dati hanno bisogno di essere aggiornati? Aiutaci a mantenere i dati accurati su GitHub. + + Oops! Could not grant access. + Ops! Impossibile abilitare l’accesso. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 - - Ready to take your investments to the next level? - Sei pronto a portare il tuo investimento al livello successivo? + + Private + Privato - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - Get Started - Inizia + + Job Queue + Coda Lavori - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + libs/common/src/lib/routes/routes.ts + 46 - - Switzerland - Svizzera - + + Market data is delayed for + I dati di mercato sono ritardati di + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Investment + Investimento + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + + Absolute Asset Performance + Rendimento assoluto dell’Asset + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + + Asset Performance + Rendimento dell’Asset + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + + Absolute Currency Performance + Rendimento assoluto della Valuta + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + + Currency Performance + Rendimento della Valuta + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + + Absolute Net Performance + Rendimento assoluto della Valuta + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + + Net Performance + Rendimento Netto + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + + Week to date + Da inizio settimana + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + WTD + Settimana corrente + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + Month to date + Da inizio mese + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + MTD + Mese corrente + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + Year to date + Da inizio anno + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + View + Visualizza + + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + + Oops! A data provider is experiencing the hiccups. + Ops! Un data provider sta riscontrando dei problemi. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Se andassi in pensione oggi, saresti in grado di prelevare all’anno o al mese, calcolato sul valore totale dei tuoi asset di e un prelievo costante del 4%. + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + + Reset Filters + Reset Filtri + + libs/ui/src/lib/assistant/assistant.html + 238 + + + + year + anno + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + anni + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Apply Filters + Applica i Filtri + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + Data Gathering + Raccolta Dati + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + General + Generale + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Cloud + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Self-Hosting + + apps/client/src/app/pages/faq/faq-page.component.ts 60 + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + self-hosting + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Ops! Sembra tu stia facendo troppe richieste. Rallenta un po’ per favore. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + My Account + Il mio Account + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Active + Attivo + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Chiuso + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Indonesia + Indonesia + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Attività + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Dividend Yield + Rendimento da Dividendi + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Execute Job + Esegui il lavoro + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Priority + Priorità + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + This action is not allowed. + Questa azione non è permessa. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Liquidity + Liquidità + + libs/ui/src/lib/i18n.ts + 48 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {attività} other {attività}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Compra e vendi + + libs/ui/src/lib/i18n.ts + 8 + + + + Delete Activities + Elimina le attività + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internazionalizzazione + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + Confermi di voler chiudere il tuo account Ghostfolio? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Zona di Pericolo + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Chiudi l’account + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Per ETF posseduti + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Approssimato in base ai principali ETF posseduti + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Registrati adesso o prova l’account demo + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + Ops! C’è stato un errore impostando l’autenticazione biometrica. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Visualizza di più + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Benchmarks + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Elimina i profili + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Confermi di voler eliminare questi profili? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + Ops! Impossibile eliminare i profili. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + Tabella + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Grafico + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + Vorresti perfezionare la tua strategia personale di investimento? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternativa + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + App + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Budgeting + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Comunità + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Ufficio familiare + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Investitore + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Open Source + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Finanza Personale + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Privacy + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Software + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Strumento + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Esperienza Utente + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Ricchezza + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Gestione Patrimoniale + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Australia + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Austria + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Belgio + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bulgaria + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Canada + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + Repubblica Ceca + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finlandia + + libs/ui/src/lib/i18n.ts + 83 + + + + France + Francia + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Germania + + libs/ui/src/lib/i18n.ts + 85 + + + + India + India + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Italia + + libs/ui/src/lib/i18n.ts + 88 + + + + Netherlands + Olanda + + libs/ui/src/lib/i18n.ts + 90 + + + + New Zealand + Nuova Zelanda + + libs/ui/src/lib/i18n.ts + 91 + + + + Poland + Polonia + + libs/ui/src/lib/i18n.ts + 92 + + + + Romania + Romania + + libs/ui/src/lib/i18n.ts + 93 + + + + South Africa + Sud Africa + + libs/ui/src/lib/i18n.ts + 95 + + + + Thailand + Tailandia + + libs/ui/src/lib/i18n.ts + 97 + + + + United States + Stati Uniti + + libs/ui/src/lib/i18n.ts + 100 + + + + Error + Errore + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + + Deactivate + Disattiva + + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Attiva + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Inactive + Inattivo + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Cancel + Annulla + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + libs/ui/src/lib/i18n.ts - 90 + 9 - - Global - Globale + + Close + Chiudi - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 libs/ui/src/lib/i18n.ts - 16 + 11 - - (Last 24 hours) - (Ultime 24 ore) + + Yes + Si - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/i18n.ts + 32 - - (Last 30 days) - (Ultimi 30 giorni) - - apps/client/src/app/pages/open/open-page.html - 48 - + + Copy link to clipboard + Copia link negli appunti - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - (Last 90 days) - (Ultimi 90 giorni) + + Portfolio Snapshot + Stato del Portfolio - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Choose or drop a file here - Seleziona o trascina qui un file + + Change with currency effect Change + Cambio con effetto valuta Cambia - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - You are using the Live Demo. - Stai usando la Live Demo. + + Performance with currency effect Performance + Prestazioni con effetto valuta Prestazioni - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - One-time fee, annual account fees - Commissione una tantum, commissioni annuali per l'account + + Threshold Min + Soglia Minima - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Distribution of corporate earnings - A distribuzione dei dividendi + + Threshold Max + Soglia Massima - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Oops! Could not get the historical exchange rate from - Ops! Impossibile ottenere il tasso di cambio storico da + + Customize + Personalizza - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/rule/rule.component.html + 67 - - Fee - Commissione + + No auto-renewal. + No rinnovo automatico. - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Interest - Interesse + + This year + Anno corrente - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/public/public-page.html + 42 - - Revenue for lending out money - Ricavi dal prestito di soldi + + From the beginning + Dall’inizio - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/pages/public/public-page.html + 60 - - Add Tag - Aggiungi un Tag + + Oops! Invalid currency. + Oops! Valuta sbagliata. - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Do you really want to delete this tag? - Sei sicuro di voler eliminare questo tag? + + This page has been archived. + Questa pagina è stata archiviata. - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Update tag - Aggiorna il tag + + is Open Source Software + è un programma Open Source - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - - - Add tag - Aggiungi un tag - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Currency Cluster Risks - Rischio di Concentrazione Valutario + + is not Open Source Software + non è un programma Open Source - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Account Cluster Risks - Rischi di Concentrazione dei Conti - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Transfer Cash Balance - Trasferisci il saldo di cassa + + can be self-hosted + può essere ospitato in proprio - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Benchmark - Benchmark + + cannot be self-hosted + non può essere ospitato in proprio - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Version - Versione - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Settings - Impostazioni + + can be used anonymously + può essere usato anonimamente - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - From - Da - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - To - A + + cannot be used anonymously + non può essere usato anonimamente - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - Transfer - Trasferisci - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Membership - Iscrizione + + offers a free plan + ha un piano gratuito - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Access - Accesso + + does not offer a free plan + non ha un piano gratuito - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Find holding... - Trova possedimenti... + + Oops! Could not find any assets. + Oops! Non ho trovato alcun asset. - libs/ui/src/lib/assistant/assistant.component.ts - 144 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - No entries... - Nessun risultato... - - libs/ui/src/lib/assistant/assistant.html - 63 - + + Data Providers + Fornitori di dati - libs/ui/src/lib/assistant/assistant.html - 84 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Asset Profile - Profilo dell'asset + + Set API key + Imposta API Key - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 - - - - Do you really want to delete this asset profile? - Vuoi veramente eliminare il profilo di questo asset? + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 + + + + Get access to 80’000+ tickers from over 50 exchanges + Ottieni accesso a oltre 80’000+ titoli da oltre 50 borse - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + libs/ui/src/lib/i18n.ts + 24 - - Search - Cerca + + Ukraine + Ucraina - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + libs/ui/src/lib/i18n.ts + 98 - - Add Manually - Aggiungi manualmente + + Join now + Iscriviti adesso - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio è un dashboard di finanza personale per tenere traccia delle vostre attività come azioni, ETF o criptovalute su più piattaforme. + + Glossary + Glossario - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html 4 - - - Last All Time High - Ultimo massimo storico - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - User - Utente - apps/client/src/app/components/admin-users/admin-users.html - 29 + libs/common/src/lib/routes/routes.ts + 293 - - Ghostfolio vs comparison table - Ghostfolio vs tabella di comparazione + + Guides + Guide - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Open Source Wealth Management Software - Software Open Source per la gestione della tua ricchezza - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, asset, crypto, dashboard, etf, finanza, gestione patrimoniale, rendimenti, portafoglio, software, stock, azioni, titoli, obbligazioni, trading, ricchezza, web3 - apps/client/src/app/pages/i18n/i18n-page.html - 9 + libs/common/src/lib/routes/routes.ts + 301 - - Oops, cash balance transfer has failed. - Ops, il trasferimento del saldo di cassa è fallito. + + guides + guide + kebab-case - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + libs/common/src/lib/routes/routes.ts + 296 - - - Extreme Fear - Paura estrema - libs/ui/src/lib/i18n.ts - 96 + libs/common/src/lib/routes/routes.ts + 299 - - Extreme Greed - Avidità estrema + + glossary + glossario + kebab-case - libs/ui/src/lib/i18n.ts - 97 + libs/common/src/lib/routes/routes.ts + 288 - - - Neutral - Neutrale - libs/ui/src/lib/i18n.ts - 100 + libs/common/src/lib/routes/routes.ts + 291 - - Oops! Could not parse historical data. - Ops! Impossibile elaborare i dati storici. + + Threshold range + Range soglia - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Do you really want to delete this system message? - Confermi di voler cancellare questo messaggio di sistema? + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray utilizza l’analisi statica per scoprire potenziali problemi e rischi nel tuo portafoglio. Modifica le regole qui sotto e imposta soglie personalizzate per allinearti alla tua strategia di investimento personale. - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - 50-Day Trend - Trend a 50 giorni + + Economic Market Cluster Risks + Rischi del cluster di mercato economico - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - 200-Day Trend - Trend a 200 giorni + + of + di - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Cash Balances - Saldi di cassa + + daily requests + richieste giornaliere - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Starting from - Inizia da + + Remove API key + Rimuovi API key - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 + + + Do you really want to delete the API key? + Vuoi davvero eliminare l’API key? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - year - anno + + Please enter your Ghostfolio API key: + Inserisci la tua API key di Ghostfolio: - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/pages/api/api-page.component.ts + 41 + + + API Requests Today + Richieste API oggi - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Do you really want to delete this account balance? - Vuoi veramente elimnare il saldo di questo conto? + + Could not generate an API key + Non è stato possibile generare un API key - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - is an invalid currency! - non è una valuta valida! + + Set this API key in your self-hosted environment: + Imposta questa API key nel tuo ambiente self-hosted: - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - If a translation is missing, kindly support us in extending it here. - Se manca una traduzione, puoi aiutarci modificando questo file: here. + + Ghostfolio Premium Data Provider API Key + API Key for Ghostfolio Premium Data Provider - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - The current market price is - L'attuale prezzo di mercato è + + Do you really want to generate a new API key? + Vuoi davvero generare una nuova API key? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Test - Prova + + API Key + API Key - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - Date Range - Intervallo di date + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Genera API key per Ghostfolio Premium Data Provider per ambienti self-hosted... - libs/ui/src/lib/assistant/assistant.html - 93 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - Permission - Permessi + + out of + fuori - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 + + + rules align with your portfolio. + le regole si allineano con il tuo portafoglio. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Restricted view - Vista limitata + + Save + Salva - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Oops! Could not grant access. - Ops! Impossibile abilitare l'accesso. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - Private - Privato - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 - - - Job Queue - Coda Lavori - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 + + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Market data is delayed for - I dati di mercato sono ritardati di - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 - - - Investment - Investimento - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Absolute Asset Performance - Rendimento assoluto dell'Asset + + Asset Class Cluster Risks + Rischi del cluster di classi di asset - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Asset Performance - Rendimento dell'Asset + + Me + Me - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/header/header.component.html + 213 - - - Absolute Currency Performance - Rendimento assoluto della Valuta - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Currency Performance - Rendimento della Valuta + + Received Access + Accesso ricevuto - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Absolute Net Performance - Rendimento assoluto della Valuta + + Please enter your Ghostfolio API key. + Inserisci la tua API key di Ghostfolio. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Net Performance - Rendimento Netto + + AI prompt has been copied to the clipboard + L’AI prompt è stato copiato negli appunti - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Week to date - Da inizio settimana + + Link has been copied to the clipboard + Il link è stato copiato negli appunti - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - WTD - Settimana corrente + + Regional Market Cluster Risks + Rischi del cluster di mercato regionale - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Month to date - Da inizio mese + + Lazy + Pigro - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - MTD - Mese corrente + + Instant + Istantaneo - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Year to date - Da inizio anno + + Default Market Price + Prezzo di mercato predefinito - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - View - Visualizza + + Mode + Modalità - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 + + + Selector + Selettore - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Oops! A data provider is experiencing the hiccups. - Ops! Un data provider sta riscontrando dei problemi. + + HTTP Request Headers + Intestazioni della richiesta HTTP - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Se andassi in pensione oggi, saresti in grado di prelevare all'anno o al mese, calcolato sul valore totale dei tuoi asset di e un prelievo costante del 4%. + + end of day + fine giornata - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Reset Filters - Reset Filtri + + real-time + in tempo reale - libs/ui/src/lib/assistant/assistant.html - 185 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - year - anno + + Open Duck.ai + Apri Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - years - anni + + Create + Creare - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - Apply Filters - Applica i Filtri + + Change + Cambia - libs/ui/src/lib/assistant/assistant.html - 195 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - Data Gathering - Raccolta Dati - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - General - Generale + + Performance + Prestazione - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - Cloud - Cloud - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Self-Hosting - Self-Hosting - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - self-hosting - self-hosting + + Copy portfolio data to clipboard for AI prompt + Copia i dati del portafoglio negli appunti per l’AI prompt - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - FAQ - FAQ + + Copy AI prompt to clipboard for analysis + Copia l’AI prompt negli appunti per l’analisi - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 + + + Armenia + Armenia - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 75 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Ops! Sembra tu stia facendo troppe richieste. Rallenta un po' per favore. + + British Virgin Islands + Isole Vergini Britanniche - apps/client/src/app/core/http-response.interceptor.ts - 96 + libs/ui/src/lib/i18n.ts + 79 - - My Account - Il mio Account + + Singapore + Singapore - apps/client/src/app/pages/i18n/i18n-page.html - 13 + libs/ui/src/lib/i18n.ts + 94 - - Active - Attivo + + Terms and Conditions + Termini e condizioni - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - Closed - Chiuso + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Ti preghiamo di conservare il tuo token di sicurezza in un luogo sicuro. Se lo perdi, non sarai in grado di recuperare il tuo account. - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Activity - Attività + + I understand that if I lose my security token, I cannot recover my account + Capisco che se perdo il mio token di sicurezza, non posso recuperare il mio account - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Dividend Yield - Rendimento da Dividendi + + Continue + Continua - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Execute Job - Esegui il lavoro + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Ecco il tuo token di sicurezza. È visibile solo una volta, per favore memorizzalo e conserva in un luogo sicuro. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Priority - Priorità + + Security token + Token di sicurezza - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - This action is not allowed. - Questa azione non è permessa. - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Liquidity - Liquidità + + Do you really want to generate a new security token for this user? + Vuoi davvero generare un nuovo token di sicurezza per questo utente? - libs/ui/src/lib/i18n.ts - 48 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {attività} other {attività}} + + Generate Security Token + Genera Token di Sicurezza - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Buy and sell - Compra e vendi + + United Kingdom + United Kingdom libs/ui/src/lib/i18n.ts - 8 + 99 - - Delete Activities - Elimina le attività + + Terms of Service + Termini e condizioni - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Internationalization - Internazionalizzazione + + terms-of-service + termini-e-condizioni + kebab-case - apps/client/src/app/app-routing.module.ts - 88 + libs/common/src/lib/routes/routes.ts + 212 + + + libs/common/src/lib/routes/routes.ts + 215 - - Do you really want to close your Ghostfolio account? - Confermi di voler chiudere il tuo account Ghostfolio? + + Terms of Service + Termini e condizioni - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/app.component.html + 112 + + + libs/common/src/lib/routes/routes.ts + 217 - - Danger Zone - Zona di Pericolo + + and I agree to the Terms of Service. + e io accetto i Termini e condizioni. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Close Account - Chiudi l'account + + () is already in use. + () e gia in uso. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - By ETF Holding - Per ETF posseduti + + An error occurred while updating to (). + Si è verificato un errore durante l’aggiornamento di (). - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Approximation based on the top holdings of each ETF - Approssimato in base ai principali ETF posseduti + + Apply + Applica - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Join now or check out the example account - Registrati adesso o prova l'account demo + + with API access for + con accesso API per - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Oops! There was an error setting up biometric authentication. - Ops! C'è stato un errore impostando l'autenticazione biometrica. + + Gather Recent Historical Market Data + Raccogli dati storici di mercato recenti - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Show more - Visualizza di più + + Gather All Historical Market Data + Raccogli tutti i dati storici di mercato - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Benchmarks - Benchmarks + + Gather Historical Market Data + Raccogli dati storici di mercato - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Delete Profiles - Elimina i profili + + Data Gathering is off + La raccolta dei dati è disattivata apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + 38 - - Do you really want to delete these profiles? - Confermi di voler eliminare questi profili? + + Performance Calculation + Calcolo delle prestazioni - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! Could not delete profiles. - Ops! Impossibile eliminare i profili. + + someone + qualcuno - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Table - Tabella + + Add asset to watchlist + Aggiungi asset alla watchlist - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Chart - Grafico + + Watchlist + Watchlist - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Would you like to refine your personal investment strategy? - Vorresti perfezionare la tua strategia personale di investimento? - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 - - Alternative - Alternativa + + Do you really want to delete this item? + Vuoi davvero eliminare questo elemento? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - App - App + + Log out + Esci - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/header/header.component.html + 329 - - Budgeting - Budgeting + + Calculations are based on delayed market data and may not be displayed in real-time. + I calcoli sono basati su dati di mercato ritardati e potrebbero non essere visualizzati in tempo reale. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 - - Community - Comunità + + changelog + registro-delle-modifiche + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - Family Office - Ufficio familiare + + Demo user account has been synced. + L’account utente demo è stato sincronizzato. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Investor - Investitore + + Sync Demo User Account + Sincronizza l’account utente demo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Open Source - Open Source + + Set up + Fondo di emergenza: istituito - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Personal Finance - Finanza Personale + + No emergency fund has been set up + Non è stato istituito alcun fondo di emergenza - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Privacy - Privacy + + An emergency fund has been set up + È stato istituito un fondo di emergenza - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Software - Software + + Fee Ratio + Rapporto tariffario - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Tool - Strumento + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Le commissioni superano il ${thresholdMax}% del tuo investimento iniziale (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - User Experience - Esperienza Utente + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Le commissioni non superano il ${thresholdMax}% del tuo investimento iniziale (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - Wealth - Ricchezza + + Name + Nome - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth Management - Gestione Patrimoniale + + Find holding or page... + Trova azienda o pagina... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Australia - Australia + + Quick Links + Collegamenti rapidi - libs/ui/src/lib/i18n.ts - 73 + libs/ui/src/lib/assistant/assistant.html + 56 - - Austria - Austria + + Asset Profiles + Profili delle risorse - libs/ui/src/lib/i18n.ts - 74 + libs/ui/src/lib/assistant/assistant.html + 112 - - Belgium - Belgio + + Live Demo + Dimostrazione dal vivo - libs/ui/src/lib/i18n.ts - 75 + apps/client/src/app/pages/landing/landing-page.html + 49 + + + apps/client/src/app/pages/landing/landing-page.html + 452 + + + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bulgaria + + Open Source Alternative to + L’alternativa open source a - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Canada + + Single Account + Conto unico - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - Repubblica Ceca + + Your net worth is managed by a single account + Il tuo patrimonio netto è gestito da un unico account - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finlandia + + Your net worth is managed by ${accountsLength} accounts + Il tuo patrimonio netto è gestito da account ${accountsLength} - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - Francia + + personal-finance-tools + strumenti-di-finanza-personale + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 - - - Germany - Germania - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 315 - - - India - India - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italia + + markets + mercati + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 - - - Netherlands - Olanda - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 307 - - New Zealand - Nuova Zelanda + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Poland - Polonia + + Get Access + Ottieni l’accesso - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Romania - Romania + + Learn more + Saperne di più - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - South Africa - Sud Africa + + Limited Offer! + Offerta limitata! - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Thailand - Tailandia + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - United States - Stati Uniti + + Available + Disponibile - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Error - Errore + + Unavailable + Non disponibile - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Deactivate - Disattiva + + new + nuovo - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Activate - Attiva - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Inactive - Inattivo + + Investment + Investimento - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Cancel - Annulla + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Oltre il ${thresholdMax}% del tuo investimento attuale è pari a ${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Close - Chiudi + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + La maggior parte del tuo investimento attuale è pari a ${maxAccountName} (${maxInvestmentRatio}%) e non supera ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Yes - Si + + Equity + Equità - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Copy link to clipboard - Copia link negli appunti + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + Il contributo azionario del tuo investimento attuale (${equityValueRatio}%) supera ${thresholdMax}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Portfolio Snapshot - Stato del Portfolio + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + Il contributo azionario del tuo investimento attuale (${equityValueRatio}%) è inferiore a ${thresholdMin}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Change with currency effect Change - Cambio con effetto valuta Cambia + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Il contributo azionario del tuo investimento attuale (${equityValueRatio}%) è compreso tra ${thresholdMin}% e ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Performance with currency effect Performance - Prestazioni con effetto valuta Prestazioni + + Fixed Income + Reddito fisso - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Min - Soglia Minima + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + Il contributo a reddito fisso del tuo investimento attuale (${fixedIncomeValueRatio}%) supera ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Max - Soglia Massima + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + Il contributo a reddito fisso del tuo investimento attuale (${fixedIncomeValueRatio}%) è inferiore a ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Close - Chiudi + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + Il contributo a reddito fisso del tuo investimento attuale (${fixedIncomeValueRatio}%) è compreso tra ${thresholdMin}% e ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Customize - Personalizza + + Investment: Base Currency + Investimento: valuta di base - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - No auto-renewal. - No rinnovo automatico. + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + La maggior parte del tuo investimento attuale non è nella valuta di base (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today - Oggi + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + La maggior parte del tuo investimento attuale è nella valuta di base (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - This year - Anno corrente + + Investment + Investimento - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - From the beginning - Dall'inizio + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - Oops! Invalid currency. - Oops! Valuta sbagliata. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - This page has been archived. - Questa pagina è stata archiviata. + + start + inizio + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 336 - - - is Open Source Software - è un programma Open Source - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 337 - - is not Open Source Software - non è un programma Open Source + + Do you really want to generate a new security token? + Vuoi davvero generare un nuovo token di sicurezza? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is Open Source Software - è un programma Open Source + + Generate + Generare - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is not Open Source Software - non è un programma Open Source + + Stocks + Azioni - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - can be self-hosted - può essere ospitato in proprio - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be self-hosted - non può essere ospitato in proprio + + Cryptocurrencies + criptovalute - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - can be self-hosted - può essere ospitato in proprio - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/pages/features/features-page.html + 51 - - cannot be self-hosted - non può essere ospitato in proprio + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - can be used anonymously - può essere usato anonimamente + + Manage Asset Profile + Gestisci profilo risorsa - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - cannot be used anonymously - non può essere usato anonimamente + + Alternative Investment + Investimenti alternativi - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 44 - - can be used anonymously - può essere usato anonimamente + + Collectible + Da collezione - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + libs/ui/src/lib/i18n.ts + 54 - - cannot be used anonymously - non può essere usato anonimamente + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - ha un piano gratuito + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - non ha un piano gratuito + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - ha un piano gratuito + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - non ha un piano gratuito + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Non ho trovato alcun asset. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Fornitori di dati + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NUOVO + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Imposta API Key + + No results found... + No results found... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Vuoi seguire le novità? Clicca sotto per essere notificato appena è disponibile. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Ottieni accesso a oltre 100’000+ titoli da oltre 50 borse + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ucraina + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Salta + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Iscriviti adesso + + Emerging Markets + Emerging Markets - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossario + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guide + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guide - snake-case + + Your net worth is managed by 0 accounts + Your net worth is managed by 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossario - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europe - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + North America - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Find Ghostfolio on GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Join the Ghostfolio Slack community - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Follow Ghostfolio on X (formerly Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Send an e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Follow Ghostfolio on LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Support Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index b13e4d66e..a0e2b5ac8 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -1,7 +1,7 @@ - + Create Account Account aanmaken @@ -16,16 +16,20 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. Het risico op verlies bij handelen kan aanzienlijk zijn. Het is niet aan te raden om geld te investeren dat je misschien op korte termijn nodig heeft. apps/client/src/app/app.component.html - 200 + 221 - + Grantee Ontvanger @@ -33,7 +37,7 @@ 11 - + Type Type @@ -53,7 +57,7 @@ 161 - + Details Details @@ -61,7 +65,7 @@ 33 - + Revoke Intrekken @@ -74,50 +78,10 @@ Wil je deze verleende toegang echt intrekken? apps/client/src/app/components/access-table/access-table.component.ts - 67 - - - - Activities - Activiteiten - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + 108 - + Name Naam @@ -126,23 +90,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -154,7 +122,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -173,7 +141,7 @@ 88 - + Total Totaal @@ -181,7 +149,7 @@ 55 - + Value Waarde @@ -198,31 +166,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -249,64 +201,56 @@ 102 - + Edit Bewerken apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Verwijderen apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -316,16 +260,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? Wil je deze rekening echt verwijderen? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + 148 - + Delete Jobs Taken verwijderen @@ -333,31 +281,7 @@ 151 - - Symbol - Symbool - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 - - - + Data Source Gegevensbron @@ -366,18 +290,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Pogingen @@ -385,7 +309,7 @@ 83 - + Created Aangemaakt @@ -393,7 +317,7 @@ 92 - + Finished Voltooid @@ -401,31 +325,39 @@ 101 - + Status Status apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Asset Profiles - Asset Profiel + Activa Profiel - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data - Historische marktgegevens + Historische marktgegevens apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Bekijk gegevens @@ -433,7 +365,7 @@ 166 - + View Stacktrace Bekijk Stacktrace @@ -441,7 +373,7 @@ 173 - + Delete Job Taak verwijderen @@ -449,7 +381,7 @@ 180 - + Details for Details voor @@ -457,12 +389,12 @@ 2 - + Date Datum apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -477,127 +409,43 @@ 6 - + Market Price Marktprijs apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Annuleren - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 - - - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 - - - - Save - Opslaan - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 - - - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 - - - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 - - - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - + First Activity Eerste activiteit apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + 148 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + 198 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + 214 libs/ui/src/lib/holdings-table/holdings-table.component.html 50 - + Activity Count Aantal activiteiten @@ -605,40 +453,24 @@ 19 - + Historical Data Historische gegevens apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + 166 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html 44 - - Please add a currency: - Voeg een valuta toe: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 - - Do you really want to delete this coupon? Wil je deze coupon echt verwijderen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 - - - - Do you really want to delete this currency? - Wil je deze valuta echt verwijderen? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + 194 @@ -646,7 +478,7 @@ Wil je echt de cache legen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + 231 @@ -654,10 +486,10 @@ Stel je systeemboodschap in: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + 251 - + User Count Aantal gebruikers @@ -665,7 +497,7 @@ 13 - + per User per gebruiker @@ -673,112 +505,84 @@ 28 - - Gather Recent Data - Verzamel recente gegevens - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 - - - - Gather All Data - Verzamel alle gegevens - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 - - - + Gather Profile Data Verzamel profielgegevens apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + 235 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Exchange Rates - Wisselkoersen - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + 44 - + Add Currency Valuta toevoegen apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + System Message Systeembericht apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Bericht instellen apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Read-only Mode Alleen lezen apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + Coupons Coupons apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Toevoegen apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Huishouding apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Cache legen apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -786,46 +590,38 @@ Wilt je deze gebruiker echt verwijderen? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Gebruiker apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + 31 apps/client/src/app/components/header/header.component.html - 229 - - - - Registration - Registratie - - apps/client/src/app/components/admin-users/admin-users.html - 97 + 231 - + Engagement per Day Betrokkenheid per dag apps/client/src/app/components/admin-users/admin-users.html - 157 + 158 - + Last Request - Laatste verzoek + Laatste verzoek apps/client/src/app/components/admin-users/admin-users.html - 202 + 204 - + Current Market Mood Huidig marktsentiment @@ -833,391 +629,199 @@ 12 - - Overview - Overzicht + + About Ghostfolio + Over Ghostfolio apps/client/src/app/components/header/header.component.html - 28 + 326 - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Portfolio - Portefeuille + + Get Started + Aan de slag - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 320 - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/public/public-page.html + 220 - - Accounts - Rekeningen + + Sign in + Aanmelden - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/header/header.component.html - 263 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + libs/common/src/lib/routes/routes.ts + 157 + + + Oops! Incorrect Security Token. + Oeps! Onjuiste beveiligingstoken. - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/components/header/header.component.ts + 274 - - - Admin Control - Beheer - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 - - Resources - Middelen + + Manage Activities + Activiteiten beheren - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Last Days + Laatste Dagen - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/markets/markets.html + 17 + + + Security Token + Beveiligingstoken - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - - - Pricing - Prijzen - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - About - Over + + or + of - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/pages/landing/landing-page.html + 48 - - - Me - Ik - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/landing/landing-page.html + 451 - - - My Ghostfolio - Mijn Ghostfolio - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - - - About Ghostfolio - Over Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Features - Functionaliteiten - - apps/client/src/app/app.component.html - 79 - + + Sign in with Internet Identity + Aanmelden met Internet Identity - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + Aanmelden met Google - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Markets - Markten + + Stay signed in + Aangemeld blijven - apps/client/src/app/app.component.html + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html 61 + + + Time in Market + Tijd in de markt - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + Absoluut bruto rendement - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Absolute Net Performance + Absoluut netto rendement - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 - - Get Started - Aan de slag - - apps/client/src/app/pages/features/features-page.html - 303 - - - apps/client/src/app/pages/public/public-page.html - 220 - - - - Sign in - Aanmelden - - apps/client/src/app/app-routing.module.ts - 150 - - - apps/client/src/app/components/header/header.component.ts - 230 - - - - Oops! Incorrect Security Token. - Oeps! Onjuiste beveiligingstoken. - - apps/client/src/app/components/header/header.component.ts - 245 - - - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 - - - - Manage Activities - Activiteiten beheren - - apps/client/src/app/components/home-holdings/home-holdings.html - 63 - - - - Last Days - Laatste Dagen - - apps/client/src/app/components/home-market/home-market.html - 7 - - - - Summary - Samenvatting - - apps/client/src/app/components/home-summary/home-summary.html - 2 - - - - Security Token - Beveiligingstoken - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - - - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 - - - - or - of - - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 - - - apps/client/src/app/pages/landing/landing-page.html - 47 - - - apps/client/src/app/pages/landing/landing-page.html - 450 - - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 - - - apps/client/src/app/pages/register/register-page.html - 30 - - - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 - - - - Sign in with Internet Identity - Aanmelden met Internet Identity - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 - - - - Sign in with Google - Aanmelden met Google - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 - - - - Stay signed in - Aangemeld blijven - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 - - - - Sign in - Aanmelden - - apps/client/src/app/components/header/header.component.html - 412 - - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 - - - - Time in Market - Tijd in de markt - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 - - - - Buy - Kopen - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 - - - - Sell - Verkopen - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 - - - - Investment - Belegging - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - - Absolute Gross Performance - Absoluut bruto rendement - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 - - - - Absolute Net Performance - Absoluut netto rendement - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 - - - + Net Performance Netto rendement @@ -1225,7 +829,7 @@ 117 - + Total Assets Totaal Activa @@ -1233,153 +837,105 @@ 143 - - Valuables - Kostbaarheden - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Noodfonds - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Koopkracht apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Net Worth Netto waarde apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Rendement per jaar apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividend - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 Please set the amount of your emergency fund. - Voer het bedrag van je noodfonds in: + Voer het bedrag van je noodfonds in: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + 71 - + Sectors Sectoren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Landen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Tags Tags apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + Report Data Glitch Gegevensstoring melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 - + Allocation Allocatie + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -1393,21 +949,9 @@ 116 - - Performance - Prestaties - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 - - - - Show all - Toon alle + + Show all + Toon alle libs/ui/src/lib/holdings-table/holdings-table.component.html 197 @@ -1417,60 +961,44 @@ Today Vandaag - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/public/public-page.html + 24 libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1J - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5J - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1478,191 +1006,75 @@ Oké apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About Over - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Privacy Policy - Privacybeleid - - apps/client/src/app/app.component.html - 103 - - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 - - - - Blog - Blog apps/client/src/app/app.component.html - 73 - - - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 - - - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 - - - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 - - - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 - - - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 - - - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 - - - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 - - - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 - - - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 - - - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 - - - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 - - - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 - - - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 - - - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 70 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/header/header.component.html + 375 - - - Changelog - Changelog - apps/client/src/app/app.component.html - 77 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/common/src/lib/routes/routes.ts + 220 - - License - Licentie + + Privacy Policy + Privacybeleid apps/client/src/app/app.component.html - 88 + 105 - apps/client/src/app/pages/about/license/license-page.html + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 - - - Privacy Policy - Privacybeleid - - apps/client/src/app/pages/about/about-page.component.ts - 62 - - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 209 My Ghostfolio Mijn Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 - - Please enter your coupon code: + + Please enter your coupon code. Voer je couponcode in: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1670,7 +1082,7 @@ Kon je kortingscode niet inwisselen apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1678,7 +1090,7 @@ Je couponcode is ingewisseld apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1686,7 +1098,7 @@ Herladen apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1694,114 +1106,94 @@ Wil je deze aanmeldingsmethode echt verwijderen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Rekening - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Lidmaatschap - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year per jaar apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Probeer Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Coupon inwisselen apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Presentatie weergave apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Basisvaluta apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Locale Locatie + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Datum- en getalnotatie apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Zen Mode Zen-modus apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Sign in with fingerprint - Aanmelden met vingerafdruk + Aanmelden met vingerafdruk apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + User ID Gebruikers-ID @@ -1810,18 +1202,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Verleende toegang apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Toegang verlenen @@ -1829,7 +1221,7 @@ 7 - + Public Openbaar @@ -1841,35 +1233,51 @@ Accounts Rekeningen - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - Update account - Rekening bijwerken - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/components/admin-users/admin-users.html + 115 - - - Add account - Rekening toevoegen - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/components/header/header.component.html + 58 - - - Cash - Contant geld - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 - + + Update account + Rekening bijwerken + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 + + + + Add account + Rekening toevoegen + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 + + + Currency Valuta @@ -1878,11 +1286,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1894,14 +1302,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Saldo @@ -1917,7 +1325,7 @@ 34 - + Platform Platform @@ -1933,7 +1341,7 @@ 48 - + Account ID Rekening-ID @@ -1945,16 +1353,116 @@ Admin Control Beheer - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 + + + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 Blog Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 + + + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 + + + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 + + + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 + + + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 + + + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 + + + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 + + + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 + + + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 + + + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 + + + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 + + + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 + + + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 + + + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 + + + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 + + + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 + + + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 + + + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 @@ -1969,91 +1477,135 @@ Frequently Asked Questions (FAQ) Veelgestelde vragen - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Functionaliteiten - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Overview Overzicht - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 Markets Markten - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 - - - Allocations - Allocaties - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 - + Allocations - Verdelingen + Allocaties apps/client/src/app/pages/portfolio/allocations/allocations-page.html 4 + + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 133 + - + By Account Per rekening @@ -2061,7 +1613,7 @@ 286 - + By Currency Per valuta @@ -2069,7 +1621,7 @@ 63 - + By Asset Class Per asset klasse @@ -2077,7 +1629,7 @@ 85 - + By Holding Per positie @@ -2085,7 +1637,7 @@ 107 - + By Sector Per sector @@ -2093,7 +1645,7 @@ 130 - + By Continent Per continent @@ -2101,7 +1653,7 @@ 153 - + By Country Per land @@ -2109,7 +1661,7 @@ 264 - + Regions Regio’s @@ -2122,50 +1674,42 @@ - Analysis - Analyse - - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 - - - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 - - - Analysis Analyse apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 + + libs/common/src/lib/routes/routes.ts + 138 + - + Investment Timeline Tijdlijn investeringen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + Top Winnaars apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom Verliezers apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + FIRE FIRE @@ -2173,7 +1717,7 @@ 4 - + Calculator Rekenmachine @@ -2181,7 +1725,7 @@ 7 - + 4% Rule 4% regel @@ -2190,26 +1734,6 @@ - Holdings - Posities - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - Holdings Posities @@ -2225,11 +1749,23 @@ 70 - libs/ui/src/lib/assistant/assistant.html - 46 + libs/common/src/lib/routes/routes.ts + 90 + + + libs/common/src/lib/routes/routes.ts + 167 + + + + Holdings + Posities + + libs/ui/src/lib/assistant/assistant.html + 82 - + Update activity Activiteit bijwerken @@ -2237,12 +1773,12 @@ 10 - + Add activity Activiteit toevoegen apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2252,77 +1788,69 @@ Sell Verkopen + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Naam, symbool of ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 124 - + Quantity Hoeveelheid apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Unit Price Prijs per eenheid apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 214 libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Fee - Transactiekosten - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 234 - - - + Note Opmerking apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2330,47 +1858,51 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 275 - - Asset Class - Asset klasse + + Activities + Activiteiten - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + 207 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/admin-users/admin-users.html + 136 - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Activities - Activiteiten - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 @@ -2378,7 +1910,7 @@ Gegevens importeren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2386,42 +1918,66 @@ Importeren is voltooid apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 Pricing Prijzen + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 + Portfolio Portefeuille apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + 124 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + 92 - - - Currencies - Valuta - apps/client/src/app/pages/public/public-page.html - 88 + libs/common/src/lib/routes/routes.ts + 151 - + Continents Continenten @@ -2429,23 +1985,27 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. Ghostfolio stelt je in staat om je vermogen bij te houden. apps/client/src/app/pages/public/public-page.html - 215 + 216 Registration Registratie - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Continue with Internet Identity Ga verder met Internet Identity @@ -2453,7 +2013,7 @@ 42 - + Continue with Google Verder met Google @@ -2461,39 +2021,39 @@ 53 - + Copy to clipboard Kopieer naar klembord apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Ik ga ermee akkoord dat ik mijn Security Token van hierboven op een veilige plaats heb opgeslagen. Als ik het verlies, kan ik mijn account niet terug krijgen. + + Resources + Bronnen - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Akkoord en doorgaan - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Bronnen - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Oeps, authenticatie is mislukt. @@ -2501,7 +2061,7 @@ 19 - + Try again Probeer opnieuw @@ -2509,15 +2069,15 @@ 27 - + Go back to Home Page Ga terug naar de startpagina apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 - + Draft Concept @@ -2530,10 +2090,18 @@ Activiteiten importeren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Activiteiten exporteren @@ -2545,7 +2113,7 @@ 396 - + Export Drafts as ICS Concept exporteren als ICS @@ -2557,7 +2125,7 @@ 409 - + Clone Kloon @@ -2565,7 +2133,7 @@ 436 - + Export Draft as ICS Concept exporteren als ICS @@ -2578,34 +2146,26 @@ Wil je deze activiteit echt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Index - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High - Verandering van All Time High + Verandering van Recordhoogte libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH van ATH libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Jaarlijkse rente @@ -2613,7 +2173,7 @@ 21 - + Time to add your first activity. Tijd om je eerste activiteit toe te voegen. @@ -2621,20 +2181,20 @@ 12 - + Language Taal apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + 56 - + Get started Aan de slag apps/client/src/app/components/header/header.component.html - 422 + 432 @@ -2642,7 +2202,7 @@ Deze functie is momenteel niet beschikbaar. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -2650,11 +2210,11 @@ Oeps! Er ging iets mis. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 184 @@ -2662,26 +2222,18 @@ Probeer het later nog eens. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 - - - - Change - Verandering - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 186 - + Developed Markets Ontwikkelde markten @@ -2693,47 +2245,15 @@ 160 - - Asset Sub Class - Asset subklasse - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 - - - - Average Unit Price - Gemiddelde prijs per eenheid - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 - - - + Maximum Price Maximale prijs apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 143 - + Other Markets Andere markten @@ -2745,7 +2265,7 @@ 178 - + Emerging Markets Opkomende markten @@ -2757,48 +2277,48 @@ 169 - + Sector Sector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + 242 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + 263 - + Country Land apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Minimum Price Minimale prijs apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Projected Total Amount Verwacht totaalbedrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2806,18 +2326,22 @@ Besparingen libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 Interest Rente - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 - libs/ui/src/lib/i18n.ts + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 + + + libs/ui/src/lib/i18n.ts 38 @@ -2826,7 +2350,7 @@ Storting libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 @@ -2834,23 +2358,23 @@ Maandelijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + 88 - + Sectors Count Aantal sectoren apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + 175 - + Countries Count Aantal landen apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + 184 @@ -2858,11 +2382,15 @@ Angst apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -2870,11 +2398,15 @@ Hebzucht apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 @@ -2882,18 +2414,18 @@ Filter op... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + 379 - - Hello, has shared a Portfolio with you! - Hallo, heeft een portefeuille met je gedeeld! + + Hello, has shared a Portfolio with you! + Hallo, heeft een portefeuille met je gedeeld! apps/client/src/app/pages/public/public-page.html - 4 + 5 - + Alias Alias @@ -2905,23 +2437,27 @@ 11 - + Experimental Features Experimentele functies apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 Benchmark Benchmark + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + 136 - + Compare with... Vergelijk met... @@ -2929,7 +2465,7 @@ 18 - + Proportion of Net Worth Verhouding van netto waarde @@ -2937,12 +2473,12 @@ 12 - + Excluded from Analysis Uitgesloten van analyse apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 @@ -2950,39 +2486,35 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 - - - Appearance - Weergave apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + 172 - - Auto - Automatisch + + Appearance + Weergave apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Licht apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Donker apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 @@ -2990,15 +2522,15 @@ Totaalbedrag apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 - + Portfolio Evolution Waardeontwikkeling van portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 @@ -3006,12 +2538,24 @@ Spaarrente apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 Account Account + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3020,6 +2564,30 @@ Asset Class Asset klasse + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3028,6 +2596,26 @@ Symbol Symbool + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3036,6 +2624,10 @@ Tag Label + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3044,9 +2636,13 @@ Cash Contant geld + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3060,6 +2656,10 @@ Equity Equity + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + libs/ui/src/lib/i18n.ts 46 @@ -3094,7 +2694,7 @@ Cryptovaluta libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3102,7 +2702,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3110,7 +2710,7 @@ Beleggingsfonds libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3118,7 +2718,7 @@ Edelmetaal libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3126,7 +2726,7 @@ Private equity libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3134,12 +2734,24 @@ Aandeel libs/ui/src/lib/i18n.ts - 58 + 60 Emergency Fund Noodfonds + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3154,19 +2766,35 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 No data available Geen gegevens beschikbaar + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 @@ -3174,7 +2802,7 @@ Noord-Amerika libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3182,7 +2810,7 @@ Afrika libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3190,7 +2818,7 @@ Azië libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3198,7 +2826,7 @@ Europa libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3206,7 +2834,7 @@ Oceanië libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3214,10 +2842,10 @@ Zuid-Amerika libs/ui/src/lib/i18n.ts - 70 + 72 - + The following file formats are supported: De volgende bestandsformaten worden ondersteund: @@ -3225,7 +2853,7 @@ 90 - + Back Terug @@ -3237,112 +2865,100 @@ 178 - - Community - Gemeenschap - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 - - - + Activities Count Aantal activiteiten apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + 157 - + Refresh Vernieuwen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + 17 - + Symbol Mapping Symbool toewijzen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 Dividend Dividend + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts 36 - + Dividend Timeline Tijdlijn dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 Asset Sub Class Asset subklasse - libs/ui/src/lib/i18n.ts + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + + + libs/ui/src/lib/i18n.ts 7 - + User Signup Account aanmaken apps/client/src/app/components/admin-overview/admin-overview.html - 111 + 34 @@ -3350,10 +2966,10 @@ Gegevens valideren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + Import Importeren @@ -3366,46 +2982,42 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Market Data Marktgegevens - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Users Gebruikers - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 61 Summary Samenvatting - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 - + Holding Positie @@ -3414,10 +3026,10 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Laad dividenden @@ -3430,7 +3042,7 @@ Jaarlijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3438,15 +3050,23 @@ Importeer dividenden apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Geldig tot apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3501,39 +3121,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values - Bescherming voor gevoelige informatie zoals absoluut rendement en hoeveelheden + Bescherming voor gevoelige informatie zoals absoluut rendement en hoeveelheden apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times - Afleidingsvrije ervaring voor roerige tijden + Afleidingsvrije ervaring voor roerige tijden apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality - Voorproefje van nieuwe functionaliteit + Voorproefje van nieuwe functionaliteit apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? Ben jij een ambitieuze investeerder die het volledige plaatje wilt zien? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Portfolio Samenvatting @@ -3542,14 +3162,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Prestatie Benchmarks @@ -3558,14 +3178,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator FIRE Calculator @@ -3574,14 +3194,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... en meer functies ... @@ -3590,175 +3210,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Overslaan apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Abonnement uitbreiden apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Voor technisch onderlegde beleggers die Ghostfolio liever op hun eigen systemen draaien. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Onbeperkte transacties apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Onbeperkte rekeningen apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Portefeuilleprestaties apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Zelf hosten, handmatig bijwerken. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Gratis apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Voor nieuwe beleggers die net beginnen met handelen. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Volledig beheerd Ghostfolio cloud-aanbod. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Voor ambitieuze beleggers die een volledig beeld willen hebben van hun financiële assets. apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Eenmalige betaling, geen automatische verlenging. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Aan de slag apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - + It’s free. Het is gratis. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 353 - + Fees Kosten apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3766,10 +3402,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Portefeuille-allocatie @@ -3782,14 +3418,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Spaargeld per maand @@ -3797,20 +3433,20 @@ 10 - + Data Import and Export Data Import and Export apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3821,20 +3457,20 @@ 13 - + Community Support Steun van de Gemeenschap apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support Ondersteuning via e-mail en chat apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3853,7 +3489,7 @@ 14 - + Market data provided by Marktgegevens geleverd door @@ -3861,15 +3497,7 @@ 2 - - Oops! Could not get the historical exchange rate from - Oeps! Kon de historische wisselkoers niet krijgen van - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - + Retirement Date Pensioen Datum @@ -3877,15 +3505,7 @@ 32 - - Gather Historical Data - Historische gegevens verzamelen - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 - - - + Professional Data Provider Professionele gegevensleverancier @@ -3894,10 +3514,10 @@ apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans Prijzen @@ -3905,7 +3525,7 @@ 4 - + Renew Plan Abonnement Vernieuwen @@ -3914,46 +3534,46 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Ons officiële Ghostfolio Premium cloud-aanbod is de eenvoudigste manier om te beginnen. Vanwege de tijd die het bespaart, zal dit voor de meeste mensen de beste optie zijn. De inkomsten worden gebruikt om de hostinginfrastructuur te dekken en de voortdurende ontwikkeling van Ghostfolio te financieren. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Ons officiële Ghostfolio Premium-cloudaanbod is de gemakkelijkste manier om aan de slag te gaan. Vanwege de tijdsbesparing zal dit voor de meeste mensen de beste optie zijn. De opbrengsten worden gebruikt om de operationele kosten voor de hostinginfrastructuur en professionele dataproviders te dekken, en om de lopende ontwikkeling te financieren. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User - Gebruiker nadoen + Gebruiker immiteren apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User Gebruiker verwijderen apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 Do you really want to delete these activities? - Wil je echt al je activiteiten verwijderen? + Weet je zeker dat je alle activiteiten wilt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider Per ETF-aanbieder @@ -3961,7 +3581,7 @@ 306 - + Update platform Platform bijwerken @@ -3969,7 +3589,7 @@ 8 - + Add platform Platform toevoegen @@ -3977,16 +3597,20 @@ 10 - + Url Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3998,18 +3622,18 @@ Wil je dit platform echt verwijderen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms Platforms apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance Saldo bijwerken @@ -4017,7 +3641,7 @@ 112 - + By Platform Per platform @@ -4025,56 +3649,44 @@ 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: Upgrade vandaag nog naar Ghostfolio Premium en krijg toegang tot exclusieve functies om je beleggingservaring te verbeteren: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. Krijg de tools om je financiën effectief te beheren en je persoonlijke beleggingsstrategie te verfijnen. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform - Platform toevoegen + Platform Toevoegen apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings Instellingen - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Equity - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 @@ -4085,7 +3697,7 @@ 19 - + Manage Benchmarks Beheer Benchmarks @@ -4093,7 +3705,7 @@ 35 - + Select Holding Selecteer positie @@ -4101,7 +3713,7 @@ 20 - + Select File Selecteer bestand @@ -4109,7 +3721,7 @@ 22 - + Select Dividends Selecteer dividenden @@ -4117,7 +3729,7 @@ 113 - + Select Activities Selecteer activiteiten @@ -4125,64 +3737,36 @@ 115 - - Import Activities - Importeer activiteiten - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Importeer dividenden - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Persoonlijke financiën + + Frequently Asked Questions (FAQ) + Veelgestelde Vragen - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Veelgestelde Vragen - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak Huidige reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak Langste reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 @@ -4217,12 +3801,12 @@ 30 - + Liabilities Verplichtingen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4233,35 +3817,35 @@ Changelog Changelog - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License Licentie - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Aandelen - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs ETF’s @@ -4269,7 +3853,7 @@ 25 - + Bonds Obligaties @@ -4277,15 +3861,7 @@ 38 - - Cryptocurrencies - Cryptovaluta - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items Kostbaarheden @@ -4293,15 +3869,15 @@ 76 - + Import and Export Importeer en exporteer apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts Meerdere accounts @@ -4309,7 +3885,7 @@ 127 - + Portfolio Calculations Portefeuilleberekeningen @@ -4317,44 +3893,44 @@ 141 - + Dark Mode - Dark Mode + Donker Thema apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood Marktsentiment apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis Statische Analyse apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language Meerdere talen apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software Open Source Software apps/client/src/app/pages/features/features-page.html - 278 + 295 @@ -4365,15 +3941,15 @@ 40 - + Scraper Configuration Scraper instellingen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile Asset profiel toevoegen @@ -4385,19 +3961,23 @@ Personal Finance Tools Tools voor persoonlijke financiën - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Ontdek Open Source alternatieven voor tools voor persoonlijke financiën apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Opgericht @@ -4405,7 +3985,7 @@ 77 - + Origin Oorsprong @@ -4413,7 +3993,7 @@ 82 - + Region Regio @@ -4421,15 +4001,15 @@ 87 - + Available in Beschikbaar in apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Wel @@ -4465,7 +4045,7 @@ 274 - + ❌ No ❌ Geen @@ -4501,31 +4081,31 @@ 281 - + Self-Hosting Zelf hosten apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Gebruik anoniem apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Gratis abonnement apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Notities @@ -4533,39 +4113,15 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Volg, analyseer en visualiseer moeiteloos je vermogen met Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Tools voor persoonlijke financiën - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Gidsen - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 - - - - Glossary - Woordenlijst - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + 329 - + Stocks, ETFs, bonds, cryptocurrencies, commodities Aandelen, ETF’s, obligaties, cryptocurrencies, grondstoffen @@ -4577,7 +4133,7 @@ 65 - + Mortgages, personal loans, credit cards Hypotheken, persoonlijke leningen, creditcards @@ -4585,7 +4141,7 @@ 57 - + Luxury items, real estate, private companies Luxe artikelen, onroerend goed, particuliere bedrijven @@ -4596,6 +4152,10 @@ Buy Koop + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4614,7 +4174,7 @@ ETF’s zonder Landen apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 @@ -4622,15 +4182,15 @@ ETF’s zonder Sectoren apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 @@ -4641,7 +4201,7 @@ 25 - + By Market Per markt @@ -4662,118 +4222,98 @@ Japan libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio Welkom bij Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts Je accounts instellen apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. Krijg een uitgebreid financieel overzicht door je bank- en effectenrekeningen toe te voegen. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities Leg je activiteiten vast apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. Leg je investeringsactiviteiten vast om je portefeuille up-to-date te houden. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio Volg en analyseer je portfolio apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. Volg je voortgang in real-time met uitgebreide analyses en inzichten. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - Geen data beschikbaar - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? Klaar om je persoonlijke financiën onder controle te krijgen? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts Account opzetten apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication Biometrische authenticatie apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. Bij Ghostfolio is transparantie één van onze kernwaarden. We publiceren de broncode als open source software (OSS) onder de AGPL-3.0 licentie en we delen openlijk geaggregeerde kerncijfers van de operationele status van het platform. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users Actieve gebruikers @@ -4785,7 +4325,7 @@ 62 - + New Users Nieuwe gebruikers @@ -4793,7 +4333,7 @@ 51 - + Users in Slack community Gebruikers in de Slack gemeenschap @@ -4801,7 +4341,7 @@ 75 - + Contributors on GitHub Contributors op GitHub @@ -4809,7 +4349,7 @@ 89 - + Stars on GitHub Sterren op GitHub @@ -4821,7 +4361,7 @@ 103 - + Pulls on Docker Hub Pulls op Docker Hub @@ -4833,7 +4373,7 @@ 117 - + Uptime Bedrijfstijd @@ -4841,12 +4381,12 @@ 132 - + Export Data Exporteer Data apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 @@ -4854,2782 +4394,3741 @@ Valuta apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 + + + + Our + Onze + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 + + + + Visit + Bezoek + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 + + + + Discover other exciting Open Source Software projects + Ontdek andere interessante Open Source Softwareprojecten + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 + + + + Check out the numerous features of Ghostfolio to manage your wealth + Bekijk de vele functies van Ghostfolio om je vermogen te beheren + + apps/client/src/app/pages/features/features-page.html + 7 + + + + Discover the latest Ghostfolio updates and insights on personal finance + Ontdek de nieuwste Ghostfolio-updates en inzichten in persoonlijke financiën + + apps/client/src/app/pages/blog/blog-page.html + 7 + + + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Als je Ghostfolio liever op je eigen systeem uitvoert, vind je de broncode en verdere instructies op GitHub. + + apps/client/src/app/pages/pricing/pricing-page.html + 14 + + + + Manage your wealth like a boss + Beheer je vermogen als een baas + + apps/client/src/app/pages/landing/landing-page.html + 6 + + + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio is een privacygericht, open source dashboard voor je persoonlijke financiën. Analyseer je asset-allocatie, ken je nettowaarde en neem gefundeerde, datagedreven investeringsbeslissingen. + + apps/client/src/app/pages/landing/landing-page.html + 10 + + + + Monthly Active Users + Maandelijkse actieve gebruikers + + apps/client/src/app/pages/landing/landing-page.html + 70 + + + + As seen in + Zoals te zien in + + apps/client/src/app/pages/landing/landing-page.html + 115 + + + + Protect your assets. Refine your personal investment strategy. + Bescherm je financiële bezittingen. Verfijn je persoonlijke investeringsstrategie. + + apps/client/src/app/pages/landing/landing-page.html + 226 + + + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio stelt drukbezette mensen in staat om aandelen, ETF’s of cryptocurrencies bij te houden zonder gevolgd te worden. + + apps/client/src/app/pages/landing/landing-page.html + 230 + + + + 360° View + 360°-overzicht + + apps/client/src/app/pages/landing/landing-page.html + 240 + + + + Web3 Ready + Klaar voor Web3 + + apps/client/src/app/pages/landing/landing-page.html + 251 + + + + Use Ghostfolio anonymously and own your financial data. + Gebruik Ghostfolio anoniem en bezit je financiële gegevens. + + apps/client/src/app/pages/landing/landing-page.html + 254 + + + + Benefit from continuous improvements through a strong community. + Profiteer van voortdurende verbeteringen door een sterke gemeenschap. + + apps/client/src/app/pages/landing/landing-page.html + 264 + + + + Why Ghostfolio? + Waarom Ghostfolio? + + apps/client/src/app/pages/landing/landing-page.html + 272 + + + + Ghostfolio is for you if you are... + Ghostfolio is iets voor je als je... + + apps/client/src/app/pages/landing/landing-page.html + 274 + + + + trading stocks, ETFs or cryptocurrencies on multiple platforms + handelt in aandelen, ETF’s of cryptocurrencies op meerdere platforms + + apps/client/src/app/pages/landing/landing-page.html + 280 + + + + pursuing a buy & hold strategy + streeft naar een buy & hold strategie + + apps/client/src/app/pages/landing/landing-page.html + 286 + + + + interested in getting insights of your portfolio composition + geïnteresseerd bent in het krijgen van inzicht in je portefeuillesamenstelling + + apps/client/src/app/pages/landing/landing-page.html + 291 + + + + valuing privacy and data ownership + privacy en eigendom van gegevens waardeert + + apps/client/src/app/pages/landing/landing-page.html + 296 + + + + into minimalism + houdt van een minimalistisch ontwerp + + apps/client/src/app/pages/landing/landing-page.html + 299 + + + + caring about diversifying your financial resources + zorgdraagt voor het diversifiëren van je financiële middelen + + apps/client/src/app/pages/landing/landing-page.html + 303 + + + + interested in financial independence + geïnteresseerd bent in financiële onafhankelijkheid + + apps/client/src/app/pages/landing/landing-page.html + 307 + + + + saying no to spreadsheets in + "nee" zegt tegen spreadsheets in + + apps/client/src/app/pages/landing/landing-page.html + 311 + + + + still reading this list + nog steeds deze lijst aan het lezen bent + + apps/client/src/app/pages/landing/landing-page.html + 314 + + + + Learn more about Ghostfolio + Leer meer over Ghostfolio + + apps/client/src/app/pages/landing/landing-page.html + 319 + + + + What our users are saying + Wat onze gebruikers zeggen + + apps/client/src/app/pages/landing/landing-page.html + 328 + + + + Members from around the globe are using Ghostfolio Premium + Leden van over de hele wereld gebruikenGhostfolio Premium + + apps/client/src/app/pages/landing/landing-page.html + 367 + + + + How does Ghostfolio work? + Hoe Ghostfolio werkt? + + apps/client/src/app/pages/landing/landing-page.html + 384 + + + + Sign up anonymously* + Anoniem aanmelden* + + apps/client/src/app/pages/landing/landing-page.html + 392 + + + + * no e-mail address nor credit card required + * geen e-mailadres of creditcard nodig + + apps/client/src/app/pages/landing/landing-page.html + 394 + + + + Add any of your historical transactions + Voeg al je historische transacties toe + + apps/client/src/app/pages/landing/landing-page.html + 406 + + + + Get valuable insights of your portfolio composition + Krijg waardevolle inzichten in de samenstelling van je portefeuille + + apps/client/src/app/pages/landing/landing-page.html + 418 + + + + Are you ready? + Ben jij er klaar voor? + + apps/client/src/app/pages/landing/landing-page.html + 432 + + + + Get the full picture of your personal finances across multiple platforms. + Krijg een volledig beeld van je persoonlijke financiën op meerdere platforms. + + apps/client/src/app/pages/landing/landing-page.html + 243 + + + + Get started in only 3 steps + Aan de slag in slechts 3 stappen + + apps/client/src/app/pages/landing/landing-page.html + 386 + + + + faq + veelgestelde-vragen + kebab-case + + libs/common/src/lib/routes/routes.ts + 234 + + + libs/common/src/lib/routes/routes.ts + 235 + + + libs/common/src/lib/routes/routes.ts + 239 + + + libs/common/src/lib/routes/routes.ts + 245 + + + + features + functionaliteiten + kebab-case + + libs/common/src/lib/routes/routes.ts + 254 + + + libs/common/src/lib/routes/routes.ts + 255 + + + + about + over + kebab-case + + libs/common/src/lib/routes/routes.ts + 176 + + + libs/common/src/lib/routes/routes.ts + 177 + + + libs/common/src/lib/routes/routes.ts + 182 + + + libs/common/src/lib/routes/routes.ts + 190 + + + libs/common/src/lib/routes/routes.ts + 198 + + + libs/common/src/lib/routes/routes.ts + 206 + + + libs/common/src/lib/routes/routes.ts + 214 + + + + privacy-policy + privacybeleid + kebab-case + + libs/common/src/lib/routes/routes.ts + 204 + + + libs/common/src/lib/routes/routes.ts + 207 + + + + license + licentie + kebab-case + + libs/common/src/lib/routes/routes.ts + 188 + + + libs/common/src/lib/routes/routes.ts + 191 + + + + markets + markten + kebab-case + + libs/common/src/lib/routes/routes.ts + 259 + + + libs/common/src/lib/routes/routes.ts + 260 + + + + pricing + prijzen + kebab-case + + libs/common/src/lib/routes/routes.ts + 269 + + + libs/common/src/lib/routes/routes.ts + 270 + + + + register + registratie + kebab-case + + libs/common/src/lib/routes/routes.ts + 279 + + + libs/common/src/lib/routes/routes.ts + 280 + + + + resources + bronnen + kebab-case + + libs/common/src/lib/routes/routes.ts + 284 + + + libs/common/src/lib/routes/routes.ts + 285 + + + libs/common/src/lib/routes/routes.ts + 290 + + + libs/common/src/lib/routes/routes.ts + 298 + + + libs/common/src/lib/routes/routes.ts + 306 + + + libs/common/src/lib/routes/routes.ts + 314 + + + libs/common/src/lib/routes/routes.ts + 322 + + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Deze overzichtspagina bevat een verzameling tools voor persoonlijke financiën vergeleken met het open source alternatief Ghostfolio. Als je waarde hecht aan transparantie, gegevensprivacy en samenwerking binnen een gemeenschap, biedt Ghostfolio een uitstekende mogelijkheid om je financieel beheer in eigen hand te nemen. + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Bekijk de links hieronder om verschillende persoonlijke financiële tools met Ghostfolio te vergelijken. + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + + Open Source Alternative to + Open Source alternatief voor + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + + The Open Source Alternative to + Open Source alternatief voor + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Ben je op zoek naar een open source alternatief voor ? Ghostfolio is een krachtige tool voor portefeuillebeheer die particulieren een uitgebreid platform biedt om hun beleggingen bij te houden, te analyseren en te optimaliseren. Of je nu een ervaren belegger bent of net begint, Ghostfolio biedt een intuïtieve gebruikersinterface en uitgebreide functionaliteiten om je te helpen weloverwogen beslissingen te nemen en je financiële toekomst in eigen handen te nemen. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio is open source software (OSS) en biedt een kosteneffectief alternatief voor waardoor het bijzonder geschikt is voor mensen met een krap budget, zoals degenen Financiële onafhankelijkheid nastreven, vroeg met pensioen gaan (FIRE). Door gebruik te maken van de collectieve inspanningen van een gemeenschap van ontwikkelaars en liefhebbers van persoonlijke financiën, verbetert Ghostfolio voortdurend de mogelijkheden, veiligheid en gebruikerservaring. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Laten we eens dieper duiken in de gedetailleerde vergelijkingstabel hieronder om een beter begrip te krijgen hoe Ghostfolio zichzelf positioneert ten opzichte van . We gaan in op verschillende aspecten zoals functies, gegevensprivacy, prijzen en meer, zodat je een weloverwogen keuze kunt maken voor jouw persoonlijke behoeften. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + + open-source-alternative-to + open-source-alternatief-voor + kebab-case + + libs/common/src/lib/routes/routes.ts + 320 + + + libs/common/src/lib/routes/routes.ts + 324 + + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Houd er rekening mee dat de verstrekte informatie in deze Ghostfolio vs is gebaseerd op ons onafhankelijk onderzoek en analyse. Deze website is niet gelieerd aan of een ander product dat in de vergelijking wordt genoemd. Aangezien het landschap van tools voor persoonlijke financiën evolueert, is het essentieel om specifieke details of wijzigingen rechtstreeks op de betreffende productpagina te controleren. Hebben je gegevens een opfrisbeurt nodig? Help ons de gegevens nauwkeurig te houden op GitHub. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 + + + + Ready to take your investments to the next level? + Klaar om je investeringen naar een hoger niveau te brengen? + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + + Switzerland + Zwitserland + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 + + + libs/ui/src/lib/i18n.ts + 96 + + + + Global + Wereldwijd + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 + + + libs/ui/src/lib/i18n.ts + 16 + + + + (Last 24 hours) + (Laatste 24 uur) + + apps/client/src/app/pages/open/open-page.html + 37 + + + + (Last 30 days) + (Laatste 30 dagen) + + apps/client/src/app/pages/open/open-page.html + 48 + + + apps/client/src/app/pages/open/open-page.html + 59 + + + + (Last 90 days) + (Laatste 90 dagen) + + apps/client/src/app/pages/open/open-page.html + 127 + + + + Choose or drop a file here + Kies of sleep bestand hier + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + + You are using the Live Demo. + U maakt gebruik van een Live Demo. + + apps/client/src/app/app.component.html + 12 + + + + One-time fee, annual account fees + Eenmalige kosten, jaarlijkse account kosten + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 + + + + Distribution of corporate earnings + Distribute van bedrijfsopbrengsten + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + + Fee + Kosten + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 234 + + + libs/ui/src/lib/i18n.ts + 37 + + + + Revenue for lending out money + Opbrengsten voor het uitlenen van geld + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + + Add Tag + Label Toevoegen + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + + Do you really want to delete this tag? + Weet u zetker dat u dit label wilt verwijderen? + + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + + Update tag + Label bijwerken + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + + Add tag + Voeg label toe + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + + Currency Cluster Risks + Valuta Cluster Risico’s + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + + Account Cluster Risks + Account Cluster Risco’s + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + + Transfer Cash Balance + Contant saldo overboeken + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + + Version + Versie + + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + + From + Van + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - Our - Onze + + To + Naar - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 - - Visit - Bezoek + + Transfer + Overdracht - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Discover other exciting Open Source Software projects - Ontdek andere interessante Open Source Softwareprojecten + + Membership + Lidmaatschap - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + libs/common/src/lib/routes/routes.ts + 31 - - - Frequently Asked Questions (FAQ) - Veelgestelde vragen - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Toegang - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Bezittingen Profiel - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 - - Check out the numerous features of Ghostfolio to manage your wealth - Bekijk de vele functies van Ghostfolio om je vermogen te beheren + + Do you really want to delete this asset profile? + Weet u zeker dat u dit bezittingen profiel wilt verwijderen? - apps/client/src/app/pages/features/features-page.html - 6 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 - - Discover the latest Ghostfolio updates and insights on personal finance - Ontdek de nieuwste Ghostfolio-updates en inzichten in persoonlijke financiën + + Search + Zoeken - apps/client/src/app/pages/blog/blog-page.html - 7 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - Als je Ghostfolio liever op je eigen systeem uitvoert, vind je de broncode en verdere instructies op GitHub. + + Add Manually + Voeg Handmatig Toe - apps/client/src/app/pages/pricing/pricing-page.html - 26 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 - - Manage your wealth like a boss - Beheer je vermogen als een baas + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio is een persoonlijk financieel dashboard om uw activa zoals aandelen, ETF’s of cryptocurrencies van verschillende platformen bij te houden. - apps/client/src/app/pages/landing/landing-page.html + apps/client/src/app/pages/i18n/i18n-page.html 5 - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio is een privacygericht, open source dashboard voor je persoonlijke financiën. Analyseer je asset-allocatie, ken je nettowaarde en neem gefundeerde, datagedreven investeringsbeslissingen. + + Last All Time High + Laatste Recordhoogte - apps/client/src/app/pages/landing/landing-page.html - 9 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - Get Started - Aan de slag + + User + Gebruiker - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs vergelijkingstabel - apps/client/src/app/pages/pricing/pricing-page.html - 324 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 - - Monthly Active Users - Maandelijkse actieve gebruikers + + Open Source Wealth Management Software + Open Source Vermogensbeheer Software - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 224 - - As seen in - Zoals te zien in + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + app, asset, cryptocurrency, dashboard, etf, financiën, management, performance, portfolio, software, aandeel, handel, vermogen, web3 - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/pages/i18n/i18n-page.html + 10 - - Protect your assets. Refine your personal investment strategy. - Bescherm je financiële bezittingen. Verfijn je persoonlijke investeringsstrategie. + + Oops, cash balance transfer has failed. + Oeps, geldoverdracht is mislukt. - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio stelt drukbezette mensen in staat om aandelen, ETF’s of cryptocurrencies bij te houden zonder gevolgd te worden. + + Extreme Fear + Extreme Angst - apps/client/src/app/pages/landing/landing-page.html - 229 + libs/ui/src/lib/i18n.ts + 103 - - 360° View - 360°-overzicht + + Extreme Greed + Extreme Hebzucht - apps/client/src/app/pages/landing/landing-page.html - 240 + libs/ui/src/lib/i18n.ts + 104 - - Web3 Ready - Klaar voor Web3 + + Neutral + Neutraal - apps/client/src/app/pages/landing/landing-page.html - 251 + libs/ui/src/lib/i18n.ts + 107 - - Use Ghostfolio anonymously and own your financial data. - Gebruik Ghostfolio anoniem en bezit je financiële gegevens. + + Oops! Could not parse historical data. + Oeps! Ophalen van historische data is mislukt. - apps/client/src/app/pages/landing/landing-page.html - 253 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 - - Open Source - Open Source + + Do you really want to delete this system message? + Wilt u dit systeembericht echt verwijderen? - apps/client/src/app/pages/landing/landing-page.html - 261 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 - - Benefit from continuous improvements through a strong community. - Profiteer van voortdurende verbeteringen door een sterke gemeenschap. + + 50-Day Trend + 50-Daagse Trend - apps/client/src/app/pages/landing/landing-page.html - 263 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 - - Why Ghostfolio? - Waarom Ghostfolio? + + 200-Day Trend + 200-Daagse Trend - apps/client/src/app/pages/landing/landing-page.html - 272 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 - - Ghostfolio is for you if you are... - Ghostfolio is iets voor je als je... + + Cash Balances + Contant Saldo - apps/client/src/app/pages/landing/landing-page.html - 273 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 - - trading stocks, ETFs or cryptocurrencies on multiple platforms - handelt in aandelen, ETF’s of cryptocurrencies op meerdere platforms + + Starting from + Begin vanaf - apps/client/src/app/pages/landing/landing-page.html - 280 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - - - pursuing a buy & hold strategy - streeft naar een buy & hold strategie - apps/client/src/app/pages/landing/landing-page.html - 286 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - interested in getting insights of your portfolio composition - geïnteresseerd bent in het krijgen van inzicht in je portefeuillesamenstelling + + Do you really want to delete this account balance? + Wilt u dit rekeningsaldo echt verwijderen? - apps/client/src/app/pages/landing/landing-page.html - 291 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - valuing privacy and data ownership - privacy en eigendom van gegevens waardeert + + If a translation is missing, kindly support us in extending it here. + Als er een vertaling ontbreekt, kunt u ons helpen deze here uit te breiden. - apps/client/src/app/pages/landing/landing-page.html - 296 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - into minimalism - houdt van een minimalistisch ontwerp + + The current market price is + De huidige markt waarde is - apps/client/src/app/pages/landing/landing-page.html - 299 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - caring about diversifying your financial resources - zorgdraagt voor het diversifiëren van je financiële middelen + + Test + Test - apps/client/src/app/pages/landing/landing-page.html - 303 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - interested in financial independence - geïnteresseerd bent in financiële onafhankelijkheid + + Date Range + Datumbereik - apps/client/src/app/pages/landing/landing-page.html - 307 + libs/ui/src/lib/assistant/assistant.html + 143 - - saying no to spreadsheets in - "nee" zegt tegen spreadsheets in + + Permission + Toestemming - apps/client/src/app/pages/landing/landing-page.html - 311 + apps/client/src/app/components/access-table/access-table.component.html + 18 - - - still reading this list - nog steeds deze lijst aan het lezen bent - apps/client/src/app/pages/landing/landing-page.html - 314 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 - - Learn more about Ghostfolio - Leer meer over Ghostfolio + + Restricted view + Beperkte blik - apps/client/src/app/pages/landing/landing-page.html - 319 + apps/client/src/app/components/access-table/access-table.component.html + 26 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - What our users are saying - Wat onze gebruikers zeggen + + Oops! Could not grant access. + Oeps! Kan geen toegang verlenen. - apps/client/src/app/pages/landing/landing-page.html - 327 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 - - Members from around the globe are using Ghostfolio Premium - Leden van over de hele wereld gebruikenGhostfolio Premium + + Private + Prive - apps/client/src/app/pages/landing/landing-page.html - 366 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - How does Ghostfolio work? - Hoe Ghostfolio werkt? + + Job Queue + Opdracht Wachtrij - apps/client/src/app/pages/landing/landing-page.html - 383 + libs/common/src/lib/routes/routes.ts + 46 - - Sign up anonymously* - Anoniem aanmelden* + + Market data is delayed for + Markt data is vertraagd voor - apps/client/src/app/pages/landing/landing-page.html - 392 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 - - * no e-mail address nor credit card required - * geen e-mailadres of creditcard nodig + + Investment + Investering - apps/client/src/app/pages/landing/landing-page.html - 394 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - - - Add any of your historical transactions - Voeg al je historische transacties toe - apps/client/src/app/pages/landing/landing-page.html - 405 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - - - Get valuable insights of your portfolio composition - Krijg waardevolle inzichten in de samenstelling van je portefeuille - apps/client/src/app/pages/landing/landing-page.html - 417 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - - - Are you ready? - Ben je er klaar voor? - apps/client/src/app/pages/landing/landing-page.html - 431 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 - - - Live Demo - Live Demo - apps/client/src/app/pages/landing/landing-page.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + Absolute Asset Performance + Absolute Activaprestaties - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Get the full picture of your personal finances across multiple platforms. - Krijg een volledig beeld van je persoonlijke financiën op meerdere platforms. + + Asset Performance + Activaprestaties - apps/client/src/app/pages/landing/landing-page.html - 242 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Get started in only 3 steps - Aan de slag in slechts 3 stappen + + Absolute Currency Performance + Absolute Valutaprestaties - apps/client/src/app/pages/landing/landing-page.html - 386 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 - - faq - veelgestelde-vragen - snake-case + + Currency Performance + Valutaprestaties - apps/client/src/app/app.component.ts - 77 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + Absolute Net Performance + Absolute Nettoprestatie - apps/client/src/app/core/paths.ts - 3 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + Net Performance + Nettoprestatie - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + Week to date + Week tot nu toe - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + WTD + Week tot nu toe - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + Month to date + Maand tot nu toe - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + MTD + MTD - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - features - functionaliteiten - snake-case + + Year to date + Jaar tot nu toe - apps/client/src/app/app.component.ts - 78 + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + View + Weergave - apps/client/src/app/components/header/header.component.ts - 82 + apps/client/src/app/components/access-table/access-table.component.html + 23 - apps/client/src/app/components/header/header.component.ts - 87 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + Oops! A data provider is experiencing the hiccups. + Oeps! Een gegevensaanbieder ondervindt problemen. - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Als u vandaag met pensioen zou gaan, kunt u per jaar or per maand opnemen, gebaseerd op uw totale vermogen van en een opnamepercentage van 4%. - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + Reset Filters + Filters Herstellen - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/ui/src/lib/assistant/assistant.html + 238 + + + year + jaar - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + years + jaren - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + Apply Filters + Filters Toepassen - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/ui/src/lib/assistant/assistant.html + 248 + + + Data Gathering + Data Verzamelen - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + General + Algemeen - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + Cloud + Cloud - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 240 - - about - over - snake-case + + Self-Hosting + Zelf Hosten - apps/client/src/app/app.component.ts - 64 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 248 + + + self-hosting + zelf-hosten + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 243 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 246 + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Oeps! Het lijkt er op dat u te veel verzoeken indient. Doe het iets rustiger aan alstublieft. - apps/client/src/app/components/header/header.component.ts - 81 + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + My Account + Mijn Account - apps/client/src/app/components/header/header.component.ts - 86 + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + Active + Actief - apps/client/src/app/core/paths.ts - 2 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + Closed + Gesloten - apps/client/src/app/pages/about/about-page.component.ts - 45 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + Indonesia + Indonesië - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/ui/src/lib/i18n.ts + 87 + + + Activity + Activiteit - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + Dividend Yield + Dividendrendement - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + Execute Job + Opdracht Uitvoeren - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + Priority + Prioriteit - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + This action is not allowed. + Deze actie is niet toegestaan. - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + Liquidity + Liquiditeit - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + libs/ui/src/lib/i18n.ts + 48 + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activiteit} other {activiteiten}} - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + Buy and sell + Aan- en Verkoop - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 8 + + + Delete Activities + Verwijder Activiteiten - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + Internationalization + Internationalizering - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 119 + + + Do you really want to close your Ghostfolio account? + Wilt u uw Ghostfolio account echt sluiten? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + Danger Zone + Gevarenzone - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 - - privacy-policy - privacybeleid - snake-case + + Close Account + Account Sluiten - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + By ETF Holding + Per Aangehouden ETF - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + Approximation based on the top holdings of each ETF + Benadering op basis van de grootste belegingen binnen iedere ETF - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 - - license - licentie - snake-case + + Join now or check out the example account + Word nu lid of bekijk het voorbeeldaccount - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/landing/landing-page.html + 435 + + + Oops! There was an error setting up biometric authentication. + Oeps! Er is een fout opgetreden met het instellen van de biometrische authenticatie. - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + Show more + Laat meer zien - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 - - markets - markten - snake-case + + Benchmarks + Benchmarks - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + Delete Profiles + Verwijder Profielen - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + Do you really want to delete these profiles? + Wilt u deze profielen echt verwijderen? - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + Oops! Could not delete profiles. + Oeps! Verwijderen van de profielen is mislukt. - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + Table + Tabel - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + Chart + Grafiek - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.html 19 + + + Would you like to refine your personal investment strategy? + Wilt u uw persoonlijke belegginngsstrategie verfijnen? - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/pages/public/public-page.html + 212 + + + Alternative + Alternatief - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + App + App - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 - - pricing - prijzen - snake-case + + Budgeting + Budgetteren - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + Community + Gemeenschap - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/app.component.html + 130 - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 - apps/client/src/app/components/header/header.component.ts - 89 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + apps/client/src/app/pages/features/features-page.html + 276 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + Family Office + Familiekantoor - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + Investor + Investeerder - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + Open Source + Open Source - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/landing/landing-page.html + 261 - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 - - register - registratie - snake-case + + Personal Finance + Persoonlijke Financiën - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/app.component.html + 57 - apps/client/src/app/components/header/header.component.ts + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts 90 + + + Privacy + Privacy - apps/client/src/app/core/auth.guard.ts - 55 - - - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + Software + Software - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + Tool + Hulpmiddel - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + User Experience + Gebruikers Ervaring - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + Wealth + Vermogen - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 - - resources - bronnen - snake-case + + Wealth Management + Vermogensbeheer - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + Australia + Australië - apps/client/src/app/components/header/header.component.ts - 85 + libs/ui/src/lib/i18n.ts + 76 + + + Austria + Oostenrijk - apps/client/src/app/components/header/header.component.ts - 91 + libs/ui/src/lib/i18n.ts + 77 + + + Belgium + België - apps/client/src/app/core/paths.ts - 10 + libs/ui/src/lib/i18n.ts + 78 + + + Bulgaria + Bulgarije - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 80 + + + Canada + Canada - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 81 + + + Czech Republic + Tsjechische Republiek - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 82 + + + Finland + Finland - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 83 + + + France + Frankrijk - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/i18n.ts + 84 + + + Germany + Duitsland - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + libs/ui/src/lib/i18n.ts + 85 + + + India + India - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/i18n.ts + 86 + + + Italy + Italië - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/i18n.ts + 88 + + + Netherlands + Nederland - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + libs/ui/src/lib/i18n.ts + 90 + + + New Zealand + Nieuw-Zeeland - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 91 + + + Poland + Polen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + libs/ui/src/lib/i18n.ts + 92 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Deze overzichtspagina bevat een verzameling tools voor persoonlijke financiën vergeleken met het open source alternatief Ghostfolio. Als je waarde hecht aan transparantie, gegevensprivacy en samenwerking binnen een gemeenschap, biedt Ghostfolio een uitstekende mogelijkheid om je financieel beheer in eigen hand te nemen. + + Romania + Roemenië - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/i18n.ts + 93 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Bekijk de links hieronder om verschillende persoonlijke financiële tools met Ghostfolio te vergelijken. + + South Africa + Zuid-Afrika - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + libs/ui/src/lib/i18n.ts + 95 - - Open Source Alternative to - Open Source alternatief voor + + Thailand + Thailand - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + libs/ui/src/lib/i18n.ts + 97 - - Open Source Alternative to - Open Source alternatief voor + + United States + Verenigde Station - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + libs/ui/src/lib/i18n.ts + 100 - - The Open Source Alternative to - Open Source alternatief voor + + Error + Fout - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Ben je op zoek naar een open source alternatief voor ? Ghostfolio is een krachtige tool voor portefeuillebeheer die particulieren een uitgebreid platform biedt om hun beleggingen bij te houden, te analyseren en te optimaliseren. Of je nu een ervaren belegger bent of net begint, Ghostfolio biedt een intuïtieve gebruikersinterface en uitgebreide functionaliteiten om je te helpen weloverwogen beslissingen te nemen en je financiële toekomst in eigen handen te nemen. + + Deactivate + Deactiveren - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + apps/client/src/app/components/rule/rule.component.html + 72 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio is open source software (OSS) en biedt een kosteneffectief alternatief voor waardoor het bijzonder geschikt is voor mensen met een krap budget, zoals degenen Financiële onafhankelijkheid nastreven, vroeg met pensioen gaan (FIRE). Door gebruik te maken van de collectieve inspanningen van een gemeenschap van ontwikkelaars en liefhebbers van persoonlijke financiën, verbetert Ghostfolio voortdurend de mogelijkheden, veiligheid en gebruikerservaring. + + Activate + Activeren - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/components/rule/rule.component.html + 74 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Laten we eens dieper duiken in de gedetailleerde vergelijkingstabel hieronder om een beter begrip te krijgen hoe Ghostfolio zichzelf positioneert ten opzichte van . We gaan in op verschillende aspecten zoals functies, gegevensprivacy, prijzen en meer, zodat je een weloverwogen keuze kunt maken voor jouw persoonlijke behoeften. + + Inactive + Inactief - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 - - open-source-alternative-to - open-source-alternatief-voor + + Cancel + Annuleren - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Houd er rekening mee dat de verstrekte informatie gebaseerd is op ons onafhankelijk onderzoek en analyse. Deze website is niet gelieerd aan of een ander product dat in de vergelijking wordt genoemd. Aangezien het landschap van tools voor persoonlijke financiën evolueert, is het essentieel om specifieke details of wijzigingen rechtstreeks op de betreffende productpagina te controleren. Hebben je gegevens een opfrisbeurt nodig? Help ons nauwkeurige gegevens te onderhouden over GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - Ready to take your investments to the next level? - Klaar om je investeringen naar een hoger niveau te brengen? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 - - - Get Started - Aan de slag - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 - - - Switzerland - Zwitserland - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 - libs/ui/src/lib/i18n.ts - 90 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 - - - Global - Wereldwijd - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 - - - (Last 24 hours) - (Laatste 24 uur) - apps/client/src/app/pages/open/open-page.html - 37 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 - - - (Last 30 days) - (Laatste 30 dagen) - apps/client/src/app/pages/open/open-page.html + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 48 - apps/client/src/app/pages/open/open-page.html - 59 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 - - (Last 90 days) - (Laatste 90 dagen) + + Close + Sluiten - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 - - Choose or drop a file here - Choose or drop a file here + + Yes + Ja - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/i18n.ts + 32 - - You are using the Live Demo. - You are using the Live Demo. + + Copy link to clipboard + Kopieer link naar klembord - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - One-time fee, annual account fees - One-time fee, annual account fees + + Portfolio Snapshot + Portfolio Momentopname - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Distribution of corporate earnings - Distribution of corporate earnings + + Change with currency effect Change + Verandering met valuta effect Verandering - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from + + Performance with currency effect Performance + Prestatie met valuta effect Prestatie - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Fee - Fee + + Threshold Min + Drempelwaarde Min - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Interest - Interest + + Threshold Max + Drempelwaarde Max - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Revenue for lending out money - Revenue for lending out money + + Customize + Aanpassen - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/components/rule/rule.component.html + 67 - - Add Tag - Add Tag + + No auto-renewal. + Geen automatische verlenging. - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Do you really want to delete this tag? - Do you really want to delete this tag? + + This year + Dit jaar - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/public/public-page.html + 42 - - Update tag - Update tag + + From the beginning + Vanaf het begin - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/public/public-page.html + 60 - - Add tag - Add tag + + Oops! Invalid currency. + Oeps! Ongeldige valuta. - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Currency Cluster Risks - Currency Cluster Risks + + This page has been archived. + Deze pagina is gearchiveerd. - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Account Cluster Risks - Account Cluster Risks + + is Open Source Software + is Open Source Software - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Transfer Cash Balance - Transfer Cash Balance + + is not Open Source Software + is geen Open Source Software - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Benchmark - Benchmark + + can be self-hosted + kan zelf gehost worden - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - - - Version - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Settings - Settings + + cannot be self-hosted + kan niet zelf gehost worden - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - From - From - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - To - To + + can be used anonymously + kan anoniem gebruikt worden - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Transfer - Transfer - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Membership - Membership + + cannot be used anonymously + kan niet anoniem gebruik worden - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Access - Access + + offers a free plan + biedt een gratis abonnement aan - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Find holding... - Find holding... + + does not offer a free plan + biedt geen gratis abonnement aan - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - No entries... - No entries... + + Oops! Could not find any assets. + Oeps! Kan geen activa vinden. - libs/ui/src/lib/assistant/assistant.html - 63 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 + + + Data Providers + Gegevensleveranciers - libs/ui/src/lib/assistant/assistant.html - 84 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Asset Profile - Asset Profile + + Set API key + API-sleutel instellen - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Do you really want to delete this asset profile? - Do you really want to delete this asset profile? + + Get access to 80’000+ tickers from over 50 exchanges + Krijg toegang tot meer dan 80.000 tickers van meer dan 50 beurzen - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + libs/ui/src/lib/i18n.ts + 24 - - Search - Search + + Ukraine + Oekraïne - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + libs/ui/src/lib/i18n.ts + 98 - - Add Manually - Add Manually + + Join now + Word nu lid - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio is een persoonlijk financieel dashboard om uw activa zoals aandelen, ETF’s of cryptocurrencies over meerdere platforms bij te houden. + + Glossary + Woordenlijst - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html 4 - - - Last All Time High - Last All Time High - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - User - User - apps/client/src/app/components/admin-users/admin-users.html - 29 + libs/common/src/lib/routes/routes.ts + 293 - - Ghostfolio vs comparison table - Ghostfolio vs comparison table + + Guides + Gidsen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Open Source Wealth Management Software - Open Source Wealth Management Software - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - apps/client/src/app/pages/i18n/i18n-page.html - 9 + libs/common/src/lib/routes/routes.ts + 301 - - Oops, cash balance transfer has failed. - Oops, cash balance transfer has failed. + + guides + gidsen + kebab-case - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + libs/common/src/lib/routes/routes.ts + 296 - - - Extreme Fear - Extreme Fear - libs/ui/src/lib/i18n.ts - 96 + libs/common/src/lib/routes/routes.ts + 299 - - Extreme Greed - Extreme Greed + + glossary + woordenlijst + kebab-case - libs/ui/src/lib/i18n.ts - 97 + libs/common/src/lib/routes/routes.ts + 288 - - - Neutral - Neutral - libs/ui/src/lib/i18n.ts - 100 + libs/common/src/lib/routes/routes.ts + 291 - - Oops! Could not parse historical data. - Oops! Could not parse historical data. + + Threshold range + Drempebereik - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Do you really want to delete this system message? - Do you really want to delete this system message? + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray gebruikt statische analyse om potentiële problemen en risico’s in uw portefeuille te ontdekken. Pas de onderstaande regels aan en stel aangepaste drempelwaarden in die aansluiten bij uw persoonlijke beleggingsstrategie. - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - 50-Day Trend - 50-Day Trend + + Economic Market Cluster Risks + Risico’s van Economische Marktclusters - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - 200-Day Trend - 200-Day Trend + + of + van - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Cash Balances - Cash Balances + + daily requests + dagelijkse verzoeken - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Starting from - Starting from + + Remove API key + Verwijder API-sleutel - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 + + + Do you really want to delete the API key? + Wilt u de API-sleutel echt verwijderen? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - year - year + + Please enter your Ghostfolio API key: + Voer uw Ghostfolio API-sleutel in: - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/pages/api/api-page.component.ts + 41 + + + API Requests Today + Aantal API-Verzoeken Vandaag - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Do you really want to delete this account balance? - Do you really want to delete this account balance? + + Could not generate an API key + Er kon geen API-sleutel worden gegenereerd - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - is an invalid currency! - is an invalid currency! + + Set this API key in your self-hosted environment: + Stel deze API-sleutel in uw zelf-gehoste omgeving in: - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - If a translation is missing, kindly support us in extending it here. - If a translation is missing, kindly support us in extending it here. + + Ghostfolio Premium Data Provider API Key + Ghostfolio Premium Gegevensleverancier API-sleutel - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - The current market price is - The current market price is + + Do you really want to generate a new API key? + Wilt u echt een nieuwe API-sleutel genereren? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Test - Test + + API Key + API-sleutel - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - Date Range - Date Range + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Genereer een Ghostfolio Premium Gegevensleverancier API-sleutel voor zelfgehoste omgevingen... - libs/ui/src/lib/assistant/assistant.html - 93 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - Permission - Permission + + out of + van - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 + + + rules align with your portfolio. + regels die aansluiten bij uw portefeuille. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Restricted view - Restricted view + + Save + Opslaan - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Oops! Could not grant access. - Oops! Could not grant access. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - Private - Private - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 - - - Job Queue - Job Queue - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Market data is delayed for - Market data is delayed for - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Investment - Investment - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Absolute Asset Performance - Absolute Asset Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Asset Performance - Asset Performance + + Asset Class Cluster Risks + Activa Klasse Cluster Risico’s - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Absolute Currency Performance - Absolute Currency Performance + + Me + Ik - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/header/header.component.html + 213 - - - Currency Performance - Currency Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Absolute Net Performance - Absolute Net Performance + + Received Access + Toegang Verkregen - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Net Performance - Net Performance + + Please enter your Ghostfolio API key. + Voer uw Ghostfolio API-sleutel in. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Week to date - Week to date + + AI prompt has been copied to the clipboard + AI-prompt is naar het klembord gekopieerd - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - WTD - WTD + + Link has been copied to the clipboard + Link is gekopieerd naar klemboord - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Month to date - Month to date + + Regional Market Cluster Risks + Regionale Markt Clusterrisico’s - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - MTD - MTD + + Lazy + Lui - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Year to date - Year to date + + Instant + Direct - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - View - View + + Default Market Price + Standaard Marktprijs - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 + + + Mode + Modus - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Oops! A data provider is experiencing the hiccups. - Oops! A data provider is experiencing the hiccups. + + Selector + Kiezer - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + + HTTP Request Headers + HTTP Verzoek Headers - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - Reset Filters - Reset Filters + + end of day + eind van de dag - libs/ui/src/lib/assistant/assistant.html - 185 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - year - year + + real-time + real-time - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - years - years + + Open Duck.ai + Open Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Apply Filters - Apply Filters + + Create + Nieuw - libs/ui/src/lib/assistant/assistant.html - 195 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - Data Gathering - Data Gathering + + Change + Aanpassen - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - General - General - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Cloud - Cloud + + Performance + Prestatie - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Self-Hosting - Self-Hosting - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - self-hosting - self-hosting + + Copy portfolio data to clipboard for AI prompt + Kopieer portfolio gegevens naar klemboord voor AI-prompt - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - FAQ - FAQ + + Copy AI prompt to clipboard for analysis + Kopieer AI-prompt naar klemboord voor analyse - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 + + + Armenia + Armenië - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 75 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! It looks like you’re making too many requests. Please slow down a bit. + + British Virgin Islands + Britse Maagdeneilanden - apps/client/src/app/core/http-response.interceptor.ts - 96 + libs/ui/src/lib/i18n.ts + 79 - - My Account - My Account + + Singapore + Singapore - apps/client/src/app/pages/i18n/i18n-page.html - 13 + libs/ui/src/lib/i18n.ts + 94 - - Active - Active + + Terms and Conditions + Algemene Voorwaarden - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - Closed - Closed + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Bewaar uw beveiligingstoken goed. Als u deze verliest, kunt u uw account niet meer herstellen. - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Activity - Activity + + I understand that if I lose my security token, I cannot recover my account + Ik begrijp dat als ik mijn beveiligingstoken verlies, ik mijn account niet kan herstellen - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Dividend Yield - Dividend Yield + + Continue + Doorgaan - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Execute Job - Execute Job + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Hier is uw beveiligingstoken. Deze is slechts één keer zichtbaar, bewaar hem op een veilige plaats. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Priority - Priority + + Security token + Beveiligingstoken - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - This action is not allowed. - This action is not allowed. - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Liquidity - Liquidity + + Do you really want to generate a new security token for this user? + Wilt u echt een nieuw beveiligingstoken voor deze gebruiker aanmaken? - libs/ui/src/lib/i18n.ts - 48 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + Generate Security Token + Beveiligingstoken Aanmaken - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Buy and sell - Buy and sell + + United Kingdom + Verenigd Koninkrijk libs/ui/src/lib/i18n.ts - 8 + 99 - - Delete Activities - Delete Activities + + Terms of Service + Servicevoorwaarden - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Internationalization - Internationalization + + terms-of-service + servicevoorwaarden + kebab-case - apps/client/src/app/app-routing.module.ts - 88 + libs/common/src/lib/routes/routes.ts + 212 + + + libs/common/src/lib/routes/routes.ts + 215 - - Do you really want to close your Ghostfolio account? - Do you really want to close your Ghostfolio account? + + Terms of Service + Servicevoorwaarden - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/app.component.html + 112 + + + libs/common/src/lib/routes/routes.ts + 217 - - Danger Zone - Danger Zone + + and I agree to the Terms of Service. + en ik ga akkoord met de Servicevoorwaarden. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Close Account - Close Account + + () is already in use. + () is al in gebruik. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - By ETF Holding - By ETF Holding + + An error occurred while updating to (). + Er is een fout opgetreden tijdens het updaten naar (). - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Apply + Toepassen - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Join now or check out the example account - Join now or check out the example account + + with API access for + met API toegang tot - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + Gather Recent Historical Market Data + Verzamel Recente Marktgegevens - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Show more - Show more + + Gather All Historical Market Data + Verzamel Alle Marktgegevens - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Benchmarks - Benchmarks + + Gather Historical Market Data + Verzamel Historische Marktgegevens - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Delete Profiles - Delete Profiles + + Data Gathering is off + Gegevensverzameling is uitgeschakeld apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + 38 - - Do you really want to delete these profiles? - Do you really want to delete these profiles? + + Performance Calculation + Prestatieberekening - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! Could not delete profiles. - Oops! Could not delete profiles. + + someone + iemand - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Table - Table + + Add asset to watchlist + Voeg activa toe aan de volglijst - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Chart - Chart + + Watchlist + Volglijst - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 + + + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? + + Do you really want to delete this item? + Wilt u dit item echt verwijderen? - apps/client/src/app/pages/public/public-page.html - 211 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Alternative - Alternative + + Log out + Uitloggen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/header/header.component.html + 329 - - App - App + + Calculations are based on delayed market data and may not be displayed in real-time. + Berekeningen zijn gebaseerd op vertraagde marktgegevens en worden mogelijk niet in realtime weergegeven. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 - - Budgeting - Budgeting + + changelog + wijzigingslogboek + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - Community - Community + + Demo user account has been synced. + Demo-gebruikersaccount is gesynchroniseerd. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Family Office - Family Office + + Sync Demo User Account + Synchroniseer demo-gebruikersaccount - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Investor - Investor + + Set up + Opgezet - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Open Source - Open Source + + No emergency fund has been set up + Er is geen noodfonds ingesteld - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Personal Finance - Personal Finance + + An emergency fund has been set up + Er is een noodfonds opgericht - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Privacy - Privacy + + Fee Ratio + Vergoedingsverhouding - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Software - Software + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + De kosten overschrijden ${thresholdMax}% van uw initiële investering (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Tool - Tool + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + De kosten bedragen niet meer dan ${thresholdMax}% van uw initiële investering (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - User Experience - User Experience + + Name + Naam - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth - Wealth + + Find holding or page... + Zoek holding of pagina... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.component.ts + 161 + + + + Quick Links + Snelle koppelingen + + libs/ui/src/lib/assistant/assistant.html + 56 - - Wealth Management - Wealth Management + + Asset Profiles + Activaprofielen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 112 - - Australia - Australia + + Live Demo + Live-demo - libs/ui/src/lib/i18n.ts - 73 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Austria - Austria - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Belgium - Belgium - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bulgaria + + Open Source Alternative to + Open Source alternatief voor - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Canada + + Single Account + Eén account - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - Czech Republic + + Your net worth is managed by a single account + Uw nettowaarde wordt beheerd door één enkele account - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finland + + Your net worth is managed by ${accountsLength} accounts + Uw nettowaarde wordt beheerd door ${accountsLength}-accounts - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - France + + personal-finance-tools + hulpmiddelen-voor-persoonlijke-financien + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 - - - Germany - Germany - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 315 - - - India - India - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italy + + markets + markten + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 - - - Netherlands - Netherlands - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 307 - - New Zealand - New Zealand + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Vul je self-hosted Ghostfolio met een krachtige dataleverancier om toegang te krijgen tot 80.000+ tickers van meer dan 50 beurzen wereldwijd. - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Poland - Poland + + Get Access + Krijg toegang - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Romania - Romania + + Learn more + Meer informatie - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - South Africa - South Africa + + Limited Offer! + Beperkt aanbod! - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Thailand - Thailand + + Get extra + Krijg extra - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - United States - United States + + Available + Beschikbaar - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Error - Error + + Unavailable + Niet beschikbaar - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Deactivate - Deactivate + + new + nieuw - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Activate - Activate - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Inactive - Inactive + + Investment + Investering - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Cancel - Cancel + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Meer dan ${thresholdMax}% van uw huidige investering bedraagt ​​${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Close - Close + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + Het grootste deel van uw huidige investering bedraagt ​​${maxAccountName} (${maxInvestmentRatio}%) en bedraagt ​​niet meer dan ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Yes - Yes + + Equity + Eigen vermogen - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + De aandelenbijdrage van uw huidige investering (${equityValueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + De inbreng in eigen vermogen van uw huidige investering (${equityValueRatio}%) ligt onder de ${thresholdMin}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Change with currency effect Change - Change with currency effect Change + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De aandelenbijdrage van uw huidige investering (${equityValueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Performance with currency effect Performance - Performance with currency effect Performance + + Fixed Income + Vastrentende waarden - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + De bijdrage van vastrentende waarden in uw huidige investering (${fixedIncomeValueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + De bijdrage van vastrentende waarden in uw huidige investering (${fixedIncomeValueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Close - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van vastrentende waarden in uw huidige investering (${fixedIncomeValueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Customize - Customize + + Investment: Base Currency + Investering: basisvaluta - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + Het grootste deel van uw huidige investering staat niet in uw basisvaluta (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today - Today + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + Het grootste deel van uw huidige investering bevindt zich in uw basisvaluta (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - This year - This year + + Investment + Investering - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - From the beginning - From the beginning + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Meer dan ${thresholdMax}% van uw huidige investering is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - Oops! Invalid currency. - Oops! Invalid currency. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + Het grootste deel van uw huidige investering is in ${currency} (${maxValueRatio}%) en overschrijdt ${thresholdMax}% niet - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - This page has been archived. - This page has been archived. + + start + start + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 336 - - - is Open Source Software - is Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 337 - - is not Open Source Software - is not Open Source Software + + Do you really want to generate a new security token? + Wilt u echt een nieuwe securitytoken genereren? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is Open Source Software - is Open Source Software + + Generate + Genereren - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is not Open Source Software - is not Open Source Software + + Stocks + Aandelen - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be self-hosted - cannot be self-hosted + + Cryptocurrencies + Cryptovaluta - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/pages/features/features-page.html + 51 - - cannot be self-hosted - cannot be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - can be used anonymously - can be used anonymously + + Manage Asset Profile + Beheer activaprofiel - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - cannot be used anonymously - cannot be used anonymously + + Alternative Investment + Alternatieve belegging - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 44 - - can be used anonymously - can be used anonymously + + Collectible + Verzamelobject - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + libs/ui/src/lib/i18n.ts + 54 - - cannot be used anonymously - cannot be used anonymously + + Average Unit Price + Gemiddelde eenheidsprijs - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Accountclusterrisico’s - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Clusterrisico’s van beleggingscategorieën - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Valutaclusterrisico’s - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Risico’s van economische marktclusters - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Noodfonds - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Kosten - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Risico’s van regionale marktclusters - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + Geen resultaten gevonden... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Ontwikkelde markten - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + De bijdrage van ontwikkelde markten aan je huidige investering (${developedMarketsValueRatio}%) overschrijdt ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + De bijdrage van ontwikkelde markten aan je huidige investering (${developedMarketsValueRatio}%) ligt onder ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van ontwikkelde markten aan je huidige investering (${developedMarketsValueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Opkomende markten - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + De bijdrage van opkomende markten aan je huidige investering (${emergingMarketsValueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + De bijdrage van opkomende markten aan je huidige investering (${emergingMarketsValueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van opkomende markten aan je huidige investering (${emergingMarketsValueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + Er zijn geen accounts ingesteld - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Je nettovermogen wordt beheerd door 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Azië-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + De bijdrage van de Azië-Pacific markt aan je huidige investering (${valueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + De bijdrage van de Azië-Pacific markt aan je huidige investering (${valueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van de Azië-Pacific markt aan je huidige investering (${valueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Opkomende markten - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + De bijdrage van de opkomende markten aan je huidige investering (${valueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + De bijdrage van de opkomende markten aan je huidige investering (${valueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van de opkomende markten aan je huidige investering (${valueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europa - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + De bijdrage van de Europese markt aan je huidige investering (${valueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + De bijdrage van de Europese markt aan je huidige investering (${valueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van de Europese markt aan je huidige investering (${valueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + De bijdrage van de Japanse markt aan je huidige investering (${valueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + De bijdrage van de Japanse markt aan je huidige investering (${valueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van de Japanse markt aan je huidige investering (${valueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + Noord-Amerika - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + De bijdrage van de Noord-Amerikaanse markt aan je huidige investering (${valueRatio}%) overschrijdt ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + De bijdrage van de Noord-Amerikaanse markt aan je huidige investering (${valueRatio}%) ligt onder ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + De bijdrage van de Noord-Amerikaanse markt aan je huidige investering (${valueRatio}%) ligt binnen het bereik van ${thresholdMin}% en ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Vind Ghostfolio op GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Word lid van de Ghostfolio Slack-gemeenschap - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Volg Ghostfolio op X (voorheen Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Stuur een e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Volg Ghostfolio op LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is een onafhankelijk en zelfgefinancierd bedrijf - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Ondersteun Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 06b42b64d..4c5a791a3 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -1,7635 +1,8134 @@ - + about o-ghostfolio - snake-case + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 214 + + + faq + faq + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 245 + + + features + funkcje + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 255 + + + license + licencja + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + rynki + kebab-case - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 260 + + + pricing + cennik + kebab-case - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 270 + + + privacy-policy + polityka-prywatnosci + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + libs/common/src/lib/routes/routes.ts + 207 - - faq - faq - snake-case - - apps/client/src/app/app.component.ts - 77 - + + register + zarejestruj + kebab-case - apps/client/src/app/core/paths.ts - 3 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + zasoby + kebab-case - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 298 - - - features - funkcje - snake-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 322 + + + You are using the Live Demo. + Korzystasz z wersji demonstracyjnej. - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/app.component.html + 12 + + + Create Account + Utwórz Konto - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/app.component.html + 13 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + apps/client/src/app/pages/register/register-page.html + 27 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 2 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + + + Frequently Asked Questions (FAQ) + Często Zadawane Pytania (FAQ) - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + Ryzyko strat na rynku może być znaczne. Nie jest zalecane inwestowanie pieniędzy, które mogą być potrzebne w krótkim okresie. - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/app.component.html + 221 + + + Alias + Alias - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + apps/client/src/app/components/access-table/access-table.component.html + 4 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 + + + Grantee + Beneficjent - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + Type + Typ - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 - - - license - licencja - snake-case - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 15 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/ui/src/lib/activities-table/activities-table.component.html + 161 - - markets - rynki - snake-case + + Details + Szczegóły - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/access-table/access-table.component.html + 33 + + + Revoke + Cofnij - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + Do you really want to revoke this granted access? + Czy na pewno chcesz cofnąć przyznany dostęp? - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/components/access-table/access-table.component.ts + 108 + + + Cash Balance + Saldo Gotówkowe - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 + + + Platform + Platforma - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 - - pricing - cennik - snake-case + + Transfer Cash Balance + Transfer Salda Gotówkowego - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Name + Nazwa - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 - apps/client/src/app/components/header/header.component.ts + apps/client/src/app/components/admin-market-data/admin-market-data.html 89 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + libs/ui/src/lib/activities-table/activities-table.component.html + 138 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts + libs/ui/src/lib/top-holdings/top-holdings.component.html 16 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + Total + Suma - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 55 + + + Currency + Waluta - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 - - - privacy-policy - polityka-prywatnosci - snake-case - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 - - - register - zarejestruj - snake-case - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 - apps/client/src/app/components/header/header.component.ts - 90 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 - apps/client/src/app/core/auth.guard.ts - 55 + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + Value + Wartość - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 - - - resources - zasoby - snake-case - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 - apps/client/src/app/components/header/header.component.ts - 85 + libs/ui/src/lib/account-balances/account-balances.component.html + 34 - apps/client/src/app/components/header/header.component.ts - 91 + libs/ui/src/lib/activities-table/activities-table.component.html + 257 - apps/client/src/app/core/paths.ts - 10 + libs/ui/src/lib/activities-table/activities-table.component.html + 293 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 + + + Edit + Edytuj - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 - apps/client/src/app/pages/features/features-page.component.ts - 30 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/activities-table/activities-table.component.html + 430 + + + Delete + Usuń - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 - - - You are using the Live Demo. - Korzystasz z wersji demonstracyjnej. - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/admin-overview/admin-overview.html + 131 - - - Create Account - Utwórz Konto - apps/client/src/app/app.component.html - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 - apps/client/src/app/pages/register/register-page.html - 27 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 2 + libs/ui/src/lib/account-balances/account-balances.component.html + 80 - - - Personal Finance - Finanse Osobiste - apps/client/src/app/app.component.html - 57 + libs/ui/src/lib/activities-table/activities-table.component.html + 457 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 - - Markets - Rynki + + Do you really want to delete this account? + Czy na pewno chcesz usunąć to konto? - apps/client/src/app/app.component.html - 61 + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 + + + Asset Profile + Profil Aktywów - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Historical Market Data + Historyczne Dane Rynkowe - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 - - Resources - Zasoby + + Data Source + Źródło Danych - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 - - About - O programie + + Attempts + Próby - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 + + + Created + Utworzono - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 + + + Finished + Zakończono - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 - - Blog - Blog + + Status + Status - apps/client/src/app/app.component.html - 73 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + + + Delete Jobs + Usuń Zadania - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + View Data + Zobacz Dane - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + View Stacktrace + Wyświetl Stos Wywołań - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 - - - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + Delete Job + Usuń Zadanie - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + Details for + Szczegóły dla - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + Date + Data - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + libs/ui/src/lib/account-balances/account-balances.component.html + 12 - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + libs/ui/src/lib/activities-table/activities-table.component.html + 170 - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + Market Price + Cena Rynkowa - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + Currencies + Waluty - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + apps/client/src/app/pages/public/public-page.html + 88 + + + ETFs without Countries + ETF-y bez Krajów - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + ETFs without Sectors + ETF-y bez Sektorów - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + Do you really want to delete this asset profile? + Czy na pewno chcesz usunąć ten profil aktywów? - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Filter by... + Filtruj według... - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + Pierwsza Aktywność - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - - - Changelog - Dziennik Zmian - apps/client/src/app/app.component.html - 77 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 - - Features - Funkcje + + Activities Count + Liczba Aktywności - apps/client/src/app/app.component.html - 79 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + Historical Data + Dane Historyczne - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/features/features-page.html - 5 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 - - Frequently Asked Questions (FAQ) - Często Zadawane Pytania (FAQ) + + Sectors Count + Liczba Sektorów - apps/client/src/app/app.component.html - 83 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + Countries Count + Liczba Krajów - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 - - License - Licencja + + Gather Profile Data + Zbierz Dane Profilu - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 - - Pricing - Cennik + + Oops! Could not parse historical data. + Ups! Nie udało się sparsować danych historycznych. - apps/client/src/app/app.component.html - 97 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Refresh + Odśwież - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 + + + Import + Importuj - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 - - Privacy Policy - Polityka Prywatności + + Sector + Sektor - apps/client/src/app/app.component.html - 103 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 - - Community - Społeczność + + Country + Kraj - apps/client/src/app/app.component.html - 121 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 + apps/client/src/app/components/admin-users/admin-users.html + 78 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 + + + Sectors + Sektory - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 + apps/client/src/app/pages/public/public-page.html + 106 + + + Countries + Kraje - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 + + + Symbol Mapping + Mapowanie Symboli - apps/client/src/app/pages/features/features-page.html - 259 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 - - The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. - Ryzyko strat na rynku może być znaczne. Nie jest zalecane inwestowanie pieniędzy, które mogą być potrzebne w krótkim okresie. + + Scraper Configuration + Konfiguracja Scrapera - apps/client/src/app/app.component.html - 200 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 - - Alias - Alias + + Note + Notatka - apps/client/src/app/components/access-table/access-table.component.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 11 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 - - - Grantee - Beneficjent - apps/client/src/app/components/access-table/access-table.component.html - 11 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 - - Type - Typ + + Add Asset Profile + Dodaj Profil Aktywa - apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 + + + Search + Szukaj - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 22 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 + + + Add Manually + Dodaj Ręcznie - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 15 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Name, symbol or ISIN + Nazwa, symbol lub ISIN - libs/ui/src/lib/activities-table/activities-table.component.html - 161 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 - - - Details - Szczegóły - apps/client/src/app/components/access-table/access-table.component.html - 33 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 - - - Revoke - Cofnij - apps/client/src/app/components/access-table/access-table.component.html - 75 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 - - - Do you really want to revoke this granted access? - Czy na pewno chcesz cofnąć przyznany dostęp? - apps/client/src/app/components/access-table/access-table.component.ts - 67 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 - - Cash Balance - Saldo Gotówkowe + + Do you really want to delete this coupon? + Czy naprawdę chcesz usunąć ten kupon? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 47 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + Do you really want to delete this system message? + Czy naprawdę chcesz usunąć tę wiadomość systemową? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 136 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + Do you really want to flush the cache? + Czy naprawdę chcesz wyczyścić pamięć podręczną? - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 34 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 - - Equity - Kapitał własny + + Please set your system message: + Proszę ustawić swoją wiadomość systemową: - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 - - Activities - Aktywności + + Version + Wersja - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + User Count + Liczba Użytkowników - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 + apps/client/src/app/components/admin-overview/admin-overview.html + 13 + + + Activity Count + Liczba Aktywności - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + per User + na Użytkownika - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 + apps/client/src/app/components/admin-overview/admin-overview.html + 28 + + + Add Currency + Dodaj Walutę - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 + + + User Signup + Rejestracja Użytkownika - apps/client/src/app/components/admin-users/admin-users.html - 135 + apps/client/src/app/components/admin-overview/admin-overview.html + 34 + + + Read-only Mode + Tryb Tylko do Odczytu - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 + apps/client/src/app/components/admin-overview/admin-overview.html + 48 + + + System Message + Wiadomość Systemowa - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + Set Message + Ustaw Wiadomość - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + apps/client/src/app/components/admin-overview/admin-overview.html + 94 - - Platform - Platforma + + Coupons + Kupony - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 67 + apps/client/src/app/components/admin-overview/admin-overview.html + 102 + + + Add + Dodaj - apps/client/src/app/components/accounts-table/accounts-table.component.html - 86 + apps/client/src/app/components/admin-overview/admin-overview.html + 176 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 48 + libs/ui/src/lib/account-balances/account-balances.component.html + 93 - - Transfer Cash Balance - Transfer Salda Gotówkowego + + Housekeeping + Konserwacja - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/components/admin-overview/admin-overview.html + 184 + + + Flush Cache + Wyczyszczenie pamięci podręcznej - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/components/admin-overview/admin-overview.html + 200 - - Name - Nazwa + + Add Platform + Dodaj Platformę - apps/client/src/app/components/accounts-table/accounts-table.component.html - 43 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + Url + Url - apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 15 + 25 + + + Do you really want to delete this platform? + Czy naprawdę chcesz usunąć tę platformę? - apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + Update platform + Aktualizuj platformę - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 15 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + Add platform + Dodaj platformę - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 15 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + Platforms + Platformy - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + Tags + Tagi - libs/ui/src/lib/activities-table/activities-table.component.html - 138 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 28 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - libs/ui/src/lib/top-holdings/top-holdings.component.html + libs/ui/src/lib/tags-selector/tags-selector.component.html 16 - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 88 - - - Total - Suma + + Add Tag + Dodaj Tag - apps/client/src/app/components/accounts-table/accounts-table.component.html - 55 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 - - Currency - Waluta + + Do you really want to delete this tag? + Czy naprawdę chcesz usunąć ten tag? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 65 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Aktualizuj tag - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Dodaj tag - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Do you really want to delete this user? + Czy na pewno chcesz usunąć tego użytkownika? - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 46 + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + User + Użytkownik - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 25 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 31 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + apps/client/src/app/components/header/header.component.html + 231 + + + Engagement per Day + Zaangażowanie na Dzień - libs/ui/src/lib/activities-table/activities-table.component.html - 276 + apps/client/src/app/components/admin-users/admin-users.html + 158 - - Value - Wartość + + Last Request + Ostatnie Żądanie - apps/client/src/app/components/accounts-table/accounts-table.component.html - 171 + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + Impersonate User + Wciel się w Użytkownika - apps/client/src/app/components/accounts-table/accounts-table.component.html - 206 + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + Delete User + Usuń Użytkownika - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 53 + apps/client/src/app/components/admin-users/admin-users.html + 261 + + + Compare with... + Porównaj z... - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + Manage Benchmarks + Zarządzanie Benchmarkami - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 + + + Portfolio + Portfel - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 + apps/client/src/app/components/header/header.component.html + 44 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + apps/client/src/app/components/header/header.component.html + 258 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + libs/common/src/lib/routes/routes.ts + 151 + + + Benchmark + Poziom Odniesienia (Benchmark) - libs/ui/src/lib/account-balances/account-balances.component.html - 34 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 - libs/ui/src/lib/activities-table/activities-table.component.html - 257 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + Current Market Mood + Obecny Nastrój Rynkowy - libs/ui/src/lib/activities-table/activities-table.component.html - 293 + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 + + + User + Użytkownik - libs/ui/src/lib/holdings-table/holdings-table.component.html - 74 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + About Ghostfolio + O Ghostfolio - libs/ui/src/lib/top-holdings/top-holdings.component.html - 25 + apps/client/src/app/components/header/header.component.html + 326 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 102 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Edit - Edytuj + + Get started + Rozpocznij - apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + apps/client/src/app/components/header/header.component.html + 432 + + + Sign in + Zaloguj się - apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + libs/common/src/lib/routes/routes.ts + 81 - libs/ui/src/lib/activities-table/activities-table.component.html - 430 + libs/common/src/lib/routes/routes.ts + 157 - - Delete - Usuń + + Oops! Incorrect Security Token. + Ups! Nieprawidłowy token bezpieczeństwa. - apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + apps/client/src/app/components/header/header.component.ts + 274 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 + + + Manage Activities + Zarządzaj Aktywnościami - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Fear + Zagrożenie - apps/client/src/app/components/admin-overview/admin-overview.html - 206 + apps/client/src/app/components/home-market/home-market.component.ts + 42 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + apps/client/src/app/components/markets/markets.component.ts + 47 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + libs/ui/src/lib/i18n.ts + 105 + + + Greed + Zachłanność - libs/ui/src/lib/account-balances/account-balances.component.html - 80 + apps/client/src/app/components/home-market/home-market.component.ts + 43 - libs/ui/src/lib/activities-table/activities-table.component.html - 457 + apps/client/src/app/components/markets/markets.component.ts + 48 - - - Do you really want to delete this account? - Czy na pewno chcesz usunąć to konto? - apps/client/src/app/components/accounts-table/accounts-table.component.ts + libs/ui/src/lib/i18n.ts 106 - - Asset Profile - Profil Aktywów + + Last Days + Ostatnie Dni - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/home-market/home-market.html + 7 - - - Historical Market Data - Historyczne Dane Rynkowe - apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + apps/client/src/app/components/markets/markets.html + 17 - - Symbol - Symbol - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - + + Welcome to Ghostfolio + Witaj w Ghostfolio - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + apps/client/src/app/components/home-overview/home-overview.html + 11 - - Data Source - Źródło Danych - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 - + + Ready to take control of your personal finances? + Jesteś gotów przejąć kontrolę nad swoimi finansami osobistymi? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + apps/client/src/app/components/home-overview/home-overview.html + 12 + + + Setup your accounts + Skonfiguruj swoje konta - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + apps/client/src/app/components/home-overview/home-overview.html + 19 - - Attempts - Próby + + Get a comprehensive financial overview by adding your bank and brokerage accounts. + Uzyskaj kompleksowy przegląd finansowy, poprzez dodanie swoich rachunków bankowych i maklerskich. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + apps/client/src/app/components/home-overview/home-overview.html + 21 - - Created - Utworzono + + Capture your activities + Rejestruj swoje działania - apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + apps/client/src/app/components/home-overview/home-overview.html + 28 - - Finished - Zakończono + + Record your investment activities to keep your portfolio up to date. + Dokumentuj swoje działania inwestycyjne, aby zapewnić aktualność portfela. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + apps/client/src/app/components/home-overview/home-overview.html + 30 - - Status - Status + + Monitor and analyze your portfolio + Monitoruj i analizuj swój portfel - apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + apps/client/src/app/components/home-overview/home-overview.html + 37 - - Delete Jobs - Usuń Zadania + + Track your progress in real-time with comprehensive analysis and insights. + Śledź swój postęp w czasie rzeczywistym dzięki kompleksowym analizom i obserwacjom. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + apps/client/src/app/components/home-overview/home-overview.html + 39 - - View Data - Zobacz Dane + + Setup accounts + Konfiguracja kont - apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + apps/client/src/app/components/home-overview/home-overview.html + 52 - - View Stacktrace - Wyświetl Stos Wywołań + + Add activity + Dodaj działalność - apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + apps/client/src/app/components/home-overview/home-overview.html + 60 - - - Delete Job - Usuń Zadanie - apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 8 - - Details for - Szczegóły dla + + Total Amount + Całkowita Kwota - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 2 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 - - Date - Data + + Savings Rate + Stopa Oszczędności - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 + + + Security Token + Token Bezpieczeństwa - libs/ui/src/lib/account-balances/account-balances.component.html - 12 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - libs/ui/src/lib/activities-table/activities-table.component.html - 170 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 6 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - - - Market Price - Cena Rynkowa - apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 26 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - Cancel - Anuluj + + or + lub - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/pages/landing/landing-page.html + 48 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/pages/landing/landing-page.html + 451 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 + + + Sign in with Internet Identity + Zaloguj się przy użyciu Tożsamości Internetowej (Internet Identity) - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + Zaloguj się przez Google - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 + + + Stay signed in + Pozostań zalogowany - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 - - Save - Zapisz + + Time in Market + Czas na Rynku - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + Bezwzględne Osiągi Brutto - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Fees + Opłaty - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 + + + Absolute Net Performance + Bezwzględne Osiągi Netto - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 + + + Net Performance + Osiągi Netto - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 + + + Total Assets + Suma Aktywów - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + Assets + Aktywa - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 - - Currencies - Waluty + + Buying Power + Siła Nabywcza - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 - - ETFs without Countries - ETF-y bez Krajów + + Excluded from Analysis + Wykluczone z Analizy - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 - - ETFs without Sectors - ETF-y bez Sektorów + + Liabilities + Pasywa (Zobowiązania Finansowe) - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 + + + apps/client/src/app/pages/features/features-page.html + 102 - - Do you really want to delete this asset profile? - Czy na pewno chcesz usunąć ten profil aktywów? + + Net Worth + Wartość Netto - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 - - Filter by... - Filtruj według... + + Annualized Performance + Osiągi w Ujęciu Rocznym - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 - - Asset Class - Klasa Aktywów + + Please set the amount of your emergency fund. + Wprowadź wysokość funduszu rezerwowego: - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 + + + Minimum Price + Cena Minimalna - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 + + + Maximum Price + Cena Maksymalna - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + Quantity + Ilość apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 189 - libs/ui/src/lib/assistant/assistant.html - 166 + libs/ui/src/lib/activities-table/activities-table.component.html + 186 - - Asset Sub Class - Podklasa Aktywów + + Report Data Glitch + Zgłoś Błąd Danych - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 446 + + + Are you an ambitious investor who needs the full picture? + Jesteś ambitnym inwestorem, który potrzebuje pełnego obrazu swojej działalności? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 + + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + Przejdź na Ghostfolio Premium już dziś i uzyskaj dostęp do ekskluzywnych funkcji, które wzbogacą Twoje doświadczenie inwestycyjne: - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 + + + Portfolio Summary + Podsumowanie Portfela - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + apps/client/src/app/pages/pricing/pricing-page.html + 44 + + + apps/client/src/app/pages/pricing/pricing-page.html + 205 - - First Activity - Pierwsza Aktywność + + Portfolio Allocations + Podział portfela - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + apps/client/src/app/pages/features/features-page.html + 161 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + apps/client/src/app/pages/pricing/pricing-page.html + 48 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 + apps/client/src/app/pages/pricing/pricing-page.html + 209 - - Activities Count - Liczba Aktywności + + Performance Benchmarks + Wskaźniki wydajności - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 - - - Historical Data - Dane Historyczne - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + apps/client/src/app/pages/pricing/pricing-page.html + 52 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 + apps/client/src/app/pages/pricing/pricing-page.html + 213 - - Sectors Count - Liczba Sektorów + + FIRE Calculator + Kalkulator FIRE - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 - - - Countries Count - Liczba Krajów - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + apps/client/src/app/pages/pricing/pricing-page.html + 56 - - - Gather Recent Data - Zbierz Najnowsze Dane - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + apps/client/src/app/pages/pricing/pricing-page.html + 217 - - Gather All Data - Zbierz Wszystkie Dane + + Professional Data Provider + Profesjonalne źródło danych - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 + + + apps/client/src/app/pages/pricing/pricing-page.html + 237 - - Gather Profile Data - Zbierz Dane Profilu + + and more Features... + i więcej Funkcji ... - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 + apps/client/src/app/pages/pricing/pricing-page.html + 72 - - - Oops! Could not parse historical data. - Ups! Nie udało się sparsować danych historycznych. - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/pages/pricing/pricing-page.html + 261 - - Refresh - Odśwież + + Get the tools to effectively manage your finances and refine your personal investment strategy. + Uzyskaj narzędzia do skutecznego zarządzania swoimi finansami i udoskonal swoją osobistą strategię inwestycyjną. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 - - Gather Historical Data - Zbierz Dane Historyczne + + Skip + Pomiń - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 - - - Import - Importuj - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 153 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + Upgrade Plan + Ulepsz Plan - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 186 + apps/client/src/app/components/header/header.component.html + 193 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html 70 - - - Sector - Sektor - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + apps/client/src/app/pages/pricing/pricing-page.html + 299 - - Country - Kraj - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 - + + Today + Dziś - apps/client/src/app/components/admin-users/admin-users.html - 77 + apps/client/src/app/pages/public/public-page.html + 24 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + libs/ui/src/lib/assistant/assistant.component.ts + 348 - - Sectors - Sektory - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 - + + YTD + Liczony od początku roku (year-to-date) - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + 1Y + 1 rok - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + 5Y + 5 lat - apps/client/src/app/pages/public/public-page.html - 106 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Countries - Kraje + + Max + Maksimum - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + libs/ui/src/lib/assistant/assistant.component.ts + 401 + + + Grant access + Przyznaj dostęp - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 7 + + + Public + Publiczny - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 25 - - Benchmark - Benchmark + + Granted Access + Przyznano dostęp - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/components/user-account-access/user-account-access.html + 57 - - Symbol Mapping - Mapowanie Symboli + + Please enter your coupon code. + Wpisz kod kuponu: - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 - - Scraper Configuration - Konfiguracja Scrapera + + Could not redeem coupon code + Nie udało się zrealizować kodu kuponu - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 - - Note - Notatka + + Coupon code has been redeemed + Kupon został zrealizowany - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 + + + Reload + Odśwież - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 78 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 + + + per year + rocznie - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 - - - Add Asset Profile - Dodaj Profil Aktywa - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 7 + apps/client/src/app/pages/pricing/pricing-page.html + 283 - - Search - Szukaj + + Try Premium + Wypróbuj Premium - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 - - Add Manually - Dodaj Ręcznie + + Redeem Coupon + Wykorzystaj kupon - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 - - Name, symbol or ISIN - Nazwa, symbol lub ISIN + + Auto + Auto - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 29 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 - - Please add a currency: - Proszę dodać walutę: + + Do you really want to remove this sign in method? + Czy na pewno chcesz usunąć tą metode logowania? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 - - Do you really want to delete this coupon? - Czy naprawdę chcesz usunąć ten kupon? + + Presenter View + Widok Prezentera - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 - - Do you really want to delete this currency? - Czy naprawdę chcesz usunąć tę walutę? + + Protection for sensitive information like absolute performances and quantity values + Ochrona dla wrażliwych informacji takich jak wyniki i wartości ilościowe - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 - - Do you really want to delete this system message? - Czy naprawdę chcesz usunąć tę wiadomość systemową? + + Base Currency + Waluta Bazowa - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 - - Do you really want to flush the cache? - Czy naprawdę chcesz wyczyścić pamięć podręczną? + + Language + Język - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 - - Please set your system message: - Proszę ustawić swoją wiadomość systemową: + + Locale + Ustawienia Regionalne - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 - - - Version - Wersja - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 - - User Count - Liczba Użytkowników + + Date and number format + Format daty i liczb - apps/client/src/app/components/admin-overview/admin-overview.html - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 - - Activity Count - Liczba Aktywności + + Appearance + Wygląd (tryb) - apps/client/src/app/components/admin-overview/admin-overview.html - 19 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 - - per User - na Użytkownika + + Light + Jasny - apps/client/src/app/components/admin-overview/admin-overview.html - 28 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 - - Exchange Rates - Kursy Walut + + Dark + Ciemny - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 - - Add Currency - Dodaj Walutę + + Zen Mode + Tryb Zen - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 22 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 - apps/client/src/app/components/admin-overview/admin-overview.html - 105 + apps/client/src/app/pages/features/features-page.html + 246 - - User Signup - Rejestracja Użytkownika + + Distraction-free experience for turbulent times + Doświadczenie bez zakłóceń w niespokojnych czasach - apps/client/src/app/components/admin-overview/admin-overview.html - 111 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 - - Read-only Mode - Tryb Tylko do Odczytu + + Biometric Authentication + Uwierzytelnianie Biometryczne - apps/client/src/app/components/admin-overview/admin-overview.html - 125 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 - - System Message - Wiadomość Systemowa + + Sign in with fingerprint + Logowanie za pomocą linii papilarnych - apps/client/src/app/components/admin-overview/admin-overview.html - 149 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 - - Set Message - Ustaw Wiadomość + + Experimental Features + Funkcje Eksperymentalne - apps/client/src/app/components/admin-overview/admin-overview.html - 171 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 - - Coupons - Kupony + + Sneak peek at upcoming functionality + Podgląd nadchodzących funkcjonalności - apps/client/src/app/components/admin-overview/admin-overview.html - 179 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 - - Add - Dodaj + + User ID + ID Użytkownika - apps/client/src/app/components/admin-overview/admin-overview.html - 239 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 - libs/ui/src/lib/account-balances/account-balances.component.html - 93 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 - - Housekeeping - Konserwacja + + Export Data + Eksportuj Dane - apps/client/src/app/components/admin-overview/admin-overview.html - 247 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 - - Flush Cache - Wyczyszczenie pamięci podręcznej + + This feature is currently unavailable. + Ta funkcja jest obecnie niedostępna. - apps/client/src/app/components/admin-overview/admin-overview.html - 251 + apps/client/src/app/core/http-response.interceptor.ts + 55 - - Add Platform - Dodaj Platformę + + Please try again later. + Spróbuj ponownie później. - apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + apps/client/src/app/core/http-response.interceptor.ts + 57 - - - Url - Url - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + apps/client/src/app/core/http-response.interceptor.ts + 88 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 + + + Oops! Something went wrong. + Ups! Coś poszło nie tak. - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 25 + apps/client/src/app/core/http-response.interceptor.ts + 86 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 - - Accounts - Konta + + Okay + Okej - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/core/http-response.interceptor.ts + 89 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 + + + + About + O Ghostfolio + + apps/client/src/app/app.component.html + 70 apps/client/src/app/components/header/header.component.html - 263 + 124 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + apps/client/src/app/components/header/header.component.html + 375 - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - - - Do you really want to delete this platform? - Czy naprawdę chcesz usunąć tę platformę? - apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 220 - - Update platform - Aktualizuj platformę + + Changelog + Changelog - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 8 + apps/client/src/app/app.component.html + 77 - - - Add platform - Dodaj platformę - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 10 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 - - - Platforms - Platformy - apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + libs/common/src/lib/routes/routes.ts + 185 - - Tags - Tagi + + License + Licencja - apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + apps/client/src/app/pages/about/license/license-page.html + 4 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/common/src/lib/routes/routes.ts + 193 + + + Privacy Policy + Polityka Prywatności - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + apps/client/src/app/app.component.html + 105 - - - Add Tag - Dodaj Tag - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 - - - Do you really want to delete this tag? - Czy naprawdę chcesz usunąć ten tag? - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 209 - - Update tag - Aktualizuj tag + + Our + Nasi - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 - - Add tag - Dodaj tag + + Discover other exciting Open Source Software projects + Odkryj inne fascynujące projekty Open Source - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 - - Do you really want to delete this user? - Czy na pewno chcesz usunąć tego użytkownika? + + Visit + Odwiedz - apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 - - User - Użytkownik + + Accounts + Konta - apps/client/src/app/components/admin-users/admin-users.html - 29 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - Registration - Rejestracja apps/client/src/app/components/admin-users/admin-users.html - 97 + 115 - - - Engagement per Day - Zaangażowanie na Dzień - apps/client/src/app/components/admin-users/admin-users.html - 157 + apps/client/src/app/components/header/header.component.html + 58 - - - Last Request - Ostatnie Żądanie - apps/client/src/app/components/admin-users/admin-users.html - 202 + apps/client/src/app/components/header/header.component.html + 268 - - - Impersonate User - Wciel się w Użytkownika - apps/client/src/app/components/admin-users/admin-users.html - 239 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 - - - Delete User - Usuń Użytkownika - apps/client/src/app/components/admin-users/admin-users.html - 251 - - - - Performance - Wydajność - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 + apps/client/src/app/pages/accounts/accounts-page.html + 4 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + libs/common/src/lib/routes/routes.ts + 69 - - Compare with... - Porównaj z... + + Oops, cash balance transfer has failed. + Ups, transfer salda nie powiódł się. - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 18 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 - - Manage Benchmarks - Zarządzanie Benchmarkami + + Update account + Uaktualnij konto - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 35 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 - - Portfolio - Portfel + + Add account + Dodaj konto - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 + + + Account ID + ID konta - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 + + + From + Z - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - Benchmark - Poziom Odniesienia (Benchmark) + + To + Do - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 - - Current Market Mood - Obecny Nastrój Rynkowy + + Transfer + Transfer - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Overview - Przegląd + + Admin Control + Panel Administratora apps/client/src/app/components/header/header.component.html - 28 + 74 apps/client/src/app/components/header/header.component.html - 245 + 289 + + + libs/common/src/lib/routes/routes.ts + 64 - - Portfolio - Portfel + + Market Data + Dane Rynkowe - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/components/header/header.component.html - 255 + libs/common/src/lib/routes/routes.ts + 51 - - Admin Control - Nadzór Administratora + + Settings + Ustawienia - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/components/header/header.component.html - 279 + libs/common/src/lib/routes/routes.ts + 34 - - - Me - Ja - apps/client/src/app/components/header/header.component.html - 211 + libs/common/src/lib/routes/routes.ts + 56 - - User - Użytkownik + + Users + Użytkownicy - apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + libs/common/src/lib/routes/routes.ts + 61 + + + Overview + Przegląd apps/client/src/app/components/header/header.component.html - 229 + 30 - - - My Ghostfolio - Moje Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 248 - - - About Ghostfolio - O Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/admin/admin-page.component.ts + 48 - - - Sign in - Zaloguj się - apps/client/src/app/components/header/header.component.html - 412 + apps/client/src/app/pages/resources/resources-page.component.ts + 30 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + libs/common/src/lib/routes/routes.ts + 113 - - - Get started - Rozpocznij - apps/client/src/app/components/header/header.component.html - 422 + libs/common/src/lib/routes/routes.ts + 170 - - Sign in - Zaloguj się + + Blog + Blog - apps/client/src/app/app-routing.module.ts - 150 + apps/client/src/app/app.component.html + 74 - apps/client/src/app/components/header/header.component.ts - 230 + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 - - - Oops! Incorrect Security Token. - Ups! Nieprawidłowy token bezpieczeństwa. - apps/client/src/app/components/header/header.component.ts - 245 + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 - - - Manage Activities - Zarządzaj Aktywnościami - apps/client/src/app/components/home-holdings/home-holdings.html - 63 + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 - - - Fear - Zagrożenie - apps/client/src/app/components/home-market/home-market.component.ts - 27 + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 - libs/ui/src/lib/i18n.ts - 98 + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 - - - Greed - Zachłanność - apps/client/src/app/components/home-market/home-market.component.ts - 28 + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 - libs/ui/src/lib/i18n.ts - 99 + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 - - - Last Days - Ostatnie Dni - apps/client/src/app/components/home-market/home-market.html - 7 + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 - - - Welcome to Ghostfolio - Witaj w Ghostfolio - apps/client/src/app/components/home-overview/home-overview.html - 7 + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 - - - Ready to take control of your personal finances? - Jesteś gotów przejąć kontrolę nad swoimi finansami osobistymi? - apps/client/src/app/components/home-overview/home-overview.html - 8 + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 - - - Setup your accounts - Skonfiguruj swoje konta - apps/client/src/app/components/home-overview/home-overview.html - 15 + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 - - - Get a comprehensive financial overview by adding your bank and brokerage accounts. - Uzyskaj kompleksowy przegląd finansowy, poprzez dodanie swoich rachunków bankowych i maklerskich. - apps/client/src/app/components/home-overview/home-overview.html - 17 + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 - - - Capture your activities - Rejestruj swoje działania - apps/client/src/app/components/home-overview/home-overview.html - 24 + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 - - - Record your investment activities to keep your portfolio up to date. - Dokumentuj swoje działania inwestycyjne, aby zapewnić aktualność portfela. - apps/client/src/app/components/home-overview/home-overview.html - 26 + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 - - - Monitor and analyze your portfolio - Monitoruj i analizuj swój portfel - apps/client/src/app/components/home-overview/home-overview.html - 33 + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 - - - Track your progress in real-time with comprehensive analysis and insights. - Śledź swój postęp w czasie rzeczywistym dzięki kompleksowym analizom i obserwacjom. - apps/client/src/app/components/home-overview/home-overview.html - 35 + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 - - - Setup accounts - Konfiguracja kont - apps/client/src/app/components/home-overview/home-overview.html - 44 + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 - - - Add activity - Dodaj działalność - apps/client/src/app/components/home-overview/home-overview.html - 52 + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 8 + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 - - - Summary - Podsumowanie - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 - - - Total Amount - Całkowita Kwota - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + apps/client/src/app/pages/blog/blog-page.html + 5 - - - Savings Rate - Stopa Oszczędności - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + libs/common/src/lib/routes/routes.ts + 225 - - Security Token - Token Bezpieczeństwa + + Discover the latest Ghostfolio updates and insights on personal finance + Odkryj najnowsze aktualizacje Ghostfolio oraz spostrzeżenia na temat finansów osobistych - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 + apps/client/src/app/pages/blog/blog-page.html + 7 + + + As you are already logged in, you cannot access the demo account. + Ponieważ jesteś już zalogowany, nie możesz uzyskać dostępu do konta demo. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 + apps/client/src/app/pages/demo/demo-page.component.ts + 35 + + + Frequently Asked Questions (FAQ) + Często zadawane pytania (FAQ) - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/app.component.html + 83 - - - or - lub - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 - apps/client/src/app/pages/landing/landing-page.html - 47 + libs/common/src/lib/routes/routes.ts + 251 + + + Features + Funkcje - apps/client/src/app/pages/landing/landing-page.html - 450 + apps/client/src/app/app.component.html + 79 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 + apps/client/src/app/components/header/header.component.html + 361 - apps/client/src/app/pages/register/register-page.html - 30 + apps/client/src/app/pages/features/features-page.html + 5 - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + libs/common/src/lib/routes/routes.ts + 256 - - Sign in with Internet Identity - Zaloguj się przy użyciu Tożsamości Internetowej (Internet Identity) + + Check out the numerous features of Ghostfolio to manage your wealth + Przetestuj liczne funkcje Ghostfolio służące zarządzaniu twoim majątkiem - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 + apps/client/src/app/pages/features/features-page.html + 7 - - Sign in with Google - Zaloguj się przez Google + + ETFs + ETFy - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 + apps/client/src/app/pages/features/features-page.html + 25 - - Stay signed in - Pozostań zalogowany + + Bonds + Obligacje - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 + apps/client/src/app/pages/features/features-page.html + 38 - - Time in Market - Czas na Rynku + + Wealth Items + Cenne przedmioty - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 + apps/client/src/app/pages/features/features-page.html + 76 - - Buy - Kupno + + Import and Export + Import i Export - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + apps/client/src/app/pages/features/features-page.html + 116 - - Sell - Sprzedaż + + Multi-Accounts + Wiele kont - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + apps/client/src/app/pages/features/features-page.html + 127 - - Investment - Inwestycja + + Portfolio Calculations + Kalkulacje portfela - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 + apps/client/src/app/pages/features/features-page.html + 141 + + + Dark Mode + Ciemny motyw - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 + apps/client/src/app/pages/features/features-page.html + 233 - - Absolute Gross Performance - Bezwzględne Osiągi Brutto + + Market Mood + Nastrój rynku - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 + apps/client/src/app/pages/features/features-page.html + 215 - - Fees - Opłaty + + Static Analysis + Analiza statyczna - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + apps/client/src/app/pages/features/features-page.html + 179 + + + Multi-Language + Wielo-językowość - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 84 + apps/client/src/app/pages/features/features-page.html + 259 + + + Open Source Software + Oprogramowanie Open Source - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + apps/client/src/app/pages/features/features-page.html + 295 - - Absolute Net Performance - Bezwzględne Osiągi Netto + + Get Started + Rozpocznij - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 + apps/client/src/app/pages/features/features-page.html + 320 - - - Net Performance - Osiągi Netto - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/pages/public/public-page.html + 220 - - Total Assets - Suma Aktywów + + Holdings + Inwestycje - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 143 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - - - Valuables - Kosztowności - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - - - Emergency Fund - Fundusz Rezerwowy - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 + apps/client/src/app/pages/public/public-page.html + 70 - apps/client/src/app/pages/features/features-page.html - 89 + libs/common/src/lib/routes/routes.ts + 90 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 + libs/common/src/lib/routes/routes.ts + 167 - - Cash - Gotówka + + Summary + Podsumowanie - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/components/home-summary/home-summary.html + 2 - - - Assets - Aktywa - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + libs/common/src/lib/routes/routes.ts + 105 - - Buying Power - Siła Nabywcza - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 - - - - Excluded from Analysis - Wykluczone z Analizy + + Markets + Rynki - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + apps/client/src/app/app.component.html + 61 - - - Liabilities - Pasywa (Zobowiązania Finansowe) - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/features/features-page.html - 102 + apps/client/src/app/components/home-market/home-market.html + 2 - - - Net Worth - Wartość Netto - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + apps/client/src/app/components/markets/markets.html + 2 - - - Annualized Performance - Osiągi w Ujęciu Rocznym - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 - - - Interest - Odsetki - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/resources/resources-page.component.ts + 40 - - - Dividend - Dywidenda - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 + libs/common/src/lib/routes/routes.ts + 100 - apps/client/src/app/pages/features/features-page.html - 63 + libs/common/src/lib/routes/routes.ts + 261 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + libs/common/src/lib/routes/routes.ts + 309 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio to osobisty panel finansowy do śledzenia Twojego majątku netto, w tym gotówki, akcji, funduszy ETF i kryptowalut na wielu platformach. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + apps/client/src/app/pages/i18n/i18n-page.html + 5 - - Please set the amount of your emergency fund. - Wprowadź wysokość funduszu rezerwowego: + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + aplikacja, aktywa, kryptowaluta, dashboard, etf, finanse, zarządzanie, wydajność, portfolio, oprogramowanie, akcje, handel, majątek, web3 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + apps/client/src/app/pages/i18n/i18n-page.html + 10 - - Change - Zmień + + Open Source Wealth Management Software + Oprogramowanie Open Source do Zarządzania Majątkiem - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + apps/client/src/app/pages/i18n/i18n-page.html + 224 - - Average Unit Price - Średnia Cena Jednostkowa + + Manage your wealth like a boss + Zarządzaj swoim majątkiem niczym Boss - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + apps/client/src/app/pages/landing/landing-page.html + 6 - - Minimum Price - Cena Minimalna + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio to zapewniający prywatność, open source’owy panel do zarządzania finansami osobistymi. Przeanalizuj szczegółowo swoją alokację aktywów, określ swoją wartość netto i podejmuj przemyślane decyzje inwestycyjne oparte na danych. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + apps/client/src/app/pages/landing/landing-page.html + 10 - - Maximum Price - Cena Maksymalna + + Get Started + Rozpocznij - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + apps/client/src/app/pages/landing/landing-page.html + 42 - - - Quantity - Ilość - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + apps/client/src/app/pages/landing/landing-page.html + 447 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + apps/client/src/app/pages/pricing/pricing-page.html + 351 - libs/ui/src/lib/activities-table/activities-table.component.html - 186 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - - Report Data Glitch - Zgłoś Błąd Danych + + Monthly Active Users + Aktywni Użytkownicy w Miesiącu - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + apps/client/src/app/pages/landing/landing-page.html + 70 - - Are you an ambitious investor who needs the full picture? - Jesteś ambitnym inwestorem, który potrzebuje pełnego obrazu swojej działalności? + + Stars on GitHub + Gwiazdki na GitHubie - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + apps/client/src/app/pages/landing/landing-page.html + 88 - - - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - Przejdź na Ghostfolio Premium już dziś i uzyskaj dostęp do ekskluzywnych funkcji, które wzbogacą Twoje doświadczenie inwestycyjne: - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + apps/client/src/app/pages/open/open-page.html + 103 - - Portfolio Summary - Podsumowanie Portfela + + Pulls on Docker Hub + Pobrania na Docker Hub - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 24 + apps/client/src/app/pages/landing/landing-page.html + 106 - apps/client/src/app/pages/pricing/pricing-page.html - 57 + apps/client/src/app/pages/open/open-page.html + 117 + + + As seen in + Dostrzegli Nas - apps/client/src/app/pages/pricing/pricing-page.html - 213 + apps/client/src/app/pages/landing/landing-page.html + 115 - - Portfolio Allocations - Podział portfela + + Protect your assets. Refine your personal investment strategy. + Chroń swoje zasoby. Udoskonal swoją osobistą strategię inwestycyjną. - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 28 + apps/client/src/app/pages/landing/landing-page.html + 226 + + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio umożliwia zapracowanym osobom śledzenie akcji, funduszy ETF lub kryptowalut, jednocześnie zachowując prywatność. - apps/client/src/app/pages/features/features-page.html - 161 + apps/client/src/app/pages/landing/landing-page.html + 230 + + + 360° View + Widok 360° - apps/client/src/app/pages/pricing/pricing-page.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 240 + + + Get the full picture of your personal finances across multiple platforms. + Uzyskaj pełny obraz swoich finansów osobistych na wielu różnych platformach. - apps/client/src/app/pages/pricing/pricing-page.html - 217 + apps/client/src/app/pages/landing/landing-page.html + 243 - - Performance Benchmarks - Wskaźniki wydajności + + Web3 Ready + Gotowy na Web3 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 32 + apps/client/src/app/pages/landing/landing-page.html + 251 + + + Use Ghostfolio anonymously and own your financial data. + Korzystaj z Ghostfolio anonimowo i zachowaj pełną kontrolę nad swoimi danymi finansowymi. - apps/client/src/app/pages/pricing/pricing-page.html - 65 + apps/client/src/app/pages/landing/landing-page.html + 254 + + + Benefit from continuous improvements through a strong community. + Czerp korzyści z nieustannych ulepszeń dzięki silnej społeczności. - apps/client/src/app/pages/pricing/pricing-page.html - 221 + apps/client/src/app/pages/landing/landing-page.html + 264 - - FIRE Calculator - Kalkulator FIRE + + Why Ghostfolio? + Dlaczego Ghostfolio? - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 36 + apps/client/src/app/pages/landing/landing-page.html + 272 + + + Ghostfolio is for you if you are... + Ghostfolio jest dla Ciebie, jeśli... - apps/client/src/app/pages/pricing/pricing-page.html - 69 + apps/client/src/app/pages/landing/landing-page.html + 274 + + + trading stocks, ETFs or cryptocurrencies on multiple platforms + handlujesz akcjami, funduszami ETF lub kryptowalutami na wielu platformach - apps/client/src/app/pages/pricing/pricing-page.html - 225 + apps/client/src/app/pages/landing/landing-page.html + 280 - - Professional Data Provider - Profesjonalne źródło danych + + pursuing a buy & hold strategy + realizujesz strategię buy & hold - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 40 + apps/client/src/app/pages/landing/landing-page.html + 286 + + + interested in getting insights of your portfolio composition + chcesz uzyskać wgląd w strukturę swojego portfolio - apps/client/src/app/pages/pricing/pricing-page.html - 240 + apps/client/src/app/pages/landing/landing-page.html + 291 - - and more Features... - i więcej Funkcji ... + + valuing privacy and data ownership + cenisz sobie prywatność i własność swoich danych - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 44 + apps/client/src/app/pages/landing/landing-page.html + 296 + + + into minimalism + lubisz minimalizm - apps/client/src/app/pages/pricing/pricing-page.html - 85 + apps/client/src/app/pages/landing/landing-page.html + 299 + + + caring about diversifying your financial resources + zależy Ci na dywersyfikacji swoich zasobów finansowych - apps/client/src/app/pages/pricing/pricing-page.html - 252 + apps/client/src/app/pages/landing/landing-page.html + 303 - - Get the tools to effectively manage your finances and refine your personal investment strategy. - Uzyskaj narzędzia do skutecznego zarządzania swoimi finansami i udoskonal swoją osobistą strategię inwestycyjną. + + interested in financial independence + jesteś zainteresowany niezależnością finansową - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + apps/client/src/app/pages/landing/landing-page.html + 307 - - Skip - Pomiń + + saying no to spreadsheets in + mówisz „nie” arkuszom kalkulacyjnym w roku - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + apps/client/src/app/pages/landing/landing-page.html + 311 - - Upgrade Plan - Ulepsz Plan + + still reading this list + nadal czytasz tę listę - apps/client/src/app/components/header/header.component.html - 185 + apps/client/src/app/pages/landing/landing-page.html + 314 + + + Learn more about Ghostfolio + Dowiedz się więcej o Ghostfolio - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 319 + + + What our users are saying + Co mówią nasi użytkownicy - apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + apps/client/src/app/pages/landing/landing-page.html + 328 + + + Members from around the globe are using Ghostfolio Premium + Użytkownicy z całego świata korzystają z Ghostfolio Premium - apps/client/src/app/pages/pricing/pricing-page.html - 288 + apps/client/src/app/pages/landing/landing-page.html + 367 - - Today - Dziś + + How does Ghostfolio work? + Jak działa Ghostfolio ? - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/landing/landing-page.html + 384 + + + Get started in only 3 steps + Rozpocznij w zaledwie 3 krokach - libs/ui/src/lib/assistant/assistant.component.ts - 221 + apps/client/src/app/pages/landing/landing-page.html + 386 - - YTD - Liczony od początku roku (year-to-date) + + Sign up anonymously* + Zarejestruj się anonimowo* - apps/client/src/app/components/toggle/toggle.component.ts - 22 + apps/client/src/app/pages/landing/landing-page.html + 392 + + + * no e-mail address nor credit card required + * nie jest wymagany ani adres e-mail, ani karta kredytowa - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/pages/landing/landing-page.html + 394 - - 1Y - 1 rok + + Add any of your historical transactions + Dodaj dowolne z Twoich historycznych transakcji - apps/client/src/app/components/toggle/toggle.component.ts - 23 + apps/client/src/app/pages/landing/landing-page.html + 406 + + + Get valuable insights of your portfolio composition + Zyskaj cenny wgląd w strukturę swojego portfolio - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/landing/landing-page.html + 418 - - 5Y - 5 lat + + Are you ready? + Czy jesteś gotów? - apps/client/src/app/components/toggle/toggle.component.ts - 24 + apps/client/src/app/pages/landing/landing-page.html + 432 + + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + W Ghostfolio przejrzystość stanowi podstawę naszych wartości. Publikujemy kod źródłowy jako oprogramowanie open source (OSS) na licencji AGPL-3.0 i otwarcie udostępniamy zagregowane kluczowe wskaźniki dotyczące stanu operacyjnego platformy. - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/pages/open/open-page.html + 7 - - Max - Maksimum + + (Last 24 hours) + (Ostatnie 24 godziny) - apps/client/src/app/components/toggle/toggle.component.ts - 25 + apps/client/src/app/pages/open/open-page.html + 37 + + + Active Users + Aktywni Użytkownicy - libs/ui/src/lib/assistant/assistant.component.ts - 260 + apps/client/src/app/pages/open/open-page.html + 40 - - - Grant access - Przyznaj dostęp - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 7 + apps/client/src/app/pages/open/open-page.html + 62 - - Public - Publiczny + + (Last 30 days) + (Ostatnie 30 dni) - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 25 + apps/client/src/app/pages/open/open-page.html + 48 + + + apps/client/src/app/pages/open/open-page.html + 59 - - Granted Access - Przyznano dostęp + + New Users + Nowi Użytkownicy - apps/client/src/app/components/user-account-access/user-account-access.html - 7 + apps/client/src/app/pages/open/open-page.html + 51 - - Please enter your coupon code: - Wpisz kod kuponu: + + Users in Slack community + Użytkownicy w społeczności Slack - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + apps/client/src/app/pages/open/open-page.html + 75 - - Could not redeem coupon code - Nie udało się zrealizować kodu kuponu + + Contributors on GitHub + Współtwórcy na GitHubie – osoby zaangażowane w rozwój projektu - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + apps/client/src/app/pages/open/open-page.html + 89 - - Coupon code has been redeemed - Kupon został zrealizowany + + (Last 90 days) + (Ostatnie 90 dni) - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + apps/client/src/app/pages/open/open-page.html + 127 - - Reload - Odśwież + + Uptime + Czas Sprawności - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + apps/client/src/app/pages/open/open-page.html + 132 - - per year - rocznie + + Activities + Aktywności - apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/pages/pricing/pricing-page.html - 274 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 - - - Try Premium - Wypróbuj Premium - apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 - - - Redeem Coupon - Wykorzystaj kupon - apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 - - - Auto - Auto - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - - - Do you really want to remove this sign in method? - Czy na pewno chcesz usunąć tą metode logowania? - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 + apps/client/src/app/components/admin-users/admin-users.html + 136 - - - Settings - Ustawienia - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Presenter View - Widok Prezentera - apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - - - Protection for sensitive information like absolute performances and quantity values - Ochrona dla wrażliwych informacji takich jak wyniki i wartości ilościowe - apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 - - - Base Currency - Waluta Bazowa - apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + libs/common/src/lib/routes/routes.ts + 128 - - Language - Język + + Do you really want to delete these activities? + Czy na pewno chcesz usunąć te aktywności? - apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 - - Locale - Ustawienia Regionalne + + Update activity + Aktualizuj aktywność - apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 - - Date and number format - Format daty i liczb + + Stocks, ETFs, bonds, cryptocurrencies, commodities + Akcje, fundusze ETF, obligacje, kryptowaluty, towary - apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 - - - Appearance - Wygląd (tryb) - apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 65 - - Auto - Auto + + One-time fee, annual account fees + Opłata jednorazowa, roczne opłaty za konto - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - Light - Jasny + + Distribution of corporate earnings + Rozkład zysków przedsiębiorstw - apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 - - Dark - Ciemny + + Revenue for lending out money + Przychód z tytułu pożyczania pieniędzy - apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 - - Zen Mode - Tryb Zen - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 - + + Mortgages, personal loans, credit cards + Kredyty hipoteczne, kredyty indywidualne, karty kredytowe - apps/client/src/app/pages/features/features-page.html - 191 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 - - Distraction-free experience for turbulent times - Doświadczenie bez zakłóceń w niespokojnych czasach + + Luxury items, real estate, private companies + Towar luksusowy, nieruchomości, firmy prywatne - apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 - - Biometric Authentication - Uwierzytelnianie Biometryczne + + Update Cash Balance + Zaktualizuj Saldo Gotówkowe - apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 - - Sign in with fingerprint - Logowanie za pomocą linii papilarnych + + Unit Price + Cena Jednostkowa - apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 - - - Experimental Features - Funkcje Eksperymentalne - apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + libs/ui/src/lib/activities-table/activities-table.component.html + 210 - - Sneak peek at upcoming functionality - Podgląd nadchodzących funkcjonalności + + Import Activities + Importuj Aktywności - apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 - - - User ID - ID Użytkownika - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 45 + libs/ui/src/lib/activities-table/activities-table.component.html + 9 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - - Export Data - Eksportuj Dane + + Import Dividends + Impotruj Dywidendy - apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 129 - - - This feature is currently unavailable. - Ta funkcja jest obecnie niedostępna. - apps/client/src/app/core/http-response.interceptor.ts - 53 + libs/ui/src/lib/activities-table/activities-table.component.html + 29 - - - Please try again later. - Spróbuj ponownie później. - apps/client/src/app/core/http-response.interceptor.ts - 55 + libs/ui/src/lib/activities-table/activities-table.component.html + 383 + + + Importing data... + Importowanie danych... - apps/client/src/app/core/http-response.interceptor.ts - 80 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 167 + + + Import has been completed + Importowanie zakończone apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + 176 - - Oops! Something went wrong. - Ups! Coś poszło nie tak. + + Validating data... + Weryfikacja danych... - apps/client/src/app/core/http-response.interceptor.ts - 78 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 + + + Select Holding + Wybierz Inwestycje - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 - - Okay - Okej + + Select File + Wybierz plik - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 22 + + + Holding + Inwestycja - apps/client/src/app/core/http-response.interceptor.ts - 81 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + libs/ui/src/lib/assistant/assistant.html + 179 - - About - O Ghostfolio + + Load Dividends + Załaduj dywidendy - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 + + + Choose or drop a file here + Wybierz lub przeciągnij plik tutaj - apps/client/src/app/pages/about/about-page.component.ts - 44 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + The following file formats are supported: + Obsługiwane są następujące formaty plików: - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 - - Changelog - Changelog + + Select Dividends + Wybierz dywidendy - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 + + + Select Activities + Wybór działań - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 - - License - Licencja + + Back + Wróc - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 - - Privacy Policy - Polityka Prywatności + + Allocations + Podziały - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - - - Our - Nasi - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + libs/common/src/lib/routes/routes.ts + 133 - - Discover other exciting Open Source Software projects - Odkryj inne fascynujące projekty Open Source + + Proportion of Net Worth + Proporcja wartości netto - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 - - Visit - Odwiedz + + By Platform + Wg. platformy - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 44 - - Accounts - Konta + + By Currency + Wg. waluty - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 - - Oops, cash balance transfer has failed. - Ups, transfer salda nie powiódł się. + + By Asset Class + Wg. klasy aktywów - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 - - Update account - Uaktualnij konto + + By Holding + Wg. inwestycji - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 - - Add account - Dodaj konto + + By Sector + Wg. sektora - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 - - Account ID - ID konta + + By Continent + Wg. kontynentu - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 96 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 - - From - Z + + By Market + Wg. rynku - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 175 - - To - Do + + Regions + Regiony - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 - - - Transfer - Transfer - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/public/public-page.html + 143 - - Admin Control - Panel Administratora + + Developed Markets + Rynki Rozwinięte - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 + + + apps/client/src/app/pages/public/public-page.html + 160 - - Market Data - Dane Rynkowe + + Emerging Markets + Rynki Wschodzące - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + apps/client/src/app/pages/public/public-page.html + 169 - - Settings - Ustawienia + + Other Markets + Inne Rynki - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 - apps/client/src/app/pages/admin/admin-page.component.ts - 32 + apps/client/src/app/pages/public/public-page.html + 178 + + + By Account + Wg. kont - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 + + + By ETF Provider + Wg. Dostawcy ETF - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 - - Users - Użytkownicy + + By Country + Wg. kraju - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 + + + + Analysis + Analiza + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 138 - - Overview - Przegląd + + Dividend + Dywidenda - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 - apps/client/src/app/pages/resources/resources-page.component.ts - 16 + apps/client/src/app/pages/features/features-page.html + 63 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 - - - Blog - Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 36 - - Discover the latest Ghostfolio updates and insights on personal finance - Odkryj najnowsze aktualizacje Ghostfolio oraz spostrzeżenia na temat finansów osobistych + + Deposit + Depozyt - apps/client/src/app/pages/blog/blog-page.html - 7 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 - - As you are already logged in, you cannot access the demo account. - Ponieważ jesteś już zalogowany, nie możesz uzyskać dostępu do konta demo. + + Monthly + Miesięcznie - apps/client/src/app/pages/demo/demo-page.component.ts - 35 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 - - Frequently Asked Questions (FAQ) - Często zadawane pytania (FAQ) + + Yearly + Rocznie - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 + + + Top + Największe wzrosty - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 - - Frequently Asked Questions (FAQ) - Często zadawane pytania (FAQ) + + Bottom + Największy spadek - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + + Portfolio Evolution + Rozwój portfela - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 + + + Investment Timeline + Oś czasu inwestycji - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 - - Features - Funkcje + + Current Streak + Obecna passa - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 - - Check out the numerous features of Ghostfolio to manage your wealth - Przetestuj liczne funkcje Ghostfolio służące zarządzaniu twoim majątkiem + + Longest Streak + Najdłuższa passa - apps/client/src/app/pages/features/features-page.html - 6 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 - - Stocks - Akcje + + Dividend Timeline + Oś czasu dywidend - apps/client/src/app/pages/features/features-page.html - 15 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 - - ETFs - ETFy + + FIRE + F.I.R.E. - apps/client/src/app/pages/features/features-page.html - 25 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 4 - - Bonds - Obligacje + + Calculator + Kalkulator - apps/client/src/app/pages/features/features-page.html - 38 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 - - Cryptocurrencies - Kryptowaluty + + 4% Rule + Zasada 4% - apps/client/src/app/pages/features/features-page.html - 51 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 - - Wealth Items - Cenne przedmioty + + Currency Cluster Risks + Ryzyko związane z klastrem walutowym - apps/client/src/app/pages/features/features-page.html - 76 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 - - Import and Export - Import i Export + + Account Cluster Risks + Ryzyko związane z klastrem kont - apps/client/src/app/pages/features/features-page.html - 115 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 - - Multi-Accounts - Wiele kont + + Holdings + Inwestycje - apps/client/src/app/pages/features/features-page.html - 127 + libs/ui/src/lib/assistant/assistant.html + 82 - - Portfolio Calculations - Kalkulacje portfela + + Pricing + Cennik - apps/client/src/app/pages/features/features-page.html - 141 + apps/client/src/app/app.component.html + 99 - - - Dark Mode - Ciemny motyw - apps/client/src/app/pages/features/features-page.html - 178 + apps/client/src/app/components/header/header.component.html + 105 - - - Market Mood - Nastrój rynku - apps/client/src/app/pages/features/features-page.html - 206 + apps/client/src/app/components/header/header.component.html + 313 - - - Static Analysis - Analiza statyczna - apps/client/src/app/pages/features/features-page.html - 225 + apps/client/src/app/components/header/header.component.html + 389 - - - Multi-Language - Wielo-językowość - apps/client/src/app/pages/features/features-page.html - 242 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts + 13 - - - Open Source Software - Oprogramowanie Open Source - apps/client/src/app/pages/features/features-page.html - 278 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 - - - Get Started - Rozpocznij - apps/client/src/app/pages/features/features-page.html - 303 + libs/common/src/lib/routes/routes.ts + 271 + + + Pricing Plans + Plany cenowe - apps/client/src/app/pages/public/public-page.html - 220 + apps/client/src/app/pages/pricing/pricing-page.html + 4 - - Holdings - Inwestycje + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Nasza oficjalna chmurowa usługa Ghostfolio Premium jest najprostszym sposobem by rozpocząć przygodę z Ghostfolio. To najlepsza opcja dla większości osób ze względu na czas, jaki można dzięki niej zaoszczędzić. Uzyskany przychód jest wykorzystywany do pokrycia kosztów infrastruktury hostingowej i finansowania bieżącego rozwoju. - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 + apps/client/src/app/pages/pricing/pricing-page.html + 7 + + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Jeżeli wolisz uruchomić Ghostfolio na własnej infrastrukturze, możesz znaleźć kod źródłowy i dalsze instrukcje na naszym GitHubie. - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + apps/client/src/app/pages/pricing/pricing-page.html + 14 + + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + Dla inwestorów obeznanych technicznie, którzy wolą uruchomić Ghostfolio na własnej infrastrukturze. - apps/client/src/app/pages/home/home-page.component.ts - 42 + apps/client/src/app/pages/pricing/pricing-page.html + 26 + + + Unlimited Transactions + Nieograniczona Liczba Transakcji - apps/client/src/app/pages/zen/zen-page.component.ts - 39 + apps/client/src/app/pages/pricing/pricing-page.html + 32 - - - Summary - Podsumowanie - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/pages/pricing/pricing-page.html + 121 - apps/client/src/app/pages/home/home-page.component.ts - 47 + apps/client/src/app/pages/pricing/pricing-page.html + 193 - - Markets - Rynki + + Unlimited Accounts + Nieograniczona Liczba Rachunków - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/pages/pricing/pricing-page.html + 36 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/pages/pricing/pricing-page.html + 125 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 197 + + + Portfolio Performance + Wyniki portfela - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/pages/pricing/pricing-page.html + 40 - apps/client/src/app/pages/resources/resources-page.component.ts - 26 + apps/client/src/app/pages/pricing/pricing-page.html + 129 - - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio to osobisty panel finansowy do śledzenia Twojego majątku netto, w tym gotówki, akcji, funduszy ETF i kryptowalut na wielu platformach. - apps/client/src/app/pages/i18n/i18n-page.html - 4 + apps/client/src/app/pages/pricing/pricing-page.html + 201 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - aplikacja, aktywa, kryptowaluta, dashboard, etf, finanse, zarządzanie, wydajność, portfolio, oprogramowanie, akcje, handel, majątek, web3 + + Data Import and Export + Importowanie i Eksportowanie Danych - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 60 - - - Open Source Wealth Management Software - Oprogramowanie Open Source do Zarządzania Majątkiem - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/pricing/pricing-page.html + 133 + + + apps/client/src/app/pages/pricing/pricing-page.html + 221 - - Manage your wealth like a boss - Zarządzaj swoim majątkiem niczym Boss + + Community Support + Wsparcie Społeczności - apps/client/src/app/pages/landing/landing-page.html - 5 + apps/client/src/app/pages/pricing/pricing-page.html + 77 - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio to zapewniający prywatność, open source'owy panel do zarządzania finansami osobistymi. Przeanalizuj szczegółowo swoją alokację aktywów, określ swoją wartość netto i podejmuj przemyślane decyzje inwestycyjne oparte na danych. + + Self-hosted, update manually. + Samodzielny hosting, aktualizacja ręczna. - apps/client/src/app/pages/landing/landing-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 81 - - Get Started - Rozpocznij + + Free + Bezpłatnie - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/pages/pricing/pricing-page.html + 83 apps/client/src/app/pages/pricing/pricing-page.html - 324 + 146 - - Live Demo - Live Demo + + For new investors who are just getting started with trading. + Dla początkujących inwestorów, którzy dopiero zaczynają swoją przygodę z tradingiem. - apps/client/src/app/pages/landing/landing-page.html - 49 + apps/client/src/app/pages/pricing/pricing-page.html + 116 + + + Fully managed Ghostfolio cloud offering. + W pełni zarządzana oferta Ghostfolio w chmurze. - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/pricing/pricing-page.html + 144 - - - Monthly Active Users - Aktywni Użytkownicy w Miesiącu - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/pricing/pricing-page.html + 270 - - Stars on GitHub - Gwiazdki na GitHubie + + For ambitious investors who need the full picture of their financial assets. + Dla ambitnych inwestorów, którzy potrzebują pełnego obrazu swoich aktywów finansowych. - apps/client/src/app/pages/landing/landing-page.html - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 187 + + + Email and Chat Support + Wsparcie przez E-mail i Czat - apps/client/src/app/pages/open/open-page.html - 103 + apps/client/src/app/pages/pricing/pricing-page.html + 266 - - Pulls on Docker Hub - Pobrania na Docker Hub + + Renew Plan + Odnów Plan - apps/client/src/app/pages/landing/landing-page.html - 106 + apps/client/src/app/components/header/header.component.html + 191 - apps/client/src/app/pages/open/open-page.html - 117 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 18 - - - As seen in - Dostrzegli Nas - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/pages/pricing/pricing-page.html + 297 - - Protect your assets. Refine your personal investment strategy. - Chroń swoje zasoby. Udoskonal swoją osobistą strategię inwestycyjną. + + One-time payment, no auto-renewal. + Płatność jednorazowa, bez automatycznego odnawiania. - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/pricing/pricing-page.html + 303 - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio umożliwia zapracowanym osobom śledzenie akcji, funduszy ETF lub kryptowalut, jednocześnie zachowując prywatność. + + It’s free. + Jest bezpłatny. - apps/client/src/app/pages/landing/landing-page.html - 229 + apps/client/src/app/pages/pricing/pricing-page.html + 353 - - 360° View - Widok 360° + + Hello, has shared a Portfolio with you! + Witaj, udostępnił Ci Portfel - apps/client/src/app/pages/landing/landing-page.html - 240 + apps/client/src/app/pages/public/public-page.html + 5 - - Get the full picture of your personal finances across multiple platforms. - Uzyskaj pełny obraz swoich finansów osobistych na wielu różnych platformach. + + Continents + Kontynenty - apps/client/src/app/pages/landing/landing-page.html - 242 + apps/client/src/app/pages/public/public-page.html + 124 - - Web3 Ready - Gotowy na Web3 + + Ghostfolio empowers you to keep track of your wealth. + Ghostfolio umożliwia śledzenie wartości swojego majątku. - apps/client/src/app/pages/landing/landing-page.html - 251 + apps/client/src/app/pages/public/public-page.html + 216 - - Use Ghostfolio anonymously and own your financial data. - Korzystaj z Ghostfolio anonimowo i zachowaj pełną kontrolę nad swoimi danymi finansowymi. + + Registration + Rejestracja - apps/client/src/app/pages/landing/landing-page.html - 253 + apps/client/src/app/components/admin-users/admin-users.html + 98 - - - Open Source - Otwarty Kod Źródłowy - apps/client/src/app/pages/landing/landing-page.html - 261 + libs/common/src/lib/routes/routes.ts + 281 - - Benefit from continuous improvements through a strong community. - Czerp korzyści z nieustannych ulepszeń dzięki silnej społeczności. + + Continue with Internet Identity + Kontynuuj z tożsamością internetową - apps/client/src/app/pages/landing/landing-page.html - 263 + apps/client/src/app/pages/register/register-page.html + 42 - - Why Ghostfolio? - Dlaczego Ghostfolio? + + Continue with Google + Zaloguj z Google - apps/client/src/app/pages/landing/landing-page.html - 272 + apps/client/src/app/pages/register/register-page.html + 53 - - Ghostfolio is for you if you are... - Ghostfolio jest dla Ciebie, jeśli... + + Copy to clipboard + Kopiuj do schowka - apps/client/src/app/pages/landing/landing-page.html - 273 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 - - trading stocks, ETFs or cryptocurrencies on multiple platforms - handlujesz akcjami, funduszami ETF lub kryptowalutami na wielu platformach + + Personal Finance Tools + Narzędzia finansów osobistych - apps/client/src/app/pages/landing/landing-page.html - 280 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 - - - pursuing a buy & hold strategy - realizujesz strategię buy & hold - apps/client/src/app/pages/landing/landing-page.html - 286 + libs/common/src/lib/routes/routes.ts + 329 - - interested in getting insights of your portfolio composition - chcesz uzyskać wgląd w strukturę swojego portfolio + + open-source-alternative-to + alternatywa-open-source-dla + kebab-case - apps/client/src/app/pages/landing/landing-page.html - 291 + libs/common/src/lib/routes/routes.ts + 320 - - - valuing privacy and data ownership - cenisz sobie prywatność i własność swoich danych - apps/client/src/app/pages/landing/landing-page.html - 296 + libs/common/src/lib/routes/routes.ts + 324 - - into minimalism - lubisz minimalizm + + Discover Open Source Alternatives for Personal Finance Tools + Odkryj alternatywy Open Source dla Narzędzi Finansów Osobistych - apps/client/src/app/pages/landing/landing-page.html - 299 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 - - caring about diversifying your financial resources - zależy Ci na dywersyfikacji swoich zasobów finansowych + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Ta przeglądowa strona zawiera wyselekcjonowaną kolekcję narzędzi do finansów osobistych w porównaniu z alternatywą open source Ghostfolio. Jeśli cenisz sobie przejrzystość, prywatność danych i współpracę ze społecznością, Ghostfolio stanowi doskonałą okazję do przejęcia kontroli nad swoim zarządzaniem finansami. - apps/client/src/app/pages/landing/landing-page.html - 303 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 - - interested in financial independence - jesteś zainteresowany niezależnością finansową + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Zapoznaj się z poniższymi linkami, aby móc porównać różne narzędzia do finansów osobistych z Ghostfolio. - apps/client/src/app/pages/landing/landing-page.html - 307 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 - - saying no to spreadsheets in - mówisz „nie” arkuszom kalkulacyjnym w roku + + Open Source Alternative to + Alternatywa Open Source dla - apps/client/src/app/pages/landing/landing-page.html - 311 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 - - still reading this list - nadal czytasz tę listę + + The Open Source Alternative to + Alternatywa Open Source dla - apps/client/src/app/pages/landing/landing-page.html - 314 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 - - Learn more about Ghostfolio - Dowiedz się więcej o Ghostfolio + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Szukasz alternatywy typu open source dla ? Ghostfolio to potężne narzędzie do zarządzania portfelem, które zapewnia osobom fizycznym kompleksową platformę do śledzenia, analizowania i optymalizacji ich inwestycji. Niezależnie od tego, czy jesteś doświadczonym inwestorem, czy dopiero zaczynasz, Ghostfolio oferuje intuicyjny interfejs użytkownika i szeroki zakres funkcjonalności, które pomogą Ci podejmować przemyślane decyzje i przejąć kontrolę nad swoją finansową przyszłością. - apps/client/src/app/pages/landing/landing-page.html - 319 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 - - What our users are saying - Co mówią nasi użytkownicy + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio to oprogramowanie o otwartym kodzie źródłowym (OSS), stanowiące opłacalną alternatywę dla , czyniąc go szczególnie odpowiednim dla osób o ograniczonym budżecie, takich jak osoby dążące do finansowej niezależności i wcześniejszej emerytury (Financial Independence, Retire Early - FIRE). Wykorzystując wspólne wysiłki społeczności programistów i entuzjastów finansów osobistych, Ghostfolio stale zwiększa swoje możliwości, bezpieczeństwo i komfort użytkowania. - apps/client/src/app/pages/landing/landing-page.html - 327 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 - - Members from around the globe are using Ghostfolio Premium - Użytkownicy z całego świata korzystają z Ghostfolio Premium + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Zagłębmy się w szczegółową tabelę porównawczą Ghostfolio vs poniżej, aby dokładnie zrozumieć, jak Ghostfolio pozycjonuje się w stosunku do . Przeanalizujemy różne aspekty, takie jak funkcje, prywatność danych, opłaty i inne, umożliwiając Tobie dokonanie przemyślanego wyboru pod kątem osobistych wymagań. - apps/client/src/app/pages/landing/landing-page.html - 366 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - How does Ghostfolio work? - Jak działa Ghostfolio ? + + Ghostfolio vs comparison table + Ghostfolio vs - tabela porównawcza - apps/client/src/app/pages/landing/landing-page.html - 383 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 - - Get started in only 3 steps - Rozpocznij w zaledwie 3 krokach + + Founded + Rok założenia - apps/client/src/app/pages/landing/landing-page.html - 386 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 - - Sign up anonymously* - Zarejestruj się anonimowo* + + Origin + Pochodzenie - apps/client/src/app/pages/landing/landing-page.html - 392 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 - - * no e-mail address nor credit card required - * nie jest wymagany ani adres e-mail, ani karta kredytowa + + Region + Region - apps/client/src/app/pages/landing/landing-page.html - 394 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 - - Add any of your historical transactions - Dodaj dowolne z Twoich historycznych transakcji + + Available in + Dostępny w następujących językach - apps/client/src/app/pages/landing/landing-page.html - 405 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 - - Get valuable insights of your portfolio composition - Zyskaj cenny wgląd w strukturę swojego portfolio + + ✅ Yes + ✅ Tak - apps/client/src/app/pages/landing/landing-page.html - 417 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 - - - Are you ready? - Czy jesteś gotów? - apps/client/src/app/pages/landing/landing-page.html - 431 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 - - - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - W Ghostfolio przejrzystość stanowi podstawę naszych wartości. Publikujemy kod źródłowy jako oprogramowanie open source (OSS) na licencji AGPL-3.0 i otwarcie udostępniamy zagregowane kluczowe wskaźniki dotyczące stanu operacyjnego platformy. - apps/client/src/app/pages/open/open-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 - - - (Last 24 hours) - (Ostatnie 24 godziny) - apps/client/src/app/pages/open/open-page.html - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 - - - Active Users - Aktywni Użytkownicy - apps/client/src/app/pages/open/open-page.html - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 - apps/client/src/app/pages/open/open-page.html - 62 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 - - - (Last 30 days) - (Ostatnie 30 dni) - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 - - New Users - Nowi Użytkownicy + + ❌ No + ❌ Nie - apps/client/src/app/pages/open/open-page.html - 51 - - - - Users in Slack community - Użytkownicy w społeczności Slack - - apps/client/src/app/pages/open/open-page.html - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 - - - Contributors on GitHub - Współtwórcy na GitHubie – osoby zaangażowane w rozwój projektu - apps/client/src/app/pages/open/open-page.html - 89 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 - - - (Last 90 days) - (Ostatnie 90 dni) - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 - - - Uptime - Czas Sprawności - apps/client/src/app/pages/open/open-page.html - 132 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 - - - Activities - Aktywności - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 - - - Do you really want to delete these activities? - Czy na pewno chcesz usunąć te aktywności? - libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 - - - Update activity - Aktualizuj aktywność - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 - - Stocks, ETFs, bonds, cryptocurrencies, commodities - Akcje, fundusze ETF, obligacje, kryptowaluty, towary + + Self-Hosting + Własny Hosting - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 + + + Use anonymously + Korzystaj anonimowo - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 65 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 210 - - One-time fee, annual account fees - Opłata jednorazowa, roczne opłaty za konto + + Free Plan + Plan Darmowy - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 - - Distribution of corporate earnings - Rozkład zysków przedsiębiorstw + + Notes + Notatki - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 - - Revenue for lending out money - Przychód z tytułu pożyczania pieniędzy + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Należy pamiętać, że informacje zawarte w tabeli porównawczej Ghostfolio vs są oparte na naszych niezależnych badaniach i analizach. Ta strona internetowa nie jest powiązana z ani żadnym innym produktem wymienionym w porównaniu. Ponieważ krajobraz narzędzi do finansów osobistych ewoluuje, ważne jest, aby weryfikować wszelkie szczegóły lub zmiany bezpośrednio na stronie danego produktu. Informacje wymagają aktualizacji? Pomóż nam utrzymywać dokładne dane na GitHub. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - Mortgages, personal loans, credit cards - Kredyty hipoteczne, kredyty indywidualne, karty kredytowe + + Ready to take your investments to the next level? + Jesteś gotów wznieść swoje inwestycje na wyższy poziom? - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 57 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 - - Luxury items, real estate, private companies - Towar luksusowy, nieruchomości, firmy prywatne + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + Bezproblemowo śledź, analizuj i wizualizuj swój majątek dzięki Ghostfolio. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 73 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 - - Account - Konto + + Switzerland + Szwajcaria - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - libs/ui/src/lib/activities-table/activities-table.component.html - 308 + libs/ui/src/lib/i18n.ts + 96 + + + Global + Globalny - libs/ui/src/lib/assistant/assistant.html - 107 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - - - Update Cash Balance - Zaktualizuj Saldo Gotówkowe - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 112 + libs/ui/src/lib/i18n.ts + 16 - - Unit Price - Cena Jednostkowa + + Resources + Zasoby - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + apps/client/src/app/app.component.html + 64 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + apps/client/src/app/components/header/header.component.html + 88 - libs/ui/src/lib/activities-table/activities-table.component.html - 210 + apps/client/src/app/components/header/header.component.html + 301 - - - Oops! Could not get the historical exchange rate from - Ups! Nie udało się uzyskać historycznego kursu wymiany z - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 - - - Fee - Opłata - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 + libs/common/src/lib/routes/routes.ts + 332 + + + Membership + Członkostwo - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + libs/common/src/lib/routes/routes.ts + 31 - libs/ui/src/lib/activities-table/activities-table.component.html - 234 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 - - Oops! Could not get the historical exchange rate from - Ups! Nie udało się uzyskać historycznego kursu wymiany z + + Access + Dostęp - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 + libs/common/src/lib/routes/routes.ts + 26 - - Import Activities - Importuj Aktywności + + My Ghostfolio + Moje Ghostfolio - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + apps/client/src/app/components/header/header.component.html + 277 - - - Import Dividends - Impotruj Dywidendy - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 - - Importing data... - Importowanie danych... + + Oops, authentication has failed. + Ups, uwierzytelnienie nie powiodło się. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 - - Import has been completed - Importowanie zakończone + + Try again + Spróbuj ponownie - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 - - Validating data... - Weryfikacja danych... + + Go back to Home Page + Wróć do Strony Głównej - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 - - Select Holding - Wybierz Inwestycje + + Export Activities + Eksportuj Działalności - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 20 + libs/ui/src/lib/activities-table/activities-table.component.html + 41 - - - Select File - Wybierz plik - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 22 + libs/ui/src/lib/activities-table/activities-table.component.html + 396 - - Holding - Inwestycja + + Export Drafts as ICS + Eksportuj Wersje Robocze jako ICS - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 32 + libs/ui/src/lib/activities-table/activities-table.component.html + 54 - libs/ui/src/lib/assistant/assistant.html - 127 + libs/ui/src/lib/activities-table/activities-table.component.html + 409 - - Load Dividends - Załaduj dywidendy + + Draft + Przygotuj Wstępną Wersję - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 68 - - - - Choose or drop a file here - Wybierz lub przeciągnij plik tutaj - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/activities-table/activities-table.component.html + 145 - - The following file formats are supported: - Obsługiwane są następujące formaty plików: + + Clone + Sklonuj - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 90 + libs/ui/src/lib/activities-table/activities-table.component.html + 436 - - Select Dividends - Wybierz dywidendy + + Export Draft as ICS + Eksportuj Wersję Roboczą jako ICS - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 113 + libs/ui/src/lib/activities-table/activities-table.component.html + 446 - - Select Activities - Wybór działań + + Do you really want to delete this activity? + Czy na pewno chcesz usunąć tę działalność? - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 115 + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 - - Back - Wróc - - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 144 - + + Asset Profiles + Profile aktywów - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 178 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - - Allocations - Podziały - - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 - + + Last All Time High + Ostatni Najwyższy Punkt w Historii - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - Allocations - Podziały + + Change from All Time High + Zmiana od Najwyższego Punktu w Historii - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + libs/ui/src/lib/benchmark/benchmark.component.html + 110 - - Proportion of Net Worth - Proporcja wartości netto + + from ATH + od ATH - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 12 + libs/ui/src/lib/benchmark/benchmark.component.html + 112 - - By Platform - Wg. platformy + + Market data provided by + Dane rynkowe dostarczone przez - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 44 + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 - - By Currency - Wg. waluty + + Savings Rate per Month + Miesięczna stopa oszczędności - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 63 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 - - By Asset Class - Wg. klasy aktywów + + Annual Interest Rate + Roczna Stopa Procentowa - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 85 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 - - By Holding - Wg. inwestycji + + Retirement Date + Data przejścia na emeryturę - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 107 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 - - By Sector - Wg. sektora + + Projected Total Amount + Przewidywana Łączna Kwota - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 130 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 - - By Continent - Wg. kontynentu + + Interest + Udział - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 153 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 - - - By Market - Wg. rynku - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 175 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 - - - Regions - Regiony - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 198 + libs/ui/src/lib/i18n.ts + 38 + + + Savings + Oszczędności - apps/client/src/app/pages/public/public-page.html - 143 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 - - Developed Markets - Rynki Rozwinięte + + Allocation + Podział - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 222 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 - apps/client/src/app/pages/public/public-page.html - 160 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 - - - Emerging Markets - Rynki Wschodzące - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 231 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 40 - apps/client/src/app/pages/public/public-page.html - 169 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 - - Other Markets - Inne Rynki - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 240 - + + Show all + Pokaż wszystko - apps/client/src/app/pages/public/public-page.html - 178 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 - - No data available - Brak danych + + Account + Konto - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 - apps/client/src/app/pages/public/public-page.html - 188 + libs/ui/src/lib/activities-table/activities-table.component.html + 308 - libs/ui/src/lib/benchmark/benchmark.component.html - 137 + libs/ui/src/lib/assistant/assistant.html + 157 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + libs/ui/src/lib/i18n.ts + 4 - - By Account - Wg. kont + + Asia-Pacific + Azja-Pacyfik - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 286 + libs/ui/src/lib/i18n.ts + 5 - - By ETF Provider - Wg. Dostawcy ETF + + Asset Class + Rodzaj Aktywów - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 306 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 - - - By Country - Wg. kraju - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 264 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 - - - Analysis - Analiza - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 - - - Dividend - Dywidenda - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 libs/ui/src/lib/i18n.ts - 36 + 6 - - Deposit - Depozyt + + Asset Sub Class + Podklasa Aktywów - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 - - - Monthly - Miesięcznie - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 - - - Yearly - Rocznie - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 - - - Analysis - Analiza - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 - - - Top - Największe wzrosty - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 - - - Bottom - Największy spadek - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + libs/ui/src/lib/i18n.ts + 7 - - Portfolio Evolution - Rozwój portfela + + Core + Główny - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + libs/ui/src/lib/i18n.ts + 10 - - Investment Timeline - Oś czasu inwestycji + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily + Przełącz się z łatwością na Ghostfolio Premium lub Ghostfolio Open Source - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + libs/ui/src/lib/i18n.ts + 12 - - Current Streak - Obecna passa + + Switch to Ghostfolio Premium easily + Przełącz się z łatwością na Ghostfolio Premium - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + libs/ui/src/lib/i18n.ts + 13 - - Longest Streak - Najdłuższa passa + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily + Przełącz się z łatwością na Ghostfolio Open Source lub Ghostfolio Basic - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + libs/ui/src/lib/i18n.ts + 14 - - Dividend Timeline - Oś czasu dywidend + + Emergency Fund + Fundusz Rezerwowy - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 - - - FIRE - F.I.R.E. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 4 + apps/client/src/app/pages/features/features-page.html + 89 - - - Calculator - Kalkulator - apps/client/src/app/pages/portfolio/fire/fire-page.html - 7 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 - - - 4% Rule - Zasada 4% - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 + libs/ui/src/lib/i18n.ts + 15 - - Currency Cluster Risks - Ryzyko związane z klastrem walutowym + + Grant + Dotacja - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + libs/ui/src/lib/i18n.ts + 17 - - Account Cluster Risks - Ryzyko związane z klastrem kont + + Higher Risk + Wyższe Ryzyko - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + libs/ui/src/lib/i18n.ts + 18 - - Holdings - Inwestycje + + This activity already exists. + Ta działalność już istnieje. - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + libs/ui/src/lib/i18n.ts + 19 + + + Japan + Japonia - apps/client/src/app/components/home-holdings/home-holdings.html - 4 + libs/ui/src/lib/i18n.ts + 89 + + + Lower Risk + Niższe Ryzyko - apps/client/src/app/pages/public/public-page.html - 70 + libs/ui/src/lib/i18n.ts + 20 + + + Month + Miesiąc - libs/ui/src/lib/assistant/assistant.html - 46 + libs/ui/src/lib/i18n.ts + 21 - - Pricing - Cennik + + Months + Miesiące - apps/client/src/app/pages/pricing/pricing-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 22 - - Pricing Plans - Plany cenowe + + Other + Inne - apps/client/src/app/pages/pricing/pricing-page.html - 4 + libs/ui/src/lib/i18n.ts + 23 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Nasza oficjalna chmurowa usługa Ghostfolio Premium jest najprostszym sposobem by rozpocząć przygodę z Ghostfolio. To najlepsza opcja dla większości osób ze względu na czas, jaki można dzięki niej zaoszczędzić. Uzyskany przychód jest wykorzystywany do pokrycia kosztów infrastruktury hostingowej i finansowania bieżącego rozwoju. + + Preset + Wstępnie ustawione - apps/client/src/app/pages/pricing/pricing-page.html - 6 + libs/ui/src/lib/i18n.ts + 25 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - Jeżeli wolisz uruchomić Ghostfolio na własnej infrastrukturze, możesz znaleźć kod źródłowy i dalsze instrukcje na naszym GitHubie. + + Retirement Provision + Świadczenia Emerytalne - apps/client/src/app/pages/pricing/pricing-page.html + libs/ui/src/lib/i18n.ts 26 - - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - Dla inwestorów obeznanych technicznie, którzy wolą uruchomić Ghostfolio na własnej infrastrukturze. + + Satellite + Satelita - apps/client/src/app/pages/pricing/pricing-page.html - 38 + libs/ui/src/lib/i18n.ts + 27 - - Unlimited Transactions - Nieograniczona Liczba Transakcji + + Symbol + Symbol - apps/client/src/app/pages/pricing/pricing-page.html - 45 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 - apps/client/src/app/pages/pricing/pricing-page.html - 134 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 - apps/client/src/app/pages/pricing/pricing-page.html - 201 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 - - - Unlimited Accounts - Nieograniczona Liczba Rachunków - apps/client/src/app/pages/pricing/pricing-page.html - 49 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 - apps/client/src/app/pages/pricing/pricing-page.html - 138 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 - apps/client/src/app/pages/pricing/pricing-page.html - 205 + libs/ui/src/lib/i18n.ts + 28 - - Portfolio Performance - Wyniki portfela + + Tag + Tag - apps/client/src/app/pages/pricing/pricing-page.html - 53 + libs/ui/src/lib/assistant/assistant.html + 207 - apps/client/src/app/pages/pricing/pricing-page.html - 142 + libs/ui/src/lib/i18n.ts + 29 + + + Year + Rok - apps/client/src/app/pages/pricing/pricing-page.html - 209 + libs/ui/src/lib/i18n.ts + 30 - - Data Import and Export - Importowanie i Eksportowanie Danych + + Years + Lata - apps/client/src/app/pages/pricing/pricing-page.html - 73 - + libs/ui/src/lib/i18n.ts + 31 + + + + Buy + Zakup - apps/client/src/app/pages/pricing/pricing-page.html - 146 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 - apps/client/src/app/pages/pricing/pricing-page.html - 229 + libs/ui/src/lib/i18n.ts + 35 - - Community Support - Wsparcie Społeczności + + Fee + Opłata - apps/client/src/app/pages/pricing/pricing-page.html - 90 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - - - Self-hosted, update manually. - Samodzielny hosting, aktualizacja ręczna. - apps/client/src/app/pages/pricing/pricing-page.html - 94 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - - - Free - Bezpłatnie - apps/client/src/app/pages/pricing/pricing-page.html - 95 + libs/ui/src/lib/i18n.ts + 37 + + + Valuable + Kosztowności - apps/client/src/app/pages/pricing/pricing-page.html - 158 + libs/ui/src/lib/i18n.ts + 39 - - For new investors who are just getting started with trading. - Dla początkujących inwestorów, którzy dopiero zaczynają swoją przygodę z tradingiem. + + Liability + Zobowiązanie - apps/client/src/app/pages/pricing/pricing-page.html - 128 + libs/ui/src/lib/i18n.ts + 40 - - Fully managed Ghostfolio cloud offering. - W pełni zarządzana oferta Ghostfolio w chmurze. + + Sell + Sprzedaj - apps/client/src/app/pages/pricing/pricing-page.html - 157 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 - apps/client/src/app/pages/pricing/pricing-page.html - 261 + libs/ui/src/lib/i18n.ts + 41 - - For ambitious investors who need the full picture of their financial assets. - Dla ambitnych inwestorów, którzy potrzebują pełnego obrazu swoich aktywów finansowych. + + Cash + Gotówka - apps/client/src/app/pages/pricing/pricing-page.html - 194 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 - - - Email and Chat Support - Wsparcie przez E-mail i Czat - apps/client/src/app/pages/pricing/pricing-page.html - 257 + libs/ui/src/lib/i18n.ts + 53 - - Renew Plan - Odnów Plan + + Commodity + Towar - apps/client/src/app/components/header/header.component.html - 191 + libs/ui/src/lib/i18n.ts + 45 + + + Equity + Kapitał - apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 - apps/client/src/app/pages/pricing/pricing-page.html - 294 + libs/ui/src/lib/i18n.ts + 46 - - One-time payment, no auto-renewal. - Płatność jednorazowa, bez automatycznego odnawiania. + + Fixed Income + Stały Dochód - apps/client/src/app/pages/pricing/pricing-page.html - 298 + libs/ui/src/lib/i18n.ts + 47 - - Get Started - Rozpocznij + + Real Estate + Nieruchomość - apps/client/src/app/pages/landing/landing-page.html - 446 + libs/ui/src/lib/i18n.ts + 49 - - It’s free. - Jest bezpłatny. + + Bond + Obligacja - apps/client/src/app/pages/pricing/pricing-page.html - 327 + libs/ui/src/lib/i18n.ts + 52 - - Hello, has shared a Portfolio with you! - Witaj, udostępnił Ci Portfel + + Cryptocurrency + Kryptowaluta - apps/client/src/app/pages/public/public-page.html - 4 + libs/ui/src/lib/i18n.ts + 55 - - Currencies - Waluty + + ETF + ETF - apps/client/src/app/pages/public/public-page.html - 88 + libs/ui/src/lib/i18n.ts + 56 - - Continents - Kontynenty + + Mutual Fund + Fundusz Wzajemny - apps/client/src/app/pages/public/public-page.html - 124 + libs/ui/src/lib/i18n.ts + 57 - - Ghostfolio empowers you to keep track of your wealth. - Ghostfolio umożliwia śledzenie wartości swojego majątku. + + Precious Metal + Metal Szlachetny - apps/client/src/app/pages/public/public-page.html - 215 + libs/ui/src/lib/i18n.ts + 58 - - Registration - Rejestracja + + Private Equity + Prywatny Kapitał - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 59 - - Continue with Internet Identity - Kontynuuj z tożsamością internetową + + Stock + Akcje - apps/client/src/app/pages/register/register-page.html - 42 + libs/ui/src/lib/i18n.ts + 60 - - Continue with Google - Zaloguj z Google + + Africa + Afryka - apps/client/src/app/pages/register/register-page.html - 53 + libs/ui/src/lib/i18n.ts + 67 - - Copy to clipboard - Kopiuj do schowka + + Asia + Azja - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + libs/ui/src/lib/i18n.ts + 68 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Wyrażam zgodę na przechowywanie mojego Tokenu zabezpieczającego w bezpiecznym miejscu. Jego utrata nie pozwoli odzyskać konta! + + Europe + Europa - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + libs/ui/src/lib/i18n.ts + 69 - - Agree and continue - Zgadzam się i kontynuuję + + North America + Ameryka Północna - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + libs/ui/src/lib/i18n.ts + 70 - - Personal Finance Tools - Narzędzia finansów osobistych + + Oceania + Oceania - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + libs/ui/src/lib/i18n.ts + 71 - - open-source-alternative-to - open-source-alternative-to - - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 - + + South America + Ameryka Południowa - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 72 - - Open Source Alternative to - Alternatywa Open Source dla + + Extreme Fear + Skrajny Strach - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + libs/ui/src/lib/i18n.ts + 103 - - Discover Open Source Alternatives for Personal Finance Tools - Odkryj alternatywy Open Source dla Narzędzi Finansów Osobistych + + Extreme Greed + Skrajna Zachłanność - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + libs/ui/src/lib/i18n.ts + 104 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Ta przeglądowa strona zawiera wyselekcjonowaną kolekcję narzędzi do finansów osobistych w porównaniu z alternatywą open source Ghostfolio. Jeśli cenisz sobie przejrzystość, prywatność danych i współpracę ze społecznością, Ghostfolio stanowi doskonałą okazję do przejęcia kontroli nad swoim zarządzaniem finansami. + + Neutral + Neutralny - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/i18n.ts + 107 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Zapoznaj się z poniższymi linkami, aby móc porównać różne narzędzia do finansów osobistych z Ghostfolio. + + Valid until + Ważność do - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 - - - Open Source Alternative to - Alternatywa Open Source dla - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + libs/ui/src/lib/membership-card/membership-card.component.html 42 - - The Open Source Alternative to - Alternatywa Open Source dla + + Time to add your first activity. + Czas dodać Twoją pierwszą działalność. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Szukasz alternatywy typu open source dla ? Ghostfolio to potężne narzędzie do zarządzania portfelem, które zapewnia osobom fizycznym kompleksową platformę do śledzenia, analizowania i optymalizacji ich inwestycji. Niezależnie od tego, czy jesteś doświadczonym inwestorem, czy dopiero zaczynasz, Ghostfolio oferuje intuicyjny interfejs użytkownika i szeroki zakres funkcjonalności, które pomogą Ci podejmować przemyślane decyzje i przejąć kontrolę nad swoją finansową przyszłością. + + No data available + Brak danych - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 - - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio to oprogramowanie o otwartym kodzie źródłowym (OSS), stanowiące opłacalną alternatywę dla , czyniąc go szczególnie odpowiednim dla osób o ograniczonym budżecie, takich jak osoby dążące do finansowej niezależności i wcześniejszej emerytury (Financial Independence, Retire Early - FIRE). Wykorzystując wspólne wysiłki społeczności programistów i entuzjastów finansów osobistych, Ghostfolio stale zwiększa swoje możliwości, bezpieczeństwo i komfort użytkowania. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Zagłębmy się w szczegółową tabelę porównawczą Ghostfolio vs poniżej, aby dokładnie zrozumieć, jak Ghostfolio pozycjonuje się w stosunku do . Przeanalizujemy różne aspekty, takie jak funkcje, prywatność danych, opłaty i inne, umożliwiając Tobie dokonanie przemyślanego wyboru pod kątem osobistych wymagań. + + 50-Day Trend + 50-Dniowy Trend - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 - - Ghostfolio vs comparison table - Ghostfolio vs - tabela porównawcza + + 200-Day Trend + 200-Dniowy Trend - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + libs/ui/src/lib/benchmark/benchmark.component.html 54 - - Founded - Rok założenia + + Cash Balances + Salda Gotówkowe - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 77 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 - - Origin - Pochodzenie + + Starting from + Począwszy od apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 82 + 289 - - - Region - Region apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 87 + 294 - - Available in - Dostępny w następujących językach + + Do you really want to delete this account balance? + Czy na pewno chcesz usunąć saldo tego konta? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - ✅ Yes - ✅ Tak + + If a translation is missing, kindly support us in extending it here. + Jeżeli brakuje jakiegoś tłumaczenia, uprzejmie prosimy o wsparcie w jego uzupełnieniu tutaj. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 140 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 + + + The current market price is + Obecna cena rynkowa wynosi - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 157 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 + + + Test + Test - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 179 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 + + + Date Range + Zakres Dat - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 196 + libs/ui/src/lib/assistant/assistant.html + 143 + + + Permission + Pozwolenie - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 218 + apps/client/src/app/components/access-table/access-table.component.html + 18 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 235 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 + + + Restricted view + Ograniczony widok - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 257 + apps/client/src/app/components/access-table/access-table.component.html + 26 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 274 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - ❌ No - ❌ Nie + + Oops! Could not grant access. + Ups! Nie udało się przyznać dostępu. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 147 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + Private + Prywatny - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 164 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 + + + Job Queue + Kolejka Zadań - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 186 + libs/common/src/lib/routes/routes.ts + 46 + + + Market data is delayed for + Dane rynkowe są opóźnione o - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 203 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + Investment + Inwestycje - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 225 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 242 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 264 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 281 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 - - - Self-Hosting - Własny Hosting - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 - - Use anonymously - Korzystaj anonimowo + + Absolute Asset Performance + Łączny wynik aktywów - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Free Plan - Plan Darmowy + + Asset Performance + Wyniki aktywów - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Notes - Notatki + + Absolute Currency Performance + Łączny wynik walut - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 302 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Należy pamiętać, że informacje zawarte w tabeli porównawczej Ghostfolio vs są oparte na naszych niezależnych badaniach i analizach. Ta strona internetowa nie jest powiązana z ani żadnym innym produktem wymienionym w porównaniu. Ponieważ krajobraz narzędzi do finansów osobistych ewoluuje, ważne jest, aby weryfikować wszelkie szczegóły lub zmiany bezpośrednio na stronie danego produktu. Informacje wymagają aktualizacji? Pomóż nam utrzymywać dokładne dane na GitHub. + + Currency Performance + Wynik walut - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 - - Ready to take your investments to the next level? - Jesteś gotów wznieść swoje inwestycje na wyższy poziom? + + Absolute Net Performance + Łączna wartość netto - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 - - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. - Bezproblemowo śledź, analizuj i wizualizuj swój majątek dzięki Ghostfolio. + + Net Performance + Wynik netto - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 - - Get Started - Rozpocznij + + Week to date + Dotychczasowy tydzień - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Personal Finance Tools - Narzędzia do Finansów Osobistych + + WTD + WTD - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Switzerland - Szwajcaria + + Month to date + Od początku miesiąca - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + MTD + MTD - libs/ui/src/lib/i18n.ts - 90 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Global - Globalny + + Year to date + Od początku roku - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + View + Widok - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/components/access-table/access-table.component.html + 23 - - - Resources - Zasoby - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - Guides - Poradniki + + Oops! A data provider is experiencing the hiccups. + Ups! Dostawca danych zmaga się teraz z drobnymi przeszkodami. - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 - - Glossary - Słowniczek + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Jeśli przejdziesz na emeryturę dzisiaj, będziesz mógł wypłacić rocznie lub miesięcznie, w oparciu o Twój łączny majątek w wysokości i stopę wypłaty w wysokości 4%. - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 - - Membership - Członkostwo + + Reset Filters + Resetuj Filtry - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + libs/ui/src/lib/assistant/assistant.html + 238 + + + year + rok - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - - - Access - Dostęp - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - My Ghostfolio - Moje Ghostfolio + + years + lata - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 33 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Oops, authentication has failed. - Ups, uwierzytelnienie nie powiodło się. + + Apply Filters + Zastosuj Filtry - apps/client/src/app/pages/webauthn/webauthn-page.html - 19 + libs/ui/src/lib/assistant/assistant.html + 248 - - Try again - Spróbuj ponownie + + Data Gathering + Gromadzenie Danych - apps/client/src/app/pages/webauthn/webauthn-page.html - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 - - Go back to Home Page - Wróć do Strony Głównej + + General + Informacje Ogólne - apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 - - Import Activities - Importuj Działalności + + Cloud + Rozwiązanie w Chmurze - libs/ui/src/lib/activities-table/activities-table.component.html - 9 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 - libs/ui/src/lib/activities-table/activities-table.component.html - 371 + libs/common/src/lib/routes/routes.ts + 240 - - Import Dividends - Importuj Dywidendy + + Self-Hosting + Własny Hosting - libs/ui/src/lib/activities-table/activities-table.component.html - 29 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - libs/ui/src/lib/activities-table/activities-table.component.html - 383 + libs/common/src/lib/routes/routes.ts + 248 - - Export Activities - Eksportuj Działalności + + self-hosting + wlasny-hosting + kebab-case - libs/ui/src/lib/activities-table/activities-table.component.html - 41 + libs/common/src/lib/routes/routes.ts + 243 - libs/ui/src/lib/activities-table/activities-table.component.html - 396 + libs/common/src/lib/routes/routes.ts + 246 - - Export Drafts as ICS - Eksportuj Wersje Robocze jako ICS + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Ups! Wygląda na to, że wykonujesz zbyt wiele zapytań. Proszę, zwolnij trochę. - libs/ui/src/lib/activities-table/activities-table.component.html - 54 + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + My Account + Moje Konto - libs/ui/src/lib/activities-table/activities-table.component.html - 409 + apps/client/src/app/pages/i18n/i18n-page.html + 13 - - Draft - Przygotuj Wstępną Wersję + + Active + Antywne - libs/ui/src/lib/activities-table/activities-table.component.html - 145 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 - - Clone - Sklonuj + + Closed + Zamknięte - libs/ui/src/lib/activities-table/activities-table.component.html - 436 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 - - Export Draft as ICS - Eksportuj Wersję Roboczą jako ICS + + Indonesia + Indonesia - libs/ui/src/lib/activities-table/activities-table.component.html - 446 + libs/ui/src/lib/i18n.ts + 87 - - Do you really want to delete this activity? - Czy na pewno chcesz usunąć tę działalność? + + Activity + Aktywność - libs/ui/src/lib/activities-table/activities-table.component.ts - 229 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 - - Find holding... - Znajdź portfel akcji... + + Dividend Yield + Dochód z Dywidendy - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 - - No entries... - Brak wpisów... + + Execute Job + Wykonaj Zadanie - libs/ui/src/lib/assistant/assistant.html - 63 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + Priority + Priorytet - libs/ui/src/lib/assistant/assistant.html - 84 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 - - Asset Profiles - Profile aktywów + + This action is not allowed. + To działanie jest niedozwolone. - libs/ui/src/lib/assistant/assistant.html + apps/client/src/app/core/http-response.interceptor.ts 67 - - Index - Indeks + + Liquidity + Płynność środków finansowych - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + libs/ui/src/lib/i18n.ts + 48 - - Last All Time High - Ostatni Najwyższy Punkt w Historii + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {działalność} other {działalność}} - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 - - Change from All Time High - Zmiana od Najwyższego Punktu w Historii + + Buy and sell + Kupno i Sprzedaż - libs/ui/src/lib/benchmark/benchmark.component.html - 81 + libs/ui/src/lib/i18n.ts + 8 - - from ATH - od ATH - - libs/ui/src/lib/benchmark/benchmark.component.html + + Delete Activities + Usuń aktywności + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internacjonalizacja + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + Czy na pewno chcesz zamknąć swoje konto Ghostfolio? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Strefa Zagrożenia + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Zamknij Konto + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Wg. Holdingu ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Przybliżenie oparte na najwyższych aktywach każdego funduszu ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Dołącz teraz lub sprawdź przykładowe konto + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + Ups! Wystąpił błąd podczas konfigurowania uwierzytelniania biometrycznego. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Pokaż więcej + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Punkty Odniesienia + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Usuń Profile + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Czy na pewno chcesz usunąć te profile? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + Ups! Nie udało się usunąć profili. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + Tabela + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Wykres + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + Chcesz udoskonalić swoją osobistą strategię inwestycyjną? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternatywa + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + Aplikacja + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Budżetowanie + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Społeczność + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts 83 - - Market data provided by - Dane rynkowe dostarczone przez + + Family Office + Biuro Rodzinne + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Inwestor + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Otwarty Kod Źródłowy + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Finanse Osobiste + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Prywatność + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Oprogramowanie + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Narzędzie + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Doświadczenie Użytkownika + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Majątek + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Zarządzanie Majątkiem + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Australia + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Austria + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Belgia + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bułgaria + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Kanada + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + Czechy + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finlandia + + libs/ui/src/lib/i18n.ts + 83 + + + + France + Francja + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Niemcy + + libs/ui/src/lib/i18n.ts + 85 + + + + India + Indie + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Włochy - libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html - 2 + libs/ui/src/lib/i18n.ts + 88 - - Savings Rate per Month - Miesięczna stopa oszczędności + + Netherlands + Holandia - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 10 + libs/ui/src/lib/i18n.ts + 90 - - Annual Interest Rate - Roczna Stopa Procentowa + + New Zealand + Nowa Zelandia - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 21 + libs/ui/src/lib/i18n.ts + 91 - - Retirement Date - Data przejścia na emeryturę + + Poland + Polska - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 32 + libs/ui/src/lib/i18n.ts + 92 - - Projected Total Amount - Przewidywana Łączna Kwota + + Romania + Rumunia - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + libs/ui/src/lib/i18n.ts + 93 - - Interest - Udział + + South Africa + Południowa Afryka - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + libs/ui/src/lib/i18n.ts + 95 + + + Thailand + Tajlandia libs/ui/src/lib/i18n.ts - 38 + 97 - - Savings - Oszczędności + + United States + Stany Zjednoczone - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + libs/ui/src/lib/i18n.ts + 100 - - Allocation - Podział + + Error + Błąd - libs/ui/src/lib/holdings-table/holdings-table.component.html - 98 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + Deactivate + Dezaktywuj - libs/ui/src/lib/top-holdings/top-holdings.component.html - 40 + apps/client/src/app/components/rule/rule.component.html + 72 + + + Activate + Aktywuj - libs/ui/src/lib/top-holdings/top-holdings.component.html - 116 + apps/client/src/app/components/rule/rule.component.html + 74 - - Show all - Pokaż wszystko + + Inactive + Nieaktywny - libs/ui/src/lib/holdings-table/holdings-table.component.html - 197 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 - - Account - Konto + + Cancel + Anuluj - libs/ui/src/lib/i18n.ts - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - Asia-Pacific - Azja-Pacyfik - libs/ui/src/lib/i18n.ts - 5 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 - - - Asset Class - Rodzaj Aktywów libs/ui/src/lib/i18n.ts - 6 + 9 - - Asset Sub Class - Podklasa Aktywów + + Close + Zamknij + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + libs/ui/src/lib/i18n.ts - 7 + 11 - - Core - Główny + + Yes + Tak libs/ui/src/lib/i18n.ts - 10 + 32 - - Switch to Ghostfolio Premium or Ghostfolio Open Source easily - Przełącz się z łatwością na Ghostfolio Premium lub Ghostfolio Open Source + + Copy link to clipboard + Kopiuj link do schowka - libs/ui/src/lib/i18n.ts - 12 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - Switch to Ghostfolio Premium easily - Przełącz się z łatwością na Ghostfolio Premium + + Portfolio Snapshot + Przegląd portfela - libs/ui/src/lib/i18n.ts - 13 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Switch to Ghostfolio Open Source or Ghostfolio Basic easily - Przełącz się z łatwością na Ghostfolio Open Source lub Ghostfolio Basic + + Change with currency effect Change + Zmiana z efektem walutowym Zmiana - libs/ui/src/lib/i18n.ts - 14 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Emergency Fund - Fundusz Rezerwowy + + Performance with currency effect Performance + Wydajność z efektem walutowym Wydajność - libs/ui/src/lib/i18n.ts - 15 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Grant - Grant + + Threshold Min + Próg minimalny - libs/ui/src/lib/i18n.ts - 17 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Higher Risk - Wyższe Ryzyko + + Threshold Max + Próg maksymalny - libs/ui/src/lib/i18n.ts - 18 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - This activity already exists. - Ta działalność już istnieje. + + Customize + Dostosuj - libs/ui/src/lib/i18n.ts - 19 + apps/client/src/app/components/rule/rule.component.html + 67 - - Japan - Japonia + + No auto-renewal. + Bez automatycznego odnawiania. - libs/ui/src/lib/i18n.ts - 84 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 + + + + This year + W tym roku + + apps/client/src/app/pages/public/public-page.html + 42 - - Lower Risk - Niższe Ryzyko + + From the beginning + Od samego początku - libs/ui/src/lib/i18n.ts - 20 + apps/client/src/app/pages/public/public-page.html + 60 - - Month - Miesiąc + + Oops! Invalid currency. + Ups! Błędna waluta. - libs/ui/src/lib/i18n.ts - 21 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Months - Miesiące + + This page has been archived. + Ta strona została zarchiwizowana. - libs/ui/src/lib/i18n.ts - 22 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Other - Inne + + is Open Source Software + jest Oprogramowaniem Open Source - libs/ui/src/lib/i18n.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Preset - Preset + + is not Open Source Software + nie jest Oprogramowaniem Open Source - libs/ui/src/lib/i18n.ts - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Retirement Provision - Świadczenia Emerytalne - libs/ui/src/lib/i18n.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Satellite - Satelita + + can be self-hosted + może być hostowany samodzielnie - libs/ui/src/lib/i18n.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - - - Symbol - Symbol - libs/ui/src/lib/i18n.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Tag - Tag + + cannot be self-hosted + nie może być hostowany samodzielnie - libs/ui/src/lib/i18n.ts - 29 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Year - Rok - libs/ui/src/lib/i18n.ts - 30 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Years - Lata + + can be used anonymously + może być używany anonimowo - libs/ui/src/lib/i18n.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Buy - Zakup - libs/ui/src/lib/i18n.ts - 35 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Fee - Opłata + + cannot be used anonymously + nie może być używany anonimowo - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - Valuable - Kosztowności - libs/ui/src/lib/i18n.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Liability - Zobowiązanie + + offers a free plan + oferuje darmowy plan - libs/ui/src/lib/i18n.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Sell - Sprzedaj - libs/ui/src/lib/i18n.ts - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Cash - Gotówka + + does not offer a free plan + nie oferuje darmowego planu - libs/ui/src/lib/i18n.ts - 44 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - Commodity - Towar - libs/ui/src/lib/i18n.ts - 45 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Equity - Kapitał + + Oops! Could not find any assets. + Ups! Nie znaleziono żadnych aktywów. - libs/ui/src/lib/i18n.ts - 46 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - Fixed Income - Stały Dochód + + Data Providers + Dostawcy danych - libs/ui/src/lib/i18n.ts - 47 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Real Estate - Nieruchomość + + Set API key + Skonfiguruj klucz API - libs/ui/src/lib/i18n.ts - 49 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Bond - Obligacja + + Get access to 80’000+ tickers from over 50 exchanges + Uzyskaj dostęp do ponad 80 000 pasków notowań giełdowych z ponad 50 giełd libs/ui/src/lib/i18n.ts - 52 + 24 - - Cryptocurrency - Kryptowaluta + + Ukraine + Ukraina libs/ui/src/lib/i18n.ts - 53 + 98 - - ETF - ETF + + Join now + Dołącz teraz - libs/ui/src/lib/i18n.ts - 54 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Mutual Fund - Fundusz Wzajemny + + Glossary + Słowniczek - libs/ui/src/lib/i18n.ts - 55 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - Precious Metal - Metal Szlachetny - libs/ui/src/lib/i18n.ts - 56 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Private Equity - Prywatny Kapitał - libs/ui/src/lib/i18n.ts - 57 + libs/common/src/lib/routes/routes.ts + 293 - - Stock - Akcje + + Guides + Poradniki - libs/ui/src/lib/i18n.ts - 58 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Africa - Afryka - libs/ui/src/lib/i18n.ts - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Asia - Azja - libs/ui/src/lib/i18n.ts - 66 + libs/common/src/lib/routes/routes.ts + 301 - - Europe - Europa + + guides + poradniki + kebab-case - libs/ui/src/lib/i18n.ts - 67 + libs/common/src/lib/routes/routes.ts + 296 - - - North America - Ameryka Północna - libs/ui/src/lib/i18n.ts - 68 + libs/common/src/lib/routes/routes.ts + 299 - - Oceania - Oceania + + glossary + slowniczek + kebab-case - libs/ui/src/lib/i18n.ts - 69 + libs/common/src/lib/routes/routes.ts + 288 - - - South America - Ameryka Południowa - libs/ui/src/lib/i18n.ts - 70 + libs/common/src/lib/routes/routes.ts + 291 - - Extreme Fear - Skrajny Strach + + Threshold range + Zakres progów - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Extreme Greed - Skrajna Zachłanność + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray wykorzystuje analizę statyczną do wykrywania potencjalnych problemów i zagrożeń w portfelu. Dostosuj poniższe zasady i ustaw niestandardowe progi, aby dostosować je do osobistej strategii inwestycyjnej. - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Neutral - Neutralny + + Economic Market Cluster Risks + Ryzyko związane z klastrem rynków gospodarczych - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - Membership - Członkostwo + + of + z - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Valid until - Ważność do + + daily requests + codzienne żądania apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 137 + + + Remove API key + Usuń klucz API - libs/ui/src/lib/membership-card/membership-card.component.html - 42 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Time to add your first activity. - Czas dodać Twoją pierwszą działalność. + + Do you really want to delete the API key? + Czy na pewno chcesz usunąć klucz API?? - libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html - 12 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - No data available - Brak danych + + Please enter your Ghostfolio API key: + Wprowadź swój klucz API konta Ghostfolio: - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + apps/client/src/app/pages/api/api-page.component.ts + 41 + + + API Requests Today + Dzisiejsze Zapytania API - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - 50-Day Trend - 50-Dniowy Trend + + Could not generate an API key + Nie udało się wygenerować klucza API - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - 200-Day Trend - 200-Dniowy Trend + + Set this API key in your self-hosted environment: + Ustaw ten klucz API w samodzielnie hostowanym środowisku: - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - Cash Balances - Salda Gotówkowe + + Ghostfolio Premium Data Provider API Key + Klucz API dostawcy danych Premium Ghostfolio - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - Starting from - Począwszy od + + Do you really want to generate a new API key? + Czy na pewno chcesz wygenerować nowy klucz API? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 + + + API Key + Klucz API - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - year - rok + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Generowanie klucza API Ghostfolio Premium Data Provider dla środowisk hostowanych samodzielnie... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 + + + out of + poza - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - Do you really want to delete this account balance? - Czy na pewno chcesz usunąć saldo tego konta? + + rules align with your portfolio. + zasady zgodne z Twoim portfelem. - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - is an invalid currency! - to nieprawidłowa waluta! + + Save + Zapisz - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - - - If a translation is missing, kindly support us in extending it here. - Jeżeli brakuje jakiegoś tłumaczenia, uprzejmie prosimy o wsparcie w jego uzupełnieniu tutaj. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - The current market price is - Obecna cena rynkowa wynosi - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - Test - Test - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 - - - Date Range - Zakres Dat - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Permission - Pozwolenie - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 + + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + 65 - - - Restricted view - Ograniczony widok - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Oops! Could not grant access. - Ups! Nie udało się przyznać dostępu. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Private - Prywatny + + Asset Class Cluster Risks + Ryzyko klastra klasy aktywów - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Job Queue - Kolejka Zadań + + Me + Ja - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Market data is delayed for - Dane rynkowe są opóźnione o + + Received Access + Otrzymany dostęp - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Investment - Inwestycje + + Please enter your Ghostfolio API key. + Wprowadź swój klucz API Ghostfolio. - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 + + + AI prompt has been copied to the clipboard + Prompt AI został skopiowany do schowka apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 197 + + + Link has been copied to the clipboard + Link został skopiowany do schowka - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Absolute Asset Performance - Łączny wynik aktywów + + Regional Market Cluster Risks + Ryzyka klastrów regionalnych rynków - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Asset Performance - Wyniki aktywów + + Lazy + Leniwy - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Absolute Currency Performance - Łączny wynik walut + + Instant + Natychmiastowy - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Currency Performance - Wynik walut + + Default Market Price + Domyślna cena rynkowa - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Absolute Net Performance - Łączna wartość netto + + Mode + Tryb - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Net Performance - Wynik netto + + Selector + Selektor - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Week to date - Dotychczasowy tydzień + + HTTP Request Headers + Nagłówki żądań HTTP - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - WTD - WTD + + end of day + koniec dnia - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Month to date - Od początku miesiąca + + real-time + w czasie rzeczywistym - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - MTD - MTD + + Open Duck.ai + Otwórz Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Year to date - Od początku roku + + Create + Stwórz - libs/ui/src/lib/assistant/assistant.component.ts - 231 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - View - Widok + + Change + Zmiana - apps/client/src/app/components/access-table/access-table.component.html - 23 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Oops! A data provider is experiencing the hiccups. - Ups! Dostawca danych zmaga się teraz z drobnymi przeszkodami. + + Performance + Wydajność - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Jeśli przejdziesz na emeryturę dzisiaj, będziesz mógł wypłacić rocznie lub miesięcznie, w oparciu o Twój łączny majątek w wysokości i stopę wypłaty w wysokości 4%. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Reset Filters - Resetuj Filtry - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - year - rok - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - - years - lata - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Apply Filters - Zastosuj Filtry + + Copy portfolio data to clipboard for AI prompt + Skopiuj dane portfela do schowka dla prompta AI - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - Data Gathering - Gromadzenie Danych + + Copy AI prompt to clipboard for analysis + Skopiuj prompt AI do schowka w celu analizy - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - General - Informacje Ogólne + + Armenia + Armenia - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/i18n.ts + 75 - - Cloud - Rozwiązanie w Chmurze - - apps/client/src/app/pages/faq/faq-page.component.ts - 41 - + + British Virgin Islands + Brytyjskie Wyspy Dziewicze - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 79 - - Self-Hosting - Własny Hosting - - apps/client/src/app/pages/faq/faq-page.component.ts - 47 - + + Singapore + Singapur - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - self-hosting - self-hosting + + Terms and Conditions + Zasady i Warunki użytkownia - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - FAQ - FAQ + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Przechowuj swój Token Bezpieczeństwa w bezpiecznym miejscu. Jeśli go zgubisz, nie będziesz mógł odzyskać swojego konta. - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 + + + I understand that if I lose my security token, I cannot recover my account + Rozumiem, że jeśli utracę token zabezpieczający, nie będę mógł odzyskać konta - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Ups! Wygląda na to, że wykonujesz zbyt wiele zapytań. Proszę, zwolnij trochę. + + Continue + Kontynuuj - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - My Account - Moje Konto + + Here is your security token. It is only visible once, please store and keep it in a safe place. + To twój Token Bezpieczeństwa. JEST ON WIDOCZNY TYLKO RAZ! Przechowuj go w bezpiecznym miejscu. - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Active - Antywne + + Security token + Token bezpieczeństwa - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Closed - Zamknięte - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Activity - Aktywność + + Do you really want to generate a new security token for this user? + Czy napewno chcesz wygenerować nowy token bezpieczeństwa dla tego użytkownika? - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - Dividend Yield - Dochód z Dywidendy + + Generate Security Token + Generowanie Tokena Zabezpieczającego - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Execute Job - Wykonaj Zadanie + + United Kingdom + Wielka Brytania - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + libs/ui/src/lib/i18n.ts + 99 - - Priority - Priorytet + + Terms of Service + Warunki świadczenia usług - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - This action is not allowed. - To działanie jest niedozwolone. + + terms-of-service + warunki-swiadczenia-uslug + kebab-case - apps/client/src/app/core/http-response.interceptor.ts - 61 + libs/common/src/lib/routes/routes.ts + 212 - - - Liquidity - Płynność środków finansowych - libs/ui/src/lib/i18n.ts - 48 + libs/common/src/lib/routes/routes.ts + 215 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + Terms of Service + Warunki świadczenia usług - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/app.component.html + 112 - - - Buy and sell - Kupno i Sprzedaż - libs/ui/src/lib/i18n.ts - 8 + libs/common/src/lib/routes/routes.ts + 217 - - Delete Activities - Usuń aktywności + + and I agree to the Terms of Service. + i zgadzam się na Warunki świadczenia usług. - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Internationalization - Internacjonalizacja + + () is already in use. + () jest już w użyciu. - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Do you really want to close your Ghostfolio account? - Czy na pewno chcesz zamknąć swoje konto Ghostfolio? + + An error occurred while updating to (). + Wystąpił błąd podczas aktualizacji do (). - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Danger Zone - Strefa Zagrożenia + + Apply + Zatwierdź - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Close Account - Zamknij Konto + + with API access for + z dostępem API dla - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - By ETF Holding - Wg. Holdingu ETF + + Gather Recent Historical Market Data + Zbierz najnowsze historyczne dane rynkowe - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Approximation based on the top holdings of each ETF - Przybliżenie oparte na najwyższych aktywach każdego funduszu ETF + + Gather All Historical Market Data + Zbierz wszystkie historyczne dane rynkowe - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Join now or check out the example account - Dołącz teraz lub sprawdź przykładowe konto + + Gather Historical Market Data + Zbierz historyczne dane rynkowe - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Oops! There was an error setting up biometric authentication. - Ups! Wystąpił błąd podczas konfigurowania uwierzytelniania biometrycznego. + + Data Gathering is off + Zbieranie danych jest wyłączone - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Show more - Pokaż więcej + + Performance Calculation + Obliczanie wydajności - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Benchmarks - Punkty Odniesienia + + someone + ktoś - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Delete Profiles - Usuń Profile + + Add asset to watchlist + Dodaj zasób do listy obserwowanych - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Do you really want to delete these profiles? - Czy na pewno chcesz usunąć te profile? + + Watchlist + Lista obserwowanych - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Oops! Could not delete profiles. - Ups! Nie udało się usunąć profili. - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/pages/features/features-page.html + 197 - - - Table - Tabela - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + libs/common/src/lib/routes/routes.ts + 110 - - Chart - Wykres + + Do you really want to delete this item? + Czy na pewno chcesz usunąć ten element? - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Would you like to refine your personal investment strategy? - Chcesz udoskonalić swoją osobistą strategię inwestycyjną? + + Log out + Wyloguj się - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/components/header/header.component.html + 329 - - Alternative - Alternatywa + + Calculations are based on delayed market data and may not be displayed in real-time. + Obliczenia opierają się na opóźnionych danych rynkowych i mogą nie być wyświetlane w czasie rzeczywistym. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/home-market/home-market.html + 44 - - - App - Aplikacja - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/markets/markets.html + 53 - - Budgeting - Budżetowanie + + changelog + dziennik-zmian + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 180 - - - Community - Społeczność - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 183 - - Family Office - Biuro Rodzinne + + Demo user account has been synced. + Konto użytkownika demonstracyjnego zostało zsynchronizowane. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Investor - Inwestor + + Sync Demo User Account + Synchronizuj konto użytkownika demonstracyjnego - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Open Source - Otwarty Kod Źródłowy + + Set up + Fundusz awaryjny: Utworzenie - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Personal Finance - Finanse Osobiste + + No emergency fund has been set up + Nie utworzono funduszu awaryjnego - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Privacy - Prywatność + + An emergency fund has been set up + Utworzono fundusz awaryjny - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Software - Oprogramowanie + + Fee Ratio + Stosunek opłat - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Tool - Narzędzie + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Opłaty przekraczają ${thresholdMax}% początkowej inwestycji (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - User Experience - Doświadczenie Użytkownika + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Opłaty nie przekraczają ${thresholdMax}% początkowej inwestycji (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - Wealth - Majątek + + Name + Nazwa - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth Management - Zarządzanie Majątkiem + + Find holding or page... + Znajdź gospodarstwo lub stronę... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Australia - Australia + + Quick Links + Szybkie linki - libs/ui/src/lib/i18n.ts - 73 + libs/ui/src/lib/assistant/assistant.html + 56 - - Austria - Austria + + Asset Profiles + Profile zasobów - libs/ui/src/lib/i18n.ts - 74 + libs/ui/src/lib/assistant/assistant.html + 112 - - Belgium - Belgia + + Live Demo + Live Demo - libs/ui/src/lib/i18n.ts - 75 + apps/client/src/app/pages/landing/landing-page.html + 49 + + + apps/client/src/app/pages/landing/landing-page.html + 452 + + + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bułgaria + + Open Source Alternative to + Alternatywa Open Source dla - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Kanada + + Single Account + Single Account - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - Czechy + + Your net worth is managed by a single account + Your net worth is managed by a single account - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finlandia + + Your net worth is managed by ${accountsLength} accounts + Your net worth is managed by ${accountsLength} accounts - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - Francja + + personal-finance-tools + personal-finance-tools + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 + + + libs/common/src/lib/routes/routes.ts + 315 - - - Germany - Niemcy - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 323 - - India - Indie + + markets + markets + kebab-case - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 304 - - - Italy - Włochy - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 307 - - Netherlands - Holandia + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 85 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - New Zealand - Nowa Zelandia + + Get Access + Get Access - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Poland - Polska + + Learn more + Learn more - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - Romania - Rumunia + + Limited Offer! + Limited Offer! - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - South Africa - Południowa Afryka + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Thailand - Tajlandia + + Available + Available - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - United States - Stany Zjednoczone + + Unavailable + Unavailable - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Error - Błąd + + new + new - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Deactivate - Dezaktywuj - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Activate - Aktywuj + + Investment + Investment - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Inactive - Nieaktywny + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Cancel - Anuluj + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Close - Zamknij + + Equity + Equity - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Yes - Tak + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Copy link to clipboard - Kopiuj link do schowka + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Portfolio Snapshot - Przegląd portfela + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Change with currency effect Change - Change with currency effect Change + + Fixed Income + Fixed Income - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Performance with currency effect Performance - Performance with currency effect Performance + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Min - Próg minimalny + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Threshold Max - Próg maksymalny + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Close - Zamknij + + Investment: Base Currency + Investment: Base Currency - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - Customize - Dostosuj + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - No auto-renewal. - Bez automatycznego odnawiania. + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - Today - Dzisiaj + + Investment + Investment - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - This year - W tym roku + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - From the beginning - Od samego początku + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - Oops! Invalid currency. - Ups! Błędna waluta. + + start + start + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + libs/common/src/lib/routes/routes.ts + 336 - - - This page has been archived. - Ta strona została zarchiwizowana. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 337 - - is Open Source Software - jest Oprogramowaniem Open Source + + Do you really want to generate a new security token? + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is not Open Source Software - nie jest Oprogramowaniem Open Source + + Generate + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is Open Source Software - jest Oprogramowaniem Open Source + + Stocks + Stocks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - is not Open Source Software - nie jest Oprogramowaniem Open Source - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/pages/features/features-page.html + 15 - - can be self-hosted - może być hostowany samodzielnie + + Cryptocurrencies + Cryptocurrencies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - cannot be self-hosted - nie może być hostowany samodzielnie - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - może być hostowany samodzielnie + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - nie może być hostowany samodzielnie + + Manage Asset Profile + Manage Asset Profile - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - może być używany anonimowo + + Alternative Investment + Alternative Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - nie może być używany anonimowo + + Collectible + Collectible - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - może być używany anonimowo + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - nie może być używany anonimowo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - oferuje darmowy plan + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - nie oferuje darmowego planu + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - oferuje darmowy plan + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - nie oferuje darmowego planu + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Ups! Nie znaleziono żadnych aktywów. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Dostawcy danych + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NOWOŚĆ + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Skonfiguruj klucz API + + No results found... + No results found... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Chcesz być na bieżąco? Kliknij poniżej, aby otrzymać powiadomienie, gdy tylko będzie dostępne. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Uzyskaj dostęp do ponad 100 000 pasków notowań giełdowych z ponad 50 giełd + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraina + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Pomiń + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Dołącz teraz + + Emerging Markets + Emerging Markets - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Słowniczek + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Poradniki + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - poradniki - snake-case + + Your net worth is managed by 0 accounts + Your net worth is managed by 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - slowniczek - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Zakres progów + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray wykorzystuje analizę statyczną do wykrywania potencjalnych problemów i zagrożeń w portfelu. Dostosuj poniższe zasady i ustaw niestandardowe progi, aby dostosować je do osobistej strategii inwestycyjnej. + + Emerging Markets + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Ryzyko związane z klastrem rynków gospodarczych + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - z + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - codzienne żądania + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Usuń klucz API + + Europe + Europe - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Czy na pewno chcesz usunąć klucz API?? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Wprowadź swój klucz API konta Ghostfolio: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Powiadom mnie + + Japan + Japan - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - Posiadam klucz API + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - Dzisiejsze Zapytania API + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Nie udało się wygenerować klucza API + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Ustaw ten klucz API w samodzielnie hostowanym środowisku: + + North America + North America - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Klucz API dostawcy danych Premium Ghostfolio + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Czy na pewno chcesz wygenerować nowy klucz API? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - Klucz API + + Find Ghostfolio on GitHub + Find Ghostfolio on GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generowanie klucza API Ghostfolio Premium Data Provider dla środowisk hostowanych samodzielnie... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - poza + + Join the Ghostfolio Slack community + Join the Ghostfolio Slack community - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - zasady zgodne z Twoim portfelem. + + Follow Ghostfolio on X (formerly Twitter) + Follow Ghostfolio on X (formerly Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Zapisz + + Send an e-mail + Send an e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Ryzyko klastra klasy aktywów + + Follow Ghostfolio on LinkedIn + Follow Ghostfolio on LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Support Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 3ad4c089e..646e45510 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -1,15 +1,15 @@ - + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. O risco de perda em investimentos pode ser substancial. Não é aconselhável investir dinheiro que possa vir a precisar a curto prazo. apps/client/src/app/app.component.html - 200 + 221 - + Alias Alias @@ -21,7 +21,7 @@ 11 - + Grantee Beneficiário (a) @@ -29,7 +29,7 @@ 11 - + Type Tipo @@ -49,7 +49,7 @@ 161 - + Details Detalhes @@ -57,7 +57,7 @@ 33 - + Revoke Revogar @@ -70,10 +70,10 @@ Pretende realmente revogar este acesso concedido? apps/client/src/app/components/access-table/access-table.component.ts - 67 + 108 - + Platform Plataforma @@ -89,47 +89,7 @@ 48 - - Activities - Atividades - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 - - - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 - - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 - - - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 - - - apps/client/src/app/components/admin-users/admin-users.html - 135 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 - - - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 - - - + Name Nome @@ -138,23 +98,27 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + 89 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 289 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 22 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html 15 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 22 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -166,7 +130,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 139 libs/ui/src/lib/activities-table/activities-table.component.html @@ -185,7 +149,7 @@ 88 - + Total Total @@ -193,7 +157,7 @@ 55 - + Currency Moeda @@ -202,11 +166,11 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + 187 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + 296 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -218,14 +182,14 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 145 libs/ui/src/lib/activities-table/activities-table.component.html 276 - + Cash Balance Saldo disponível em dinheiro @@ -241,7 +205,7 @@ 34 - + Value Valor @@ -258,31 +222,15 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + 205 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + 208 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + 211 libs/ui/src/lib/account-balances/account-balances.component.html @@ -309,64 +257,56 @@ 102 - + Edit Editar apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + 307 apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + 268 apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + 74 apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + 67 libs/ui/src/lib/activities-table/activities-table.component.html 430 - + Delete Eliminar apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + 318 apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + 290 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 - - - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + 64 apps/client/src/app/components/admin-overview/admin-overview.html - 206 + 131 apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + 85 apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + 78 libs/ui/src/lib/account-balances/account-balances.component.html @@ -376,40 +316,20 @@ libs/ui/src/lib/activities-table/activities-table.component.html 457 + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + Do you really want to delete this account? Pretende realmente eliminar esta conta? apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 - - - - Symbol - Símbolo - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + 148 - + Data Source Fonte de dados @@ -418,18 +338,18 @@ apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + 106 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + 165 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 155 - + Attempts Tentativas @@ -437,7 +357,7 @@ 83 - + Created Criado @@ -445,7 +365,7 @@ 92 - + Finished Terminado @@ -453,15 +373,19 @@ 101 - + Status Estado apps/client/src/app/components/admin-jobs/admin-jobs.html 110 + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + - + Delete Jobs Eliminar Tarefas @@ -469,23 +393,27 @@ 151 - + Asset Profiles Perfil de Ativos - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - + Historical Market Data Histórico de Dados de Mercado apps/client/src/app/components/admin-jobs/admin-jobs.html 37 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + - + View Data Visualizar dados @@ -493,7 +421,7 @@ 166 - + View Stacktrace Ver Stacktrace @@ -501,7 +429,7 @@ 173 - + Delete Job Apagar Tarefa @@ -509,7 +437,7 @@ 180 - + Details for Detalhes para @@ -517,12 +445,12 @@ 2 - + Date Data apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 161 libs/ui/src/lib/account-balances/account-balances.component.html @@ -537,291 +465,123 @@ 6 - + Market Price Preço de Mercado apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + 133 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + 111 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 26 - - Cancel - Cancelar + + Filter by... + Filtrar por... - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + Primeira Atividade - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 + + + Activity Count + Número de Atividades - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + Historical Data + Dados Históricos - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 + + + Countries Count + Contagem de Países - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 + + + Sectors Count + Contagem de Setores - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 - - Save - Guardar + + Gather Profile Data + Recolher Dados de Perfíl - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 + + + Do you really want to delete this coupon? + Deseja realmente eliminar este cupão? - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + Do you really want to flush the cache? + Deseja realmente limpar a cache? - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 + + + Please set your system message: + Por favor, defina a sua mensagem do sistema: - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 - - - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 - - - - Filter by... - Filtrar por... - - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 - - - - Asset Class - Classe do Ativo - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 - - - libs/ui/src/lib/assistant/assistant.html - 166 - - - - Asset Sub Class - Subclasse do ativo - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 - - - - First Activity - Primeira Atividade - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 - - - - Activity Count - Número de Atividades - - apps/client/src/app/components/admin-overview/admin-overview.html - 19 - - - - Historical Data - Dados Históricos - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 - - - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 - - - - Countries Count - Contagem de Países - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 - - - - Sectors Count - Contagem de Setores - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 - - - - Gather Recent Data - Atualizar dados mais recentes - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 - - - - Gather All Data - Recolher Todos os Dados - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 - - - - Gather Profile Data - Recolher Dados de Perfíl - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 - - - - Please add a currency: - Por favor, adicione uma moeda: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 - - - - Do you really want to delete this coupon? - Deseja realmente eliminar este cupão? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 - - - - Do you really want to delete this currency? - Deseja realmente excluir esta moeda? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 - - - - Do you really want to flush the cache? - Deseja realmente limpar a cache? - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 - - - - Please set your system message: - Por favor, defina a sua mensagem do sistema: - - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 - + User Count Número de Utilizadores @@ -829,7 +589,7 @@ 13 - + per User por Utilizador @@ -837,84 +597,72 @@ 28 - - Exchange Rates - Taxas de Câmbio - - apps/client/src/app/components/admin-overview/admin-overview.html - 34 - - - + Add Currency Adicionar Moeda apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 22 - - apps/client/src/app/components/admin-overview/admin-overview.html - 105 - - + System Message Mensagem de Sistema apps/client/src/app/components/admin-overview/admin-overview.html - 149 + 72 - + Set Message Definir Mensagem apps/client/src/app/components/admin-overview/admin-overview.html - 171 + 94 - + Read-only Mode Modo Somente Leitura apps/client/src/app/components/admin-overview/admin-overview.html - 125 + 48 - + Coupons Cupões apps/client/src/app/components/admin-overview/admin-overview.html - 179 + 102 - + Add Adicionar apps/client/src/app/components/admin-overview/admin-overview.html - 239 + 176 libs/ui/src/lib/account-balances/account-balances.component.html 93 - + Housekeeping Manutenção apps/client/src/app/components/admin-overview/admin-overview.html - 247 + 184 - + Flush Cache Limpar Cache apps/client/src/app/components/admin-overview/admin-overview.html - 251 + 200 @@ -922,86 +670,38 @@ Deseja realmente excluir este utilizador? apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + 177 - + User Utilizador apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 - - - apps/client/src/app/components/header/header.component.html - 229 - - - - Registration - Registo - - apps/client/src/app/components/admin-users/admin-users.html - 97 - - - - Accounts - Contas - - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 - - - apps/client/src/app/components/admin-users/admin-users.html - 114 - - - apps/client/src/app/components/header/header.component.html - 54 + 31 apps/client/src/app/components/header/header.component.html - 263 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 - - - apps/client/src/app/pages/accounts/accounts-page.html - 4 + 231 - + Engagement per Day Envolvimento por Dia apps/client/src/app/components/admin-users/admin-users.html - 157 + 158 - + Last Request Último Pedido apps/client/src/app/components/admin-users/admin-users.html - 202 - - - - Performance - Desempenho - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 - - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + 204 - + Compare with... Comparar com... @@ -1014,223 +714,87 @@ Portefólio apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 - - - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 - - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 - - - - Benchmark - Referência - - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 - - - - Current Market Mood - Tom do Mercado Atual - - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 - - - - Overview - Visão geral - - apps/client/src/app/components/header/header.component.html - 28 - - - apps/client/src/app/components/header/header.component.html - 245 - - - - Portfolio - Portefólio - - apps/client/src/app/components/header/header.component.html - 41 - - - apps/client/src/app/components/header/header.component.html - 255 - - - - Admin Control - Controlo Administrativo - - apps/client/src/app/components/header/header.component.html - 68 - - - apps/client/src/app/components/header/header.component.html - 279 - - - - Resources - Recursos - - apps/client/src/app/app.component.html - 64 - - - apps/client/src/app/components/header/header.component.html - 82 + 124 apps/client/src/app/components/header/header.component.html - 291 - - - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 - - - - Pricing - Preços - - apps/client/src/app/app.component.html - 97 - - - apps/client/src/app/components/header/header.component.html - 99 + 44 apps/client/src/app/components/header/header.component.html - 303 + 258 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + libs/common/src/lib/routes/routes.ts + 151 - - About - Sobre - - apps/client/src/app/app.component.html - 70 - - - apps/client/src/app/components/header/header.component.html - 117 - + + Benchmark + Referência - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 - - - Me - Eu - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 - - My Ghostfolio - O meu Ghostfolio + + Current Market Mood + Tom do Mercado Atual - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 - + About Ghostfolio Sobre o Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 326 apps/client/src/app/pages/about/overview/about-overview-page.html 5 - - Features - Funcionalidades - - apps/client/src/app/app.component.html - 79 - - - apps/client/src/app/components/header/header.component.html - 351 - - - apps/client/src/app/pages/features/features-page.html - 5 - - - - Markets - Mercados - - apps/client/src/app/app.component.html - 61 - + + Get started + Começar apps/client/src/app/components/header/header.component.html - 398 - - - apps/client/src/app/components/home-market/home-market.html - 2 - - - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + 432 - + Sign in Iniciar sessão apps/client/src/app/components/header/header.component.html - 412 + 422 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + apps/client/src/app/components/header/header.component.ts + 259 - - - Get started - Começar - apps/client/src/app/components/header/header.component.html - 422 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - - - Sign in - Iniciar sessão - apps/client/src/app/app-routing.module.ts - 150 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/components/header/header.component.ts - 230 + libs/common/src/lib/routes/routes.ts + 157 @@ -1238,19 +802,23 @@ Oops! Token de Segurança Incorreto. apps/client/src/app/components/header/header.component.ts - 245 + 274 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + 191 - + Manage Activities Gerir Atividades apps/client/src/app/components/home-holdings/home-holdings.html - 63 + 66 @@ -1258,11 +826,15 @@ Medo apps/client/src/app/components/home-market/home-market.component.ts - 27 + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 libs/ui/src/lib/i18n.ts - 98 + 105 @@ -1270,27 +842,27 @@ Ganância apps/client/src/app/components/home-market/home-market.component.ts - 28 + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 libs/ui/src/lib/i18n.ts - 99 + 106 - + Last Days Últimos Dias apps/client/src/app/components/home-market/home-market.html 7 - - - Summary - Resumo - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/components/markets/markets.html + 17 @@ -1298,7 +870,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + 360 @@ -1306,7 +878,7 @@ Valor Total apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + 141 @@ -1314,43 +886,55 @@ Taxa de Poupança apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + 200 - + Security Token Token de Segurança apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html 11 + + apps/client/src/app/components/user-account-access/user-account-access.html + 3 + + + apps/client/src/app/components/user-account-access/user-account-access.html + 15 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 + 279 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + 64 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - + or ou - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + 32 apps/client/src/app/pages/landing/landing-page.html - 47 + 48 apps/client/src/app/pages/landing/landing-page.html - 450 + 451 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1358,14 +942,14 @@ apps/client/src/app/pages/register/register-page.html - 30 + 31 apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + 30 - + Sign in with Internet Identity Iniciar sessão com Internet Identity @@ -1373,7 +957,7 @@ 42 - + Sign in with Google Iniciar sessão com Google @@ -1381,7 +965,7 @@ 52 - + Stay signed in Manter sessão iniciada @@ -1389,7 +973,7 @@ 61 - + Time in Market Tempo no Mercado @@ -1397,59 +981,31 @@ 3 - - Buy - Compra + + Absolute Gross Performance + Desempenho Bruto Absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + 70 - - Sell - Venda + + Absolute Net Performance + Desempenho Líquido Absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + 102 - - Investment - Investimento - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 - - - - Absolute Gross Performance - Desempenho Bruto Absoluto - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 - - - - Absolute Net Performance - Desempenho Líquido Absoluto - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 - - - - Net Performance - Desempenho Líquido + + Net Performance + Desempenho Líquido apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html 117 - + Total Assets Ativos Totais @@ -1457,237 +1013,173 @@ 143 - - Valuables - Bens de valor - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 - - - - Emergency Fund - Fundo de Emergência - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 - - - apps/client/src/app/pages/features/features-page.html - 89 - - - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 - - - + Buying Power Poder de Compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + 216 - + Excluded from Analysis Excluído da Análise apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + 228 - + Net Worth Valor Líquido apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + 261 - + Annualized Performance Desempenho Anual apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 - - - - Dividend - Dividendo - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 - - - apps/client/src/app/pages/features/features-page.html - 63 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + 274 Please set the amount of your emergency fund. - Por favor, insira o valor do seu fundo de emergência: + Por favor, insira o valor do seu fundo de emergência: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 - - - - Change - Alterar - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 - - - - Average Unit Price - Preço Médio por Unidade - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + 71 - + Minimum Price Preço Mínimo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 127 - + Maximum Price Preço Máximo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 143 - + Quantity Quantidade apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + 189 libs/ui/src/lib/activities-table/activities-table.component.html 186 - + Sector Setor apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + 242 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + 263 - + Country País apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + 253 apps/client/src/app/components/admin-users/admin-users.html - 77 + 78 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + 273 - + Sectors Setores apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + 259 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 492 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + 279 apps/client/src/app/pages/public/public-page.html 106 - + Countries Países apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + 269 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 503 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + 291 - + Tags Marcadores apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 - + Report Data Glitch Dados do Relatório com Problema apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 446 - + Allocation Alocação + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + libs/ui/src/lib/holdings-table/holdings-table.component.html 98 @@ -1701,7 +1193,7 @@ 116 - + Show all Mostrar tudo @@ -1713,60 +1205,44 @@ Today Hoje - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/public/public-page.html + 24 libs/ui/src/lib/assistant/assistant.component.ts - 221 + 348 YTD AATD - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + 360 1Y 1A - - apps/client/src/app/components/toggle/toggle.component.ts - 23 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + 370 5Y 5A - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + 395 Max Máx - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts - 260 + 401 @@ -1774,7 +1250,7 @@ Esta funcionalidade está atualmente indisponível. apps/client/src/app/core/http-response.interceptor.ts - 53 + 55 @@ -1782,15 +1258,15 @@ Por favor tente novamente mais tarde. apps/client/src/app/core/http-response.interceptor.ts - 55 + 57 apps/client/src/app/core/http-response.interceptor.ts - 80 + 88 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + 186 @@ -1798,11 +1274,11 @@ Oops! Ocorreu um erro. apps/client/src/app/core/http-response.interceptor.ts - 78 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 184 @@ -1810,86 +1286,66 @@ OK apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + 154 apps/client/src/app/core/http-response.interceptor.ts - 81 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 187 About Sobre - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - - - apps/client/src/app/pages/about/about-page.component.ts - 44 - - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - - Changelog - Changelog apps/client/src/app/app.component.html - 77 - - - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + 70 - - - License - Licença - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/header/header.component.html + 375 - - - Privacy Policy - Política de Privacidade - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 220 - + Privacy Policy Política de Privacidade apps/client/src/app/app.component.html - 103 + 105 apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html 4 + + libs/common/src/lib/routes/routes.ts + 209 + My Ghostfolio O meu Ghostfolio - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts 33 @@ -1898,15 +1354,19 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + 69 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 - - Please enter your coupon code: + + Please enter your coupon code. Por favor, insira o seu código de cupão: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + 215 @@ -1914,7 +1374,7 @@ Não foi possível resgatar o código de cupão apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + 179 @@ -1922,7 +1382,7 @@ Código de cupão foi resgatado apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + 192 @@ -1930,7 +1390,7 @@ Atualizar apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + 193 @@ -1938,174 +1398,142 @@ Deseja realmente remover este método de início de sessão? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 - - - - Account - Conta - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 308 - - - libs/ui/src/lib/assistant/assistant.html - 107 - - - - Membership - Filiação - - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + 280 - + per year por ano apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 274 + 283 - + Try Premium Experimentar Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 - + Redeem Coupon Resgatar Cupão apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 - + Presenter View Vista do Apresentador apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + 183 - + Base Currency Moeda Base apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + 9 - + Language Língua apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + 56 Users Utilizadores - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 61 - + Locale Localidade + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + 133 - + Date and number format Formato de números e datas apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + 135 - + Zen Mode Modo Zen apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + 201 apps/client/src/app/pages/features/features-page.html - 191 + 246 - + Appearance Aparência apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 - - - - Auto - Auto - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + 158 - + Light Claro apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + 173 - + Dark Escuro apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + 174 - + Sign in with fingerprint Iniciar sessão com impressão digital apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + 219 - + Experimental Features Funcionalidades Experimentais apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + 235 - + User ID ID do Utilizador @@ -2114,18 +1542,18 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + 252 - + Granted Access Acesso Concedido apps/client/src/app/components/user-account-access/user-account-access.html - 7 + 57 - + Grant access Conceder Acesso @@ -2133,7 +1561,7 @@ 7 - + Public Público @@ -2145,11 +1573,35 @@ Accounts Contas - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 + + + apps/client/src/app/components/admin-users/admin-users.html + 115 + + + apps/client/src/app/components/header/header.component.html + 58 + + + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 - + Update account Atualizar conta @@ -2157,7 +1609,7 @@ 8 - + Add account Adicionar conta @@ -2165,15 +1617,7 @@ 10 - - Cash - Dinheiro - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 - - - + Account ID ID da Conta @@ -2185,113 +1629,117 @@ Admin Control Controlo Administrativo - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/components/header/header.component.html + 74 - - - Blog - Blog - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 - + Blog Blog apps/client/src/app/app.component.html - 73 + 74 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + 205 apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + 185 apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + 210 apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + 197 apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + 182 apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + 142 apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + 169 apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + 179 apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + 203 apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + 254 apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + 234 apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + 244 apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + 155 apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + 274 apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + 184 apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + 149 apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + 271 apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + 190 apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + 168 apps/client/src/app/pages/blog/blog-page.html 5 + + libs/common/src/lib/routes/routes.ts + 225 + As you are already logged in, you cannot access the demo account. @@ -2305,83 +1753,163 @@ Frequently Asked Questions (FAQ) FAQ - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 Features Funcionalidades - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 Overview Visão geral - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/components/header/header.component.html + 30 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 apps/client/src/app/pages/resources/resources-page.component.ts - 16 + 30 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + libs/common/src/lib/routes/routes.ts + 113 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 170 Markets Mercados - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/components/home-market/home-market.html + 2 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 apps/client/src/app/pages/resources/resources-page.component.ts - 26 + 40 + + + libs/common/src/lib/routes/routes.ts + 95 + + + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 Activities Atividades - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 + + + apps/client/src/app/components/admin-users/admin-users.html + 136 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 + + + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 - + Update activity Atualizar atividade @@ -2389,12 +1917,12 @@ 10 - + Add activity Adicionar atividade apps/client/src/app/components/home-overview/home-overview.html - 52 + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -2404,61 +1932,53 @@ Sell Venda + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + libs/ui/src/lib/i18n.ts 41 - + Name, symbol or ISIN Nome, símbolo or ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 29 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 - - - - Unit Price - Preço por Unidade - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 210 + 124 - - Fee - Comissão - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - + + Unit Price + Preço por Unidade apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 214 libs/ui/src/lib/activities-table/activities-table.component.html - 234 + 210 - + Note Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 528 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2466,7 +1986,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 275 @@ -2474,7 +1994,7 @@ A importar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + 167 @@ -2482,10 +2002,10 @@ A importação foi concluída apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + 176 - + The following file formats are supported: Os seguintes formatos de ficheiro são suportados: @@ -2493,7 +2013,7 @@ 90 - + Back Anterior @@ -2509,23 +2029,19 @@ Allocations Alocações - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - - - Allocations - Alocações - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + libs/common/src/lib/routes/routes.ts + 133 - + Proportion of Net Worth Proporção do Valor Líquido @@ -2533,7 +2049,7 @@ 12 - + By Account Por Conta @@ -2541,7 +2057,7 @@ 286 - + By Currency Por Moeda @@ -2549,7 +2065,7 @@ 63 - + By Asset Class Por Classe de Ativo @@ -2557,7 +2073,7 @@ 85 - + By Holding Por Posse @@ -2565,7 +2081,7 @@ 107 - + By Sector Por Setor @@ -2573,7 +2089,7 @@ 130 - + By Continent Por Continente @@ -2581,7 +2097,7 @@ 153 - + By Country Por País @@ -2589,7 +2105,7 @@ 264 - + Regions Regiões @@ -2601,7 +2117,7 @@ 143 - + Developed Markets Mercados Desenvoldidos @@ -2613,7 +2129,7 @@ 160 - + Emerging Markets Mercados Emergentes @@ -2625,7 +2141,7 @@ 169 - + Other Markets Outros Mercados @@ -2641,12 +2157,12 @@ Analysis Análise - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 138 @@ -2654,50 +2170,42 @@ Mensalmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 - - - - Analysis - Análise - - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + 88 - + Top Topo apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + 239 - + Bottom Fundo apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + 288 - + Portfolio Evolution Evolução do Portefólio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + 341 - + Investment Timeline Cronograma de Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + 368 - + FIRE FIRE @@ -2705,7 +2213,7 @@ 4 - + Calculator Calculadora @@ -2713,7 +2221,7 @@ 7 - + 4% Rule Regra dos 4% @@ -2722,26 +2230,6 @@ - Holdings - Posições - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - Holdings Posições @@ -2756,36 +2244,64 @@ apps/client/src/app/pages/public/public-page.html 70 + + libs/common/src/lib/routes/routes.ts + 90 + + + libs/common/src/lib/routes/routes.ts + 167 + + + + Holdings + Posições libs/ui/src/lib/assistant/assistant.html - 46 + 82 Pricing Preços + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 - - - Hello, has shared a Portfolio with you! - Olá, partilhou um Portefólio consigo! - apps/client/src/app/pages/public/public-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 - - Currencies - Moedas + + Hello, has shared a Portfolio with you! + Olá, partilhou um Portefólio consigo! apps/client/src/app/pages/public/public-page.html - 88 + 5 - + Continents Continentes @@ -2793,20 +2309,20 @@ 124 - + Ghostfolio empowers you to keep track of your wealth. O Ghostfolio permite-lhe estar a par e gerir a sua riqueza. apps/client/src/app/pages/public/public-page.html - 215 + 216 - + Get Started Começar apps/client/src/app/pages/features/features-page.html - 303 + 320 apps/client/src/app/pages/public/public-page.html @@ -2817,11 +2333,15 @@ Registration Registo - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 - + Create Account Criar Conta @@ -2836,8 +2356,12 @@ apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 2 + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + - + Continue with Internet Identity Continuar com Internet Identity @@ -2845,7 +2369,7 @@ 42 - + Continue with Google Continuar com Google @@ -2853,39 +2377,39 @@ 53 - + Copy to clipboard Copiar para a área de transferência apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + 88 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - Concordo em como guardei o meu Token de Segurança acima num local seguro. Se o perder, não conseguirei recuperar a minha conta. + + Resources + Recursos - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/app.component.html + 64 - - - Agree and continue - Aceitar e continuar - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/components/header/header.component.html + 88 - - - Resources - Recursos - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 - + Oops, authentication has failed. Oops, a autenticação falhou. @@ -2893,7 +2417,7 @@ 19 - + Try again Tentar novamente @@ -2901,15 +2425,15 @@ 27 - + Go back to Home Page Voltar à Página Inicial apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + 33 - + Draft Rascunho @@ -2922,10 +2446,18 @@ Importar Atividades apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - + Export Activities Exportar Atividades @@ -2937,7 +2469,7 @@ 396 - + Export Drafts as ICS Exportar Rascunhos como ICS @@ -2949,7 +2481,7 @@ 409 - + Clone Clonar @@ -2957,7 +2489,7 @@ 436 - + Export Draft as ICS Exportar Rascunho como ICS @@ -2970,34 +2502,26 @@ Deseja realmente eliminar esta atividade? libs/ui/src/lib/activities-table/activities-table.component.ts - 229 - - - - Index - Índice - - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + 260 - + Change from All Time High Diferença desde o Máximo Histórico libs/ui/src/lib/benchmark/benchmark.component.html - 81 + 110 - + from ATH a partir do ATH (All Time High) libs/ui/src/lib/benchmark/benchmark.component.html - 83 + 112 - + Annual Interest Rate Taxa de Juro Anual @@ -3005,20 +2529,24 @@ 21 - + Projected Total Amount Montante Total Projetado libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 Interest Juros + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + 370 libs/ui/src/lib/i18n.ts @@ -3030,12 +2558,24 @@ Poupanças libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + 380 Account Conta + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + libs/ui/src/lib/i18n.ts 4 @@ -3044,6 +2584,30 @@ Asset Class Classe de Ativo + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + libs/ui/src/lib/i18n.ts 6 @@ -3052,6 +2616,18 @@ Emergency Fund Fundo de Emergência + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + libs/ui/src/lib/i18n.ts 15 @@ -3066,12 +2642,32 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + 412 Symbol Símbolo + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + libs/ui/src/lib/i18n.ts 28 @@ -3080,6 +2676,10 @@ Tag Marcador + + libs/ui/src/lib/assistant/assistant.html + 207 + libs/ui/src/lib/i18n.ts 29 @@ -3088,9 +2688,13 @@ Cash Dinheiro + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + libs/ui/src/lib/i18n.ts - 44 + 53 @@ -3105,7 +2709,11 @@ Equity Ações - libs/ui/src/lib/i18n.ts + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + + + libs/ui/src/lib/i18n.ts 46 @@ -3138,7 +2746,7 @@ Criptomoedas libs/ui/src/lib/i18n.ts - 53 + 55 @@ -3146,7 +2754,7 @@ ETF libs/ui/src/lib/i18n.ts - 54 + 56 @@ -3154,7 +2762,7 @@ Fundo de Investimento libs/ui/src/lib/i18n.ts - 55 + 57 @@ -3162,7 +2770,7 @@ Metal Precioso libs/ui/src/lib/i18n.ts - 56 + 58 @@ -3170,7 +2778,7 @@ Private Equity libs/ui/src/lib/i18n.ts - 57 + 59 @@ -3178,7 +2786,7 @@ Ação libs/ui/src/lib/i18n.ts - 58 + 60 @@ -3186,7 +2794,7 @@ África libs/ui/src/lib/i18n.ts - 65 + 67 @@ -3194,7 +2802,7 @@ Ásia libs/ui/src/lib/i18n.ts - 66 + 68 @@ -3202,7 +2810,7 @@ Europa libs/ui/src/lib/i18n.ts - 67 + 69 @@ -3210,7 +2818,7 @@ América do Norte libs/ui/src/lib/i18n.ts - 68 + 70 @@ -3218,7 +2826,7 @@ Oceânia libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3226,10 +2834,10 @@ América do Sul libs/ui/src/lib/i18n.ts - 70 + 72 - + Time to add your first activity. Está na hora de adicionar a sua primeira atividade. @@ -3240,117 +2848,85 @@ No data available Sem dados disponíveis + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + 414 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - + Activities Count Nº de Atividades apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + 157 - + Refresh Atualizar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + 17 - + Symbol Mapping Mapeamento de Símbolo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + 360 - + User Signup Registo do Utilizador apps/client/src/app/components/admin-overview/admin-overview.html - 111 - - - - Community - Comunidade - - apps/client/src/app/app.component.html - 121 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 - - - apps/client/src/app/pages/features/features-page.html - 259 + 34 Market Data Dados de Mercado - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 51 Summary Sumário - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/pages/home/home-page.component.ts - 47 + libs/common/src/lib/routes/routes.ts + 105 @@ -3358,10 +2934,10 @@ A validar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + 284 - + Import Importar @@ -3374,38 +2950,74 @@ libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + 71 Dividend Dividendos + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + 73 libs/ui/src/lib/i18n.ts 36 - + Dividend Timeline Cronograma de Dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + 425 Asset Sub Class Subclasse de Ativos + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + libs/ui/src/lib/i18n.ts 7 - + Holding Detenção @@ -3414,10 +3026,10 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 179 - + Load Dividends Carregar Dividendos @@ -3430,7 +3042,7 @@ Anualmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + 89 @@ -3438,15 +3050,23 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - + Valid until Válido até apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 74 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3501,39 +3121,39 @@ 27 - + Protection for sensitive information like absolute performances and quantity values Proteção para informações sensíveis, como desempenhos absolutos e valores quantitativos apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + 185 - + Distraction-free experience for turbulent times Experiência sem distrações para tempos turbulentos apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + 203 - + Sneak peek at upcoming functionality Acesso antecipado a funcionalidades futuras apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + 237 - + Are you an ambitious investor who needs the full picture? É um investidor ambicioso que precisa de ter uma vista completa? apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + 15 - + Portfolio Summary Resumo do Portefólio @@ -3542,14 +3162,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 57 + 44 apps/client/src/app/pages/pricing/pricing-page.html - 213 + 205 - + Performance Benchmarks Desempenho das Referências @@ -3558,14 +3178,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 65 + 52 apps/client/src/app/pages/pricing/pricing-page.html - 221 + 213 - + FIRE Calculator Calculadora FIRE @@ -3574,14 +3194,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 69 + 56 apps/client/src/app/pages/pricing/pricing-page.html - 225 + 217 - + and more Features... e mais Funcionalidades... @@ -3590,175 +3210,191 @@ apps/client/src/app/pages/pricing/pricing-page.html - 85 + 72 apps/client/src/app/pages/pricing/pricing-page.html - 252 + 261 - + Skip Saltar apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 - + Upgrade Plan Atualizar Plano apps/client/src/app/components/header/header.component.html - 185 + 193 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + 70 apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 288 + 299 - + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. Para investidores experientes que preferem correr o Ghostfolio na sua própria infraestrutura. apps/client/src/app/pages/pricing/pricing-page.html - 38 + 26 - + Unlimited Transactions Transações Ilimitadas apps/client/src/app/pages/pricing/pricing-page.html - 45 + 32 apps/client/src/app/pages/pricing/pricing-page.html - 134 + 121 apps/client/src/app/pages/pricing/pricing-page.html - 201 + 193 - + Unlimited Accounts Contas Ilimitadas apps/client/src/app/pages/pricing/pricing-page.html - 49 + 36 apps/client/src/app/pages/pricing/pricing-page.html - 138 + 125 apps/client/src/app/pages/pricing/pricing-page.html - 205 + 197 - + Portfolio Performance Desempenho do Portefólio apps/client/src/app/pages/pricing/pricing-page.html - 53 + 40 apps/client/src/app/pages/pricing/pricing-page.html - 142 + 129 apps/client/src/app/pages/pricing/pricing-page.html - 209 + 201 - + Self-hosted, update manually. Hospedado localmente, atualização manual. apps/client/src/app/pages/pricing/pricing-page.html - 94 + 81 - + Free Grátis apps/client/src/app/pages/pricing/pricing-page.html - 95 + 83 apps/client/src/app/pages/pricing/pricing-page.html - 158 + 146 - + For new investors who are just getting started with trading. Para novos investidores que estão a começar a investir agora. apps/client/src/app/pages/pricing/pricing-page.html - 128 + 116 - + Fully managed Ghostfolio cloud offering. Ghostfolio hospedado na nuvem, totalmente gerido. apps/client/src/app/pages/pricing/pricing-page.html - 157 + 144 apps/client/src/app/pages/pricing/pricing-page.html - 261 + 270 - + For ambitious investors who need the full picture of their financial assets. Para investidores ambiciosos que precisam de ter uma visão completa de seus ativos financeiros. apps/client/src/app/pages/pricing/pricing-page.html - 194 + 187 - + One-time payment, no auto-renewal. Pagamento único, sem renovação automática. apps/client/src/app/pages/pricing/pricing-page.html - 298 + 303 - + Get Started Começar apps/client/src/app/pages/landing/landing-page.html - 446 + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - + It’s free. É gratuito. apps/client/src/app/pages/pricing/pricing-page.html - 327 + 353 - + Fees Taxas apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + 204 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -3766,10 +3402,10 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 213 - + Portfolio Allocations Alocações do Portefólio @@ -3782,14 +3418,14 @@ apps/client/src/app/pages/pricing/pricing-page.html - 61 + 48 apps/client/src/app/pages/pricing/pricing-page.html - 217 + 209 - + Savings Rate per Month Taxa de Poupança por Mês @@ -3797,20 +3433,20 @@ 10 - + Data Import and Export Importação e Exportação de Dados apps/client/src/app/pages/pricing/pricing-page.html - 73 + 60 apps/client/src/app/pages/pricing/pricing-page.html - 146 + 133 apps/client/src/app/pages/pricing/pricing-page.html - 229 + 221 @@ -3821,20 +3457,20 @@ 13 - + Community Support Suporte da Comunidade apps/client/src/app/pages/pricing/pricing-page.html - 90 + 77 - + Email and Chat Support Suporte por Email e Chat apps/client/src/app/pages/pricing/pricing-page.html - 257 + 266 @@ -3853,7 +3489,7 @@ 14 - + Market data provided by Dados de mercado fornecidos por @@ -3861,23 +3497,7 @@ 2 - - Oops! Could not get the historical exchange rate from - Oops! Não foi possível obter a taxa de câmbio histórica de - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - - - Gather Historical Data - Obter Dados Históricos - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 - - - + Retirement Date Data da Reforma @@ -3885,7 +3505,7 @@ 32 - + Professional Data Provider Provedor de Dados Profissionais @@ -3894,10 +3514,10 @@ apps/client/src/app/pages/pricing/pricing-page.html - 240 + 237 - + Pricing Plans Planos de Preços @@ -3905,7 +3525,7 @@ 4 - + Renew Plan Renovar Plano @@ -3914,35 +3534,35 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 294 + 297 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - A nossa oferta oficial Ghostfolio Premium na nuvem é a maneira mais fácil de começar. Com o tempo que poupa, esta será a melhor opção para a maioria das pessoas. A receita é utilizada para cobrir a infraestrutura de hospedagem e financiar o desenvolvimento contínuo do Ghostfolio. + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + A nossa oferta oficial Ghostfolio Premium na nuvem é a maneira mais fácil de começar. Com o tempo que poupa, esta será a melhor opção para a maioria das pessoas. A receita é utilizada para cobrir a infraestrutura de hospedagem e financiar o desenvolvimento contínuo do Ghostfolio. apps/client/src/app/pages/pricing/pricing-page.html - 6 + 7 - + Impersonate User Personificar Utilizador apps/client/src/app/components/admin-users/admin-users.html - 239 + 240 - + Delete User Apagar Utilizador apps/client/src/app/components/admin-users/admin-users.html - 251 + 261 @@ -3950,10 +3570,10 @@ Deseja mesmo eliminar estas atividades? libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + 250 - + By ETF Provider Por Prestador de ETF @@ -3961,7 +3581,7 @@ 306 - + Update platform Atualizar plataforma @@ -3969,7 +3589,7 @@ 8 - + Add platform Adicionar plataforma @@ -3977,16 +3597,20 @@ 10 - + Url Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -3998,18 +3622,18 @@ Deseja mesmo eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + 107 - + Platforms Plataformas apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + 195 - + Update Cash Balance Atualizar saldo em Dinheiro @@ -4017,7 +3641,7 @@ 112 - + By Platform Por Plataforma @@ -4025,56 +3649,44 @@ 44 - + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: Atualize para o Ghostfolio Premium e obtenha acesso a recursos exclusivos para aperfeiçoar a sua experiência de investimento: apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + 18 - + Get the tools to effectively manage your finances and refine your personal investment strategy. Obtenha as ferramentas necessárias para gerir as suas finanças de forma eficaz e aperfeiçoe a sua estratégia de investimento pessoal. apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + 48 - + Add Platform Adicionar Plataforma apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + 9 Settings Definições - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 - - - apps/client/src/app/pages/admin/admin-page.component.ts - 32 - - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + libs/common/src/lib/routes/routes.ts + 34 - - - Equity - Ações - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + libs/common/src/lib/routes/routes.ts + 56 @@ -4085,7 +3697,7 @@ 19 - + Manage Benchmarks Gerir Referências @@ -4093,7 +3705,7 @@ 35 - + Select Holding Selecionar Posição @@ -4101,7 +3713,7 @@ 20 - + Select File Selecionar Ficheiro @@ -4109,7 +3721,7 @@ 22 - + Select Dividends Selecionar Dividendos @@ -4117,7 +3729,7 @@ 113 - + Select Activities Selecionar Atividades @@ -4125,64 +3737,36 @@ 115 - - Import Activities - Importar Atividades - - libs/ui/src/lib/activities-table/activities-table.component.html - 9 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 371 - - - - Import Dividends - Importar Dividendos - - libs/ui/src/lib/activities-table/activities-table.component.html - 29 - - - libs/ui/src/lib/activities-table/activities-table.component.html - 383 - - - - Personal Finance - Finanças pessoais + + Frequently Asked Questions (FAQ) + Perguntas Frequentes (FAQ) - apps/client/src/app/app.component.html - 57 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - - - Frequently Asked Questions (FAQ) - Perguntas Frequentes (FAQ) - apps/client/src/app/app.component.html - 83 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 - + Current Streak Série Atual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + 389 - + Longest Streak Série mais Longa apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + 398 @@ -4217,12 +3801,12 @@ 30 - + Liabilities Responsabilidades apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + 243 apps/client/src/app/pages/features/features-page.html @@ -4233,43 +3817,43 @@ Changelog Registo de alterações - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 License Licença - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/about/license/license-page.html + 4 - - - Stocks - Ações - apps/client/src/app/pages/features/features-page.html - 15 + libs/common/src/lib/routes/routes.ts + 193 - + ETFs - ETFs + ETFs apps/client/src/app/pages/features/features-page.html 25 - + Bonds Obrigações @@ -4277,15 +3861,7 @@ 38 - - Cryptocurrencies - Criptomoedas - - apps/client/src/app/pages/features/features-page.html - 51 - - - + Wealth Items Artigos de património @@ -4293,15 +3869,15 @@ 76 - + Import and Export Importação e exportação apps/client/src/app/pages/features/features-page.html - 115 + 116 - + Multi-Accounts Múltiplas contas @@ -4309,7 +3885,7 @@ 127 - + Portfolio Calculations Cálculos do portefólio @@ -4317,63 +3893,63 @@ 141 - + Dark Mode Modo escuro apps/client/src/app/pages/features/features-page.html - 178 + 233 - + Market Mood Humor do mercado apps/client/src/app/pages/features/features-page.html - 206 + 215 - + Static Analysis Análise estática apps/client/src/app/pages/features/features-page.html - 225 + 179 - + Multi-Language Multilíngua apps/client/src/app/pages/features/features-page.html - 242 + 259 - + Open Source Software Software de código aberto apps/client/src/app/pages/features/features-page.html - 278 + 295 Liability - Liability + Responsabilidade libs/ui/src/lib/i18n.ts 40 - + Scraper Configuration - Scraper Configuration + Configuração do raspador apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 385 - + Add Asset Profile Adicionar perfil do ativo @@ -4385,19 +3961,23 @@ Personal Finance Tools Ferramentas de finanças pessoais - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 - + Discover Open Source Alternatives for Personal Finance Tools Descubra alternativas de software livre para ferramentas de finanças pessoais apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + 5 - + Founded Fundada @@ -4405,7 +3985,7 @@ 77 - + Origin Origem @@ -4413,7 +3993,7 @@ 82 - + Region Região @@ -4421,15 +4001,15 @@ 87 - + Available in Disponível em apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + 109 - + ✅ Yes ✅ Sim @@ -4465,7 +4045,7 @@ 274 - + ❌ No ❌ Não @@ -4501,31 +4081,31 @@ 281 - + Self-Hosting Auto-hospedagem apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + 171 - + Use anonymously Utilizar anonimamente apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + 210 - + Free Plan Plano gratuito apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 249 - + Notes Notas @@ -4533,41 +4113,17 @@ 302 - + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. Acompanhe, analise e visualize o seu património sem esforço com a Ghostfolio. apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 - - - - Personal Finance Tools - Ferramentas de finanças pessoais - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 - - - - Guides - Guias - - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 - - - - Glossary - Glossário - - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + 329 - + Stocks, ETFs, bonds, cryptocurrencies, commodities - Stocks, ETFs, bonds, cryptocurrencies, commodities + Ações, ETFs, títulos, criptomoedas, commodities apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 25 @@ -4577,7 +4133,7 @@ 65 - + Mortgages, personal loans, credit cards Hipotecas, crédito pessoal, cartões de crédito @@ -4585,7 +4141,7 @@ 57 - + Luxury items, real estate, private companies Artigos de luxo, bens imobiliários, empresas privadas @@ -4596,6 +4152,10 @@ Buy Comprar + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + libs/ui/src/lib/i18n.ts 35 @@ -4603,7 +4163,7 @@ Valuable - Valuable + De valor libs/ui/src/lib/i18n.ts 39 @@ -4611,26 +4171,26 @@ ETFs without Countries - ETFs without Countries + ETFs sem países apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + 130 ETFs without Sectors - ETFs without Sectors + ETFs sem setores apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + 135 - + Assets Ativos apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + 203 @@ -4641,7 +4201,7 @@ 25 - + By Market Por mercado @@ -4662,118 +4222,98 @@ Japão libs/ui/src/lib/i18n.ts - 84 + 89 - + Welcome to Ghostfolio Bem-vindo à Ghostfolio apps/client/src/app/components/home-overview/home-overview.html - 7 + 11 - + Setup your accounts Configurar as suas contas apps/client/src/app/components/home-overview/home-overview.html - 15 + 19 - + Get a comprehensive financial overview by adding your bank and brokerage accounts. Obtenha uma visão financeira abrangente adicionando as suas contas bancárias e de corretagem. apps/client/src/app/components/home-overview/home-overview.html - 17 + 21 - + Capture your activities - Capture your activities + Capture suas atividades apps/client/src/app/components/home-overview/home-overview.html - 24 + 28 - + Record your investment activities to keep your portfolio up to date. Registe as suas actividades de investimento para manter a sua carteira actualizada. apps/client/src/app/components/home-overview/home-overview.html - 26 + 30 - + Monitor and analyze your portfolio Monitorizar e analisar a sua carteira apps/client/src/app/components/home-overview/home-overview.html - 33 + 37 - + Track your progress in real-time with comprehensive analysis and insights. Acompanhe o seu progresso em tempo real com análises e conhecimentos abrangentes. apps/client/src/app/components/home-overview/home-overview.html - 35 - - - - No data available - Não há dados disponíveis - - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 - - - apps/client/src/app/pages/public/public-page.html - 188 - - - libs/ui/src/lib/benchmark/benchmark.component.html - 137 - - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 39 - + Ready to take control of your personal finances? Pronto para assumir o controlo das suas finanças pessoais? apps/client/src/app/components/home-overview/home-overview.html - 8 + 12 - + Setup accounts Configurar contas apps/client/src/app/components/home-overview/home-overview.html - 44 + 52 - + Biometric Authentication Autenticação biométrica apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + 218 - + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + Na Ghostfolio, a transparência está no centro dos nossos valores. Publicamos o código fonte como open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. apps/client/src/app/pages/open/open-page.html - 6 + 7 - + Active Users Utilizadores ativos @@ -4785,7 +4325,7 @@ 62 - + New Users Novos utilizadores @@ -4793,7 +4333,7 @@ 51 - + Users in Slack community Utilizadores na comunidade Slack @@ -4801,7 +4341,7 @@ 75 - + Contributors on GitHub Colaboradores em GitHub @@ -4809,7 +4349,7 @@ 89 - + Stars on GitHub Estrelas no GitHub @@ -4821,9 +4361,9 @@ 103 - + Pulls on Docker Hub - Pulls on Docker Hub + Não puxa Docker Hub apps/client/src/app/pages/landing/landing-page.html 106 @@ -4833,7 +4373,7 @@ 117 - + Uptime Tempo de funcionamento @@ -4841,12 +4381,12 @@ 132 - + Export Data Exportar dados apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + 260 @@ -4854,26 +4394,30 @@ Moedas apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 - + Our - Our + Nosso apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 6 - + Visit - Visit + Visita apps/client/src/app/pages/about/oss-friends/oss-friends-page.html 28 - + Discover other exciting Open Source Software projects Descubra outros projectos interessantes de software de fonte aberta @@ -4881,2755 +4425,3710 @@ 9 - - Frequently Asked Questions (FAQ) - Perguntas frequentes (FAQ) + + Check out the numerous features of Ghostfolio to manage your wealth + Confira os inúmeros recursos do Ghostfolio para gerenciar seu patrimônio - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + apps/client/src/app/pages/features/features-page.html + 7 - - apps/client/src/app/pages/faq/saas/saas-page.html - 4 - - - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 - - - - Check out the numerous features of Ghostfolio to manage your wealth - Check out the numerous features of Ghostfolio to manage your wealth - - apps/client/src/app/pages/features/features-page.html - 6 - - - - Discover the latest Ghostfolio updates and insights on personal finance - Discover the latest Ghostfolio updates and insights on personal finance + + + Discover the latest Ghostfolio updates and insights on personal finance + Descubra as últimas atualizações e insights do Ghostfolio sobre finanças pessoais apps/client/src/app/pages/blog/blog-page.html 7 - + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Se você preferir executar o Ghostfolio em sua própria infraestrutura, encontre o código-fonte e mais instruções em GitHub. apps/client/src/app/pages/pricing/pricing-page.html - 26 + 14 - + Manage your wealth like a boss - Manage your wealth like a boss + Gerencie seu patrimônio como um chefe apps/client/src/app/pages/landing/landing-page.html - 5 + 6 - + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - - apps/client/src/app/pages/landing/landing-page.html - 9 - - - - Get Started - Começar + Ghostfolio é um painel de código aberto que prioriza a privacidade para suas finanças pessoais. Divida sua alocação de ativos, conheça seu patrimônio líquido e tome decisões de investimento sólidas e baseadas em dados. apps/client/src/app/pages/landing/landing-page.html - 41 - - - apps/client/src/app/pages/pricing/pricing-page.html - 324 + 10 - + Monthly Active Users - Monthly Active Users + Usuários ativos mensais apps/client/src/app/pages/landing/landing-page.html 70 - + As seen in - As seen in + Como visto em apps/client/src/app/pages/landing/landing-page.html 115 - + Protect your assets. Refine your personal investment strategy. - Protect your assets. Refine your personal investment strategy. + Proteja o seu assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 225 + 226 - + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + O Ghostfolio permite que pessoas ocupadas acompanhem ações, ETFs ou criptomoedas sem serem rastreadas. apps/client/src/app/pages/landing/landing-page.html - 229 + 230 - + 360° View - 360° View + 360° visualizar apps/client/src/app/pages/landing/landing-page.html 240 - + Web3 Ready - Web3 Ready + Web3 Preparar apps/client/src/app/pages/landing/landing-page.html 251 - + Use Ghostfolio anonymously and own your financial data. - Use Ghostfolio anonymously and own your financial data. - - apps/client/src/app/pages/landing/landing-page.html - 253 - - - - Open Source - Open Source + Use o Ghostfolio anonimamente e possua seus dados financeiros. apps/client/src/app/pages/landing/landing-page.html - 261 + 254 - + Benefit from continuous improvements through a strong community. - Benefit from continuous improvements through a strong community. + Beneficie-se de melhorias contínuas através de uma comunidade forte. apps/client/src/app/pages/landing/landing-page.html - 263 + 264 - + Why Ghostfolio? - Why Ghostfolio? + Por que Ghostfolio? apps/client/src/app/pages/landing/landing-page.html 272 - + Ghostfolio is for you if you are... - Ghostfolio is for you if you are... + Ghostfolio é para você se você for... apps/client/src/app/pages/landing/landing-page.html - 273 + 274 - + trading stocks, ETFs or cryptocurrencies on multiple platforms - trading stocks, ETFs or cryptocurrencies on multiple platforms + negociar ações, ETFs ou criptomoedas em múltiplas plataformas apps/client/src/app/pages/landing/landing-page.html 280 - + pursuing a buy & hold strategy - pursuing a buy & hold strategy + buscando uma compra & estratégia de retenção apps/client/src/app/pages/landing/landing-page.html 286 - + interested in getting insights of your portfolio composition - interested in getting insights of your portfolio composition + interessado em obter insights sobre a composição do seu portfólio apps/client/src/app/pages/landing/landing-page.html 291 - + valuing privacy and data ownership - valuing privacy and data ownership + valorizando a privacidade e a propriedade dos dados apps/client/src/app/pages/landing/landing-page.html 296 - + into minimalism - into minimalism + no minimalismo apps/client/src/app/pages/landing/landing-page.html 299 - + caring about diversifying your financial resources - caring about diversifying your financial resources + preocupando-se em diversificar seus recursos financeiros apps/client/src/app/pages/landing/landing-page.html 303 - + interested in financial independence - interested in financial independence + interessado em independência financeira apps/client/src/app/pages/landing/landing-page.html 307 - + saying no to spreadsheets in - saying no to spreadsheets in + dizendo não às planilhas em apps/client/src/app/pages/landing/landing-page.html 311 - + still reading this list - still reading this list + ainda lendo esta lista apps/client/src/app/pages/landing/landing-page.html 314 - + Learn more about Ghostfolio - Learn more about Ghostfolio + Saiba mais sobre o Ghostfolio apps/client/src/app/pages/landing/landing-page.html 319 - + What our users are saying - What our users are saying + Qual é o nosso users are saying apps/client/src/app/pages/landing/landing-page.html - 327 + 328 - + Members from around the globe are using Ghostfolio Premium - Members from around the globe are using Ghostfolio Premium + Membros de todo o mundo estão usando Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 366 + 367 - + How does Ghostfolio work? - How does Ghostfolio work? + Como é que Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 383 + 384 - + Sign up anonymously* - Sign up anonymously* + Inscreva-se anonimamente* apps/client/src/app/pages/landing/landing-page.html 392 - + * no e-mail address nor credit card required - * no e-mail address nor credit card required + * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html 394 - + Add any of your historical transactions - Add any of your historical transactions + Adicione qualquer uma de suas transações históricas apps/client/src/app/pages/landing/landing-page.html - 405 + 406 - + Get valuable insights of your portfolio composition - Get valuable insights of your portfolio composition + Obtenha insights valiosos sobre a composição do seu portfólio apps/client/src/app/pages/landing/landing-page.html - 417 + 418 - + Are you ready? - Are you ready? - - apps/client/src/app/pages/landing/landing-page.html - 431 - - - - Live Demo - Live Demo - - apps/client/src/app/pages/landing/landing-page.html - 49 - + São you preparar? apps/client/src/app/pages/landing/landing-page.html - 451 + 432 - + Get the full picture of your personal finances across multiple platforms. - Get the full picture of your personal finances across multiple platforms. + Tenha uma visão completa das suas finanças pessoais em diversas plataformas. apps/client/src/app/pages/landing/landing-page.html - 242 + 243 - + Get started in only 3 steps - Get started in only 3 steps + Comece em apenas 3 passos apps/client/src/app/pages/landing/landing-page.html 386 - + faq perguntas-mais-frequentes - snake-case - - apps/client/src/app/app.component.ts - 77 - + kebab-case - apps/client/src/app/core/paths.ts - 3 - - - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 - - - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 245 - + features funcionalidades - snake-case - - apps/client/src/app/app.component.ts - 78 - + kebab-case - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/components/header/header.component.ts - 87 + libs/common/src/lib/routes/routes.ts + 255 + + + about + sobre + kebab-case - apps/client/src/app/core/paths.ts - 4 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 214 + + + privacy-policy + politica-de-privacidade + kebab-case - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 207 + + + license + licenca + kebab-case - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + mercados + kebab-case - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + libs/common/src/lib/routes/routes.ts + 260 - - about - sobre - snake-case + + pricing + precos + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 270 + + + register + registo + kebab-case - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + recursos + kebab-case - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 306 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 322 + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Esta página de visão geral apresenta uma coleção selecionada de ferramentas de finanças pessoais em comparação com a alternativa de código abertoGhostfolio. Se você valoriza transparência, privacidade de dados e colaboração comunitária, o Ghostfolio oferece uma excelente oportunidade para assumir o controle de sua gestão financeira. - apps/client/src/app/pages/about/about-page.component.ts - 74 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Explore os links abaixo para comparar uma variedade de ferramentas de finanças pessoais com o Ghostfolio. - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + Open Source Alternative to + Alternativa de software livre ao - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + The Open Source Alternative to + A alternativa de software livre ao - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Você está procurando uma alternativa de código aberto para ? Ghostfolio é uma poderosa ferramenta de gestão de portfólio que oferece aos investidores uma plataforma abrangente para monitorar, analisar e otimizar seus investimentos. Seja você um investidor experiente ou iniciante, o Ghostfolio oferece uma interface de usuário intuitiva e um ampla gama de funcionalidades para ajudá-lo a tomar decisões informadas e assumir o controle do seu futuro financeiro. - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio é um software de código aberto (OSS), que oferece uma alternativa econômica para tornando-o particularmente adequado para indivíduos com orçamento apertado, como aqueles buscando Independência Financeira, Aposentadoria Antecipada (FIRE). Ao aproveitar os esforços coletivos de uma comunidade de desenvolvedores e entusiastas de finanças pessoais, o Ghostfolio aprimora continuamente seus recursos, segurança e experiência do usuário. - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Vamos nos aprofundar nos detalhes do Ghostfolio vs tabela de comparação abaixo para obter uma compreensão completa de como o Ghostfolio se posiciona em relação a . Exploraremos vários aspectos, como recursos, privacidade de dados, preços e muito mais, permitindo que você faça uma escolha bem informada para suas necessidades pessoais. - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + open-source-alternative-to + alternativa-de-software-livre-ao + kebab-case - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 324 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Observe que as informações fornecidas no Ghostfolio vs. A tabela de comparação é baseada em nossa pesquisa e análise independentes. Este site não é afiliado a ou qualquer outro produto mencionado na comparação. À medida que o cenário das ferramentas de finanças pessoais evolui, é essencial verificar quaisquer detalhes ou alterações específicas diretamente na página do produto correspondente. Os dados precisam de uma atualização? Ajude-nos a manter dados precisos sobre GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - privacy-policy - politica-de-privacidade - snake-case + + Ready to take your investments to the next level? + Pronto para levar o seu investimentos para o próximo nível? - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Switzerland + Suíça - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/ui/src/lib/i18n.ts + 96 - - license - licenca - snake-case + + Global + Global - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/core/paths.ts - 5 + libs/ui/src/lib/i18n.ts + 16 + + + (Last 24 hours) + (Últimas 24 horas) - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/open/open-page.html + 37 - - markets - mercados - snake-case + + (Last 30 days) + (Últimos 30 dias) - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/pages/open/open-page.html + 59 + + + (Last 90 days) + (Últimos 90 dias) - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/pages/open/open-page.html + 127 + + + Choose or drop a file here + Selecione ou solte um arquivo aqui - apps/client/src/app/core/paths.ts - 6 - - - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 - - - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 - - - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + You are using the Live Demo. + Você está usando a demonstração ao vivo. - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/app.component.html + 12 + + + One-time fee, annual account fees + Taxa única, taxas de conta anuais - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - pricing - precos - snake-case + + Distribution of corporate earnings + Distribuição de lucros corporativos - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Fee + Taxa - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - apps/client/src/app/components/header/header.component.ts - 84 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - apps/client/src/app/components/header/header.component.ts - 89 + libs/ui/src/lib/i18n.ts + 37 + + + Revenue for lending out money + Receita por empréstimo de dinheiro - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + Add Tag + Adicionar etiqueta - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + Do you really want to delete this tag? + Você realmente deseja excluir esta tag? - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Atualizar etiqueta - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + Adicionar etiqueta - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Currency Cluster Risks + Riscos de cluster monetário - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + Account Cluster Risks + Riscos de cluster de contas - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Transfer Cash Balance + Transferir saldo de dinheiro - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Version + Versão - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + From + De - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + To + Para - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + Transfer + Transferir - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + Membership + Associação - libs/ui/src/lib/membership-card/membership-card.component.ts + libs/common/src/lib/routes/routes.ts 31 - - - register - registo - snake-case - apps/client/src/app/app.component.ts - 81 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + Access + Acesso - apps/client/src/app/components/header/header.component.ts - 90 + libs/common/src/lib/routes/routes.ts + 26 + + + Asset Profile + Perfil de ativos - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Do you really want to delete this asset profile? + Você realmente deseja excluir este perfil de ativo? - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Procurar - apps/client/src/app/pages/faq/saas/saas-page.component.ts + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html 16 + + + Add Manually + Adicionar manualmente - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio é um dashboard de finanças pessoais para acompanhar os seus activos como acções, ETFs ou criptomoedas em múltiplas plataformas. - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Última alta de todos os tempos - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - resources - recursos - snake-case + + User + Usuário - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio vs tabela de comparação - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + Open Source Wealth Management Software + Software de gerenciamento de patrimônio de código aberto - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + aplicativo, ativo, criptomoeda, painel, etf, finanças, gestão, desempenho, portfólio, software, ação, negociação, riqueza, web3 - apps/client/src/app/core/paths.ts + apps/client/src/app/pages/i18n/i18n-page.html 10 + + + Oops, cash balance transfer has failed. + Ops, a transferência do saldo em dinheiro falhou. - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Medo Extremo - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Ganância Extrema - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Neutro - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + Ops! Não foi possível analisar os dados históricos. - apps/client/src/app/pages/features/features-page.component.ts - 30 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + Você realmente deseja excluir esta mensagem do sistema? - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + Tendência de 50 dias - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + Tendência de 200 dias - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + Cash Balances + Saldos de caixa - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + Starting from + A partir de - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + + Do you really want to delete this account balance? + Você realmente deseja excluir o saldo desta conta? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Explore the links below to compare a variety of personal finance tools with Ghostfolio. + + If a translation is missing, kindly support us in extending it here. + Se faltar uma tradução, por favor, ajude-nos a estendê-la here. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Open Source Alternative to - Alternativa de software livre ao + + The current market price is + O preço de mercado atual é - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Open Source Alternative to - Alternativa de software livre ao + + Test + Teste - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - The Open Source Alternative to - A alternativa de software livre ao + + Date Range + Período - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + libs/ui/src/lib/assistant/assistant.html + 143 + + + + Permission + Permissão + + apps/client/src/app/components/access-table/access-table.component.html + 18 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 + + + + Restricted view + Visualização restrita + + apps/client/src/app/components/access-table/access-table.component.html + 26 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 + + + + Oops! Could not grant access. + Ops! Não foi possível conceder acesso. + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + + Private + Privado + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 + + + + Job Queue + Fila de trabalhos + + libs/common/src/lib/routes/routes.ts + 46 + + + + Market data is delayed for + Dados de mercado estão atrasados para + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Investment + Investimento + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + + Absolute Asset Performance + Desempenho absoluto de ativos + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + + Asset Performance + Desempenho de ativos + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + + Absolute Currency Performance + Desempenho absoluto da moeda + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + + Currency Performance + Desempenho da moeda + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + + Absolute Net Performance + Desempenho Líquido Absoluto + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + + Net Performance + Desempenho líquido + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + + Week to date + Semana até agora + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + WTD + WTD + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + Month to date + Do mês até a data + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + MTD + MTD + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + Year to date + No acumulado do ano + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + View + Visualizar + + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + + Oops! A data provider is experiencing the hiccups. + Ops! Um provedor de dados está enfrentando problemas. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html 8 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Se você se aposentar hoje, poderá sacar per year or per month, based on your total assets of and a withdrawal rate of 4%. + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + + Reset Filters + Redefinir filtros + + libs/ui/src/lib/assistant/assistant.html + 238 + + + + year + ano + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + anos + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Apply Filters + Aplicar filtros + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + Data Gathering + Coleta de dados + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + General + geral + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Nuvem + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Auto-hospedagem + + apps/client/src/app/pages/faq/faq-page.component.ts + 60 + + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + auto-hospedagem + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Ops! Parece que você está fazendo muitas solicitações. Por favor, diminua um pouco a velocidade. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + My Account + Minha conta + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Active + Ativo + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Fechado + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Indonesia + Indonesia + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Atividade + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Dividend Yield + Rendimento de dividendos + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Execute Job + Executar trabalho + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Priority + Prioridade + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + This action is not allowed. + Esta ação não é permitida. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Liquidity + Liquidez + + libs/ui/src/lib/i18n.ts + 48 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Compre e venda + + libs/ui/src/lib/i18n.ts + 8 + + + + Delete Activities + Excluir atividades + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Internationalization + Internacionalização + + libs/common/src/lib/routes/routes.ts + 119 + + + + Do you really want to close your Ghostfolio account? + Você realmente deseja encerrar sua conta Ghostfolio? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Danger Zone + Zona de perigo + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Fechar conta + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + By ETF Holding + Por ETF Holding + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Aproximação baseada nas principais participações de cada ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Join now or check out the example account + Cadastre-se agora ou confira a conta de exemplo + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + Oops! There was an error setting up biometric authentication. + Ops! Ocorreu um erro ao configurar a autenticação biométrica. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Show more + Mostrar mais + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + Benchmarks + Referências + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Delete Profiles + Excluir perfis + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete these profiles? + Você realmente deseja excluir esses perfis? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Oops! Could not delete profiles. + Ops! Não foi possível excluir perfis. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Table + o índice + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Gráfico + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Would you like to refine your personal investment strategy? + Você gostaria de refinar seu estratégia de investimento pessoal? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Alternative + Alternativo + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + Aplicativo + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Orçamento + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Comunidade + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Escritório Familiar + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Investidor + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Código aberto + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Finanças Pessoais + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Privacidade + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Programas + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Ferramenta + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Experiência do usuário + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Fortuna + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Gestão de patrimônio + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + Australia + Austrália + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Áustria + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Bélgica + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Bulgária + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Canadá + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + República Tcheca + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Finlândia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + libs/ui/src/lib/i18n.ts + 83 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + + France + França - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + libs/ui/src/lib/i18n.ts + 84 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + + Germany + Alemanha - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + libs/ui/src/lib/i18n.ts + 85 - - open-source-alternative-to - alternativa-de-software-livre-ao + + India + Índia - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + libs/ui/src/lib/i18n.ts + 86 + + + Italy + Itália - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 88 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + + Netherlands + Holanda - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + libs/ui/src/lib/i18n.ts + 90 - - Ready to take your investments to the next level? - Ready to take your investments to the next level? + + New Zealand + Nova Zelândia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + libs/ui/src/lib/i18n.ts + 91 - - Get Started - Começar + + Poland + Polônia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + libs/ui/src/lib/i18n.ts + 92 - - Switzerland - Switzerland + + Romania + Romênia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + libs/ui/src/lib/i18n.ts + 93 + + + South Africa + África do Sul libs/ui/src/lib/i18n.ts - 90 + 95 - - Global - Global + + Thailand + Tailândia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + libs/ui/src/lib/i18n.ts + 97 + + + United States + Estados Unidos libs/ui/src/lib/i18n.ts - 16 + 100 - - (Last 24 hours) - (Last 24 hours) + + Error + Erro - apps/client/src/app/pages/open/open-page.html - 37 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 - - (Last 30 days) - (Last 30 days) + + Deactivate + Desativar - apps/client/src/app/pages/open/open-page.html + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Ativar + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Inactive + Inativo + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Cancel + Cancelar + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html 48 - apps/client/src/app/pages/open/open-page.html - 59 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 - - (Last 90 days) - (Last 90 days) + + Close + Fechar - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 - - Choose or drop a file here - Choose or drop a file here + + Yes + Sim - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/i18n.ts + 32 - - You are using the Live Demo. - You are using the Live Demo. + + Copy link to clipboard + Copiar link para a área de transferência - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - One-time fee, annual account fees - One-time fee, annual account fees + + Portfolio Snapshot + Visão geral do portfólio - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Distribution of corporate earnings - Distribution of corporate earnings + + Change with currency effect Change + Change with currency effect Change - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from + + Performance with currency effect Performance + Performance with currency effect Performance - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Fee - Fee + + Threshold Min + Limite mínimo - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 + + + + Threshold Max + Limite máximo + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 + + + + Customize + Personalizar + + apps/client/src/app/components/rule/rule.component.html + 67 + + + + No auto-renewal. + Sem renovação automática. + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 + + + + This year + Este ano + + apps/client/src/app/pages/public/public-page.html + 42 + + + + From the beginning + Desde o início + + apps/client/src/app/pages/public/public-page.html + 60 + + + + Oops! Invalid currency. + Ops! Moeda inválida. + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 + + + + This page has been archived. + Esta página foi arquivada. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 + + + + is Open Source Software + é software de código aberto + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Interest - Interest + + is not Open Source Software + não é software de código aberto - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Revenue for lending out money - Revenue for lending out money - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Add Tag - Add Tag + + can be self-hosted + pode ser auto-hospedado - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - - - Do you really want to delete this tag? - Do you really want to delete this tag? - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Update tag - Update tag + + cannot be self-hosted + não pode ser auto-hospedado - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Add tag - Add tag - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Currency Cluster Risks - Currency Cluster Risks + + can be used anonymously + pode ser usado anonimamente - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Account Cluster Risks - Account Cluster Risks - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Transfer Cash Balance - Transfer Cash Balance + + cannot be used anonymously + não pode ser usado anonimamente - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Benchmark - Benchmark + + offers a free plan + oferece um plano gratuito - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Version - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Settings - Settings + + does not offer a free plan + não oferece um plano gratuito - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - From - From - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - To - To + + Oops! Could not find any assets. + Ops! Não foi possível encontrar nenhum ativo. - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - Transfer - Transfer + + Data Providers + Provedores de dados - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Membership - Membership + + Set API key + Definir chave de API - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 + + + Get access to 80’000+ tickers from over 50 exchanges + Tenha acesso a mais de 80’000 tickers de mais de 50 bolsas - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + libs/ui/src/lib/i18n.ts + 24 - - Access - Access + + Ukraine + Ucrânia - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + libs/ui/src/lib/i18n.ts + 98 + + + Join now + Cadastre-se agora - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Find holding... - Find holding... + + Glossary + Glossário - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - No entries... - No entries... - libs/ui/src/lib/assistant/assistant.html - 63 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - libs/ui/src/lib/assistant/assistant.html - 84 + libs/common/src/lib/routes/routes.ts + 293 - - Asset Profile - Asset Profile + + Guides + Guias - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Do you really want to delete this asset profile? - Do you really want to delete this asset profile? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Search - Search - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + libs/common/src/lib/routes/routes.ts + 301 - - Add Manually - Add Manually + + guides + guias + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + libs/common/src/lib/routes/routes.ts + 296 - - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio é um dashboard de finanças pessoais para acompanhar os seus activos como acções, ETFs ou criptomoedas em múltiplas plataformas. - apps/client/src/app/pages/i18n/i18n-page.html - 4 + libs/common/src/lib/routes/routes.ts + 299 - - Last All Time High - Last All Time High + + glossary + glossario + kebab-case - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + libs/common/src/lib/routes/routes.ts + 288 + + + libs/common/src/lib/routes/routes.ts + 291 - - User - User + + Threshold range + Faixa limite - apps/client/src/app/components/admin-users/admin-users.html - 29 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Ghostfolio vs comparison table - Ghostfolio vs tabela de comparação + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + O Ghostfolio X-ray utiliza análise estática para identificar potenciais problemas e riscos em seu portfólio. Ajuste as regras abaixo e defina limites personalizados para alinhá-los à sua estratégia de investimento. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Open Source Wealth Management Software - Open Source Wealth Management Software + + Economic Market Cluster Risks + Riscos do Cluster do Mercado Econômico - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + + of + de - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Oops, cash balance transfer has failed. - Oops, cash balance transfer has failed. + + daily requests + solicitações diárias - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Extreme Fear - Extreme Fear + + Remove API key + Remover chave de API - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Extreme Greed - Extreme Greed + + Do you really want to delete the API key? + Você realmente deseja excluir a chave de API? - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Neutral - Neutral + + Please enter your Ghostfolio API key: + Please enter your Ghostfolio API key: - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Oops! Could not parse historical data. - Oops! Could not parse historical data. + + API Requests Today + API Requests Today - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Do you really want to delete this system message? - Do you really want to delete this system message? + + Could not generate an API key + Could not generate an API key - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - 50-Day Trend - 50-Day Trend + + Set this API key in your self-hosted environment: + Set this API key in your self-hosted environment: - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - 200-Day Trend - 200-Day Trend + + Ghostfolio Premium Data Provider API Key + Ghostfolio Premium Data Provider API Key - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - Cash Balances - Cash Balances + + Do you really want to generate a new API key? + Do you really want to generate a new API key? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Starting from - Starting from + + API Key + API Key - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 + + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - year - year + + out of + out of - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 + + + rules align with your portfolio. + rules align with your portfolio. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Do you really want to delete this account balance? - Do you really want to delete this account balance? + + Save + Save - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - - - is an invalid currency! - is an invalid currency! - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - If a translation is missing, kindly support us in extending it here. - If a translation is missing, kindly support us in extending it here. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - - - The current market price is - The current market price is - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 - - - Test - Test - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Date Range - Date Range - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Permission - Permission - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 32 + 65 - - - Restricted view - Restricted view - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Oops! Could not grant access. - Oops! Could not grant access. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Private - Private + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 - - Job Queue - Job Queue + + Me + Me - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Market data is delayed for - Market data is delayed for + + Received Access + Received Access - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Investment - Investment + + Please enter your Ghostfolio API key. + Please enter your Ghostfolio API key. - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 + + + AI prompt has been copied to the clipboard + AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 197 + + + Link has been copied to the clipboard + O link foi copiado para a área de transferência - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Absolute Asset Performance - Absolute Asset Performance + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Asset Performance - Asset Performance + + Lazy + Lazy - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Absolute Currency Performance - Absolute Currency Performance + + Instant + Instant - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - Currency Performance - Currency Performance + + Default Market Price + Preço de mercado padrão - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Absolute Net Performance - Absolute Net Performance + + Mode + Mode - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - Net Performance - Net Performance + + Selector + Selector - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Week to date - Week to date + + HTTP Request Headers + HTTP Request Headers - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - WTD - WTD + + end of day + end of day - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Month to date - Month to date + + real-time + real-time - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - MTD - MTD + + Open Duck.ai + Open Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Year to date - Year to date + + Create + Criar - libs/ui/src/lib/assistant/assistant.component.ts - 231 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - View - View + + Change + Mudar - apps/client/src/app/components/access-table/access-table.component.html - 23 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Oops! A data provider is experiencing the hiccups. - Oops! A data provider is experiencing the hiccups. + + Performance + Performance - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Reset Filters - Reset Filters - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - year - year - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - - years - years - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Apply Filters - Apply Filters + + Copy portfolio data to clipboard for AI prompt + Copy portfolio data to clipboard for AI prompt - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - Data Gathering - Data Gathering + + Copy AI prompt to clipboard for analysis + Copy AI prompt to clipboard for analysis - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - General - General + + Armenia + Armenia - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/i18n.ts + 75 - - Cloud - Cloud + + British Virgin Islands + British Virgin Islands - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + Singapore - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Self-Hosting - Self-Hosting + + Terms and Conditions + Termos e Condições - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 + + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Please keep your security token safe. If you lose it, you will not be able to recover your account. - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - self-hosting - self-hosting + + I understand that if I lose my security token, I cannot recover my account + I understand that if I lose my security token, I cannot recover my account - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - FAQ - FAQ + + Continue + Continue - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 + + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Here is your security token. It is only visible once, please store and keep it in a safe place. - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! It looks like you’re making too many requests. Please slow down a bit. + + Security token + Security token - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - My Account - My Account - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Active - Active + + Do you really want to generate a new security token for this user? + Do you really want to generate a new security token for this user? - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - Closed - Closed + + Generate Security Token + Generate Security Token - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Activity - Activity + + United Kingdom + United Kingdom - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + libs/ui/src/lib/i18n.ts + 99 - - Dividend Yield - Dividend Yield + + Terms of Service + Termos de Serviço - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Execute Job - Execute Job + + terms-of-service + termos-de-servico + kebab-case - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + libs/common/src/lib/routes/routes.ts + 212 - - - Priority - Priority - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + libs/common/src/lib/routes/routes.ts + 215 - - This action is not allowed. - This action is not allowed. + + Terms of Service + Termos de Serviço - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/app.component.html + 112 - - - Liquidity - Liquidity - libs/ui/src/lib/i18n.ts - 48 + libs/common/src/lib/routes/routes.ts + 217 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + and I agree to the Terms of Service. + and I agree to the Terms of Service. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Buy and sell - Buy and sell + + () is already in use. + () is already in use. - libs/ui/src/lib/i18n.ts - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Delete Activities - Delete Activities + + An error occurred while updating to (). + An error occurred while updating to (). - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Internationalization - Internationalization + + Apply + Apply - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Do you really want to close your Ghostfolio account? - Do you really want to close your Ghostfolio account? + + with API access for + with API access for - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Danger Zone - Danger Zone + + Gather Recent Historical Market Data + Gather Recent Historical Market Data - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Close Account - Close Account + + Gather All Historical Market Data + Gather All Historical Market Data - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - By ETF Holding - By ETF Holding + + Gather Historical Market Data + Gather Historical Market Data - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Data Gathering is off + Data Gathering is off - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Join now or check out the example account - Join now or check out the example account + + Performance Calculation + Performance Calculation - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + someone + someone - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Show more - Show more + + Add asset to watchlist + Add asset to watchlist - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Benchmarks - Benchmarks + + Watchlist + Watchlist - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Delete Profiles - Delete Profiles - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/pages/features/features-page.html + 197 - - - Do you really want to delete these profiles? - Do you really want to delete these profiles? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + libs/common/src/lib/routes/routes.ts + 110 - - Oops! Could not delete profiles. - Oops! Could not delete profiles. + + Do you really want to delete this item? + Do you really want to delete this item? - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Table - Table + + Log out + Log out - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/header/header.component.html + 329 - - Chart - Chart + + Calculations are based on delayed market data and may not be displayed in real-time. + Calculations are based on delayed market data and may not be displayed in real-time. - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-market/home-market.html + 44 - - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/components/markets/markets.html + 53 - - Alternative - Alternative + + changelog + changelog + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - App - App + + Demo user account has been synced. + Demo user account has been synced. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Budgeting - Budgeting + + Sync Demo User Account + Sync Demo User Account - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Community - Community + + Set up + Set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Family Office - Family Office + + No emergency fund has been set up + No emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Investor - Investor + + An emergency fund has been set up + An emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Open Source - Open Source + + Fee Ratio + Fee Ratio - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Personal Finance - Personal Finance + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Privacy - Privacy + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - Software - Software + + Name + Nome - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Tool - Tool + + Find holding or page... + Encontrar holding ou página... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - User Experience - User Experience + + Quick Links + Links rápidos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/assistant/assistant.html + 56 - - Wealth - Wealth + + Asset Profiles + Perfis de ativos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.html + 112 - - Wealth Management - Wealth Management + + Live Demo + Live Demo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Australia - Australia - libs/ui/src/lib/i18n.ts - 73 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Austria - Austria - libs/ui/src/lib/i18n.ts - 74 + libs/common/src/lib/routes/routes.ts + 231 - - Belgium - Belgium + + Open Source Alternative to + Alternativa de software livre ao - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 326 - - Bulgaria - Bulgaria + + Single Account + Single Account - libs/ui/src/lib/i18n.ts - 76 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Canada - Canada + + Your net worth is managed by a single account + Your net worth is managed by a single account - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Czech Republic - Czech Republic + + Your net worth is managed by ${accountsLength} accounts + Your net worth is managed by ${accountsLength} accounts - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - Finland - Finland + + personal-finance-tools + personal-finance-tools + kebab-case - libs/ui/src/lib/i18n.ts - 79 + libs/common/src/lib/routes/routes.ts + 312 - - - France - France - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 315 - - - Germany - Germany - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 323 - - India - India + + markets + markets + kebab-case - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 304 - - - Italy - Italy - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 307 - - Netherlands - Netherlands + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 85 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - New Zealand - New Zealand + + Get Access + Get Access - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Poland - Poland + + Learn more + Learn more - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - Romania - Romania + + Limited Offer! + Limited Offer! - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - South Africa - South Africa + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Thailand - Thailand + + Available + Available - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - United States - United States + + Unavailable + Unavailable - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Error - Error + + new + new - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Deactivate - Deactivate - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Activate - Activate + + Investment + Investment - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Inactive - Inactive + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Cancel - Cancel + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Close - Close + + Equity + Equity - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Yes - Yes + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Change with currency effect Change - Change with currency effect Change + + Fixed Income + Fixed Income - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Performance with currency effect Performance - Performance with currency effect Performance + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Close - Close + + Investment: Base Currency + Investment: Base Currency - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - Customize - Customize + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - Today - Today + + Investment + Investment - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - This year - This year + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - From the beginning - From the beginning + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - Oops! Invalid currency. - Oops! Invalid currency. + + start + start + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + libs/common/src/lib/routes/routes.ts + 336 - - - This page has been archived. - This page has been archived. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 337 - - is Open Source Software - is Open Source Software + + Do you really want to generate a new security token? + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is not Open Source Software - is not Open Source Software + + Generate + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is Open Source Software - is Open Source Software + + Stocks + Stocks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - is not Open Source Software - is not Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/pages/features/features-page.html + 15 - - can be self-hosted - can be self-hosted + + Cryptocurrencies + Criptomoedas - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - cannot be self-hosted - cannot be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - can be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - cannot be self-hosted + + Manage Asset Profile + Gerenciar perfil de ativos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - can be used anonymously + + Alternative Investment + Investimento Alternativo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - cannot be used anonymously + + Collectible + Colecionável - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - can be used anonymously + + Average Unit Price + Preço médio unitário - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - cannot be used anonymously - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Riscos de cluster de contas - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Riscos de cluster de classe de ativos - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Riscos de cluster monetário - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Riscos de Cluster do Mercado Econômico - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Fundo de Emergência - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Tarifas - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Riscos de cluster de mercado regional - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + Nenhum resultado encontrado... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Mercados Emergentes - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + Nenhuma conta foi configurada - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Seu patrimônio líquido é gerenciado por 0 contas - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Ásia-Pacífico - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Mercados Emergentes - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Europa - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japão - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + América do Norte - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + Encontre o Ghostfolio no GitHub - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Junte-se à comunidade do Ghostfolio Slack - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Siga o Ghostfolio no X (antigo Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Enviar um e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Siga o Ghostfolio no LinkedIn - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio é um negócio independente e autossuficiente - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Apoie o Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 5e8a124eb..9ab07640a 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -1,7635 +1,8134 @@ - + about hakkinda - snake-case + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 214 + + + faq + sss + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 245 + + + features + oezellikler + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 255 + + + license + lisans + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + piyasalar + kebab-case - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 260 + + + pricing + fiyatlandirma + kebab-case - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 270 + + + privacy-policy + gizlilik-politikasi + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + libs/common/src/lib/routes/routes.ts + 207 - - faq - sss - snake-case + + register + kayit-ol + kebab-case - apps/client/src/app/app.component.ts - 77 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/core/paths.ts - 3 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + kaynaklar + kebab-case - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 306 - - - features - oezellikler - snake-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 322 + + + Frequently Asked Questions (FAQ) + Sıkça Sorulan Sorular (SSS) - apps/client/src/app/components/header/header.component.ts - 87 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + Alım satımda kayıp riski büyük boyutta olabilir. Kısa vadede ihtiyaç duyabileceğiniz parayla yatırım yapmak tavsiye edilmez. - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + apps/client/src/app/app.component.html + 221 + + + Alias + Takma Ad - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + apps/client/src/app/components/access-table/access-table.component.html + 4 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 + + + Grantee + Hibe Alan / Alıcı - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + Type + Tip - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 15 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + libs/ui/src/lib/activities-table/activities-table.component.html + 161 + + + Details + Ayrıntılar - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 33 + + + Revoke + Geri Al - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + Do you really want to revoke this granted access? + Bu erişim iznini geri almayı gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + apps/client/src/app/components/access-table/access-table.component.ts + 108 - - license - lisans - snake-case + + Cash Balance + Nakit Bakiye - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 - apps/client/src/app/core/paths.ts - 5 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 - - markets - piyasalar - snake-case + + Platform + Platform - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 + + + Name + Ad - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 89 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 - - - pricing - fiyatlandirma - snake-case - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 - apps/client/src/app/components/header/header.component.ts - 89 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + libs/ui/src/lib/activities-table/activities-table.component.html + 138 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 - apps/client/src/app/core/http-response.interceptor.ts - 72 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 16 - apps/client/src/app/core/paths.ts - 7 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + Total + Toplam - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 55 + + + Currency + Para Birimi - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 - - - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 16 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + Value + Değer - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 - - - privacy-policy - gizlilik-politikasi - snake-case - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 - - - register - kayit-ol - snake-case - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 - apps/client/src/app/components/header/header.component.ts - 90 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 - apps/client/src/app/core/auth.guard.ts - 55 + libs/ui/src/lib/account-balances/account-balances.component.html + 34 - apps/client/src/app/core/paths.ts - 9 + libs/ui/src/lib/activities-table/activities-table.component.html + 257 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + libs/ui/src/lib/activities-table/activities-table.component.html + 293 - apps/client/src/app/pages/features/features-page.component.ts - 29 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 - - resources - kaynaklar - snake-case + + Edit + Düzenle - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 - apps/client/src/app/components/header/header.component.ts - 91 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 - apps/client/src/app/core/paths.ts - 10 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 430 + + + Delete + Sil - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 - apps/client/src/app/pages/features/features-page.component.ts - 30 + apps/client/src/app/components/admin-overview/admin-overview.html + 131 - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + libs/ui/src/lib/account-balances/account-balances.component.html + 80 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + libs/ui/src/lib/activities-table/activities-table.component.html + 457 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + + + Do you really want to delete this account? + Bu hesabı silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 - - Personal Finance - Kişisel Finans + + Data Source + Veri Kaynağı - apps/client/src/app/app.component.html - 57 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 - - - Markets - Piyasalar - apps/client/src/app/app.component.html - 61 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 + + + Attempts + Deneme - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 - - Resources - Piyasalar + + Created + Oluşturuldu - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 + + + Finished + Tamamlandı - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 + + + Status + Durum - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 - - About - Hakkında + + Delete Jobs + İşleri Sil - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + Asset Profiles + Varlık Profili - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 + + + Historical Market Data + Tarihsel Piyasa Verisi - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 - - - Blog - Blog - apps/client/src/app/app.component.html - 73 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + + + View Data + Veri Gör - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + View Stacktrace + Hata İzini Görüntüle - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + Delete Job + İşleri Sil - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + Details for + Detaylar - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + Date + Tarih - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + libs/ui/src/lib/account-balances/account-balances.component.html + 12 - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + libs/ui/src/lib/activities-table/activities-table.component.html + 170 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + Market Price + Piyasa Fiyatı - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 - - - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + Currencies + Para Birimleri - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + apps/client/src/app/pages/public/public-page.html + 88 + + + ETFs without Countries + Ülkesi Olmayan ETF’ler - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + ETFs without Sectors + Sektörü Olmayan ETF’ler - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + Filter by... + Filtrele... - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + İlk İşlem - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + apps/client/src/app/components/admin-market-data/admin-market-data.html 148 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 + + + Activities Count + İşlem Sayısı - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 - - Changelog - Değişiklik Günlüğü + + Historical Data + Tarihsel Veri - apps/client/src/app/app.component.html - 77 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 - - Features - Özellikler - - apps/client/src/app/app.component.html - 79 - + + Sectors Count + Sektör Sayısı - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + Countries Count + Ülke Sayısı - apps/client/src/app/pages/features/features-page.html - 5 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 - - Frequently Asked Questions (FAQ) - Sıkça Sorulan Sorular (SSS) + + Gather Profile Data + Profil Verisini Getir - apps/client/src/app/app.component.html - 83 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 - - License - Lisans - - apps/client/src/app/app.component.html - 88 - + + Refresh + Yenile - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 - - Pricing - Fiyatlandırma + + Sector + Sektör - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 + + + Country + Ülke - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/components/admin-users/admin-users.html + 78 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 - - Privacy Policy - Gizlilik Politikası + + Sectors + Sektörler - apps/client/src/app/app.component.html - 103 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 - - - Community - Topluluk - apps/client/src/app/app.component.html - 121 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 + apps/client/src/app/pages/public/public-page.html + 106 + + + Countries + Ülkeler - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 + + + Symbol Mapping + Sembol Eşleştirme - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 + + + Scraper Configuration + Veri Toplayıcı Yapılandırması - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 + + + Note + Not - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 + + + Add Asset Profile + Varlık Profili Ekle - apps/client/src/app/pages/features/features-page.html - 259 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 - - The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. - Alım satımda kayıp riski büyük boyutta olabilir. Kısa vadede ihtiyaç duyabileceğiniz parayla yatırım yapmak tavsiye edilmez. + + Name, symbol or ISIN + Ad, sembol ya da ISIN - apps/client/src/app/app.component.html - 200 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 - - - Alias - Takma Ad - apps/client/src/app/components/access-table/access-table.component.html - 4 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 11 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 - - - Grantee - Hibe Alan / Alıcı - apps/client/src/app/components/access-table/access-table.component.html - 11 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 - - Type - Tip + + Do you really want to delete this coupon? + Bu kuponu gerçekten silmek istiyor musunuz? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + Do you really want to flush the cache? + Önbelleği temizlemeyi gerçekten istiyor musunuz? - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 22 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 + + + Please set your system message: + Lütfen sistem mesajınızı belirleyin: - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 15 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 + + + User Count + Kullanıcı Sayısı - libs/ui/src/lib/activities-table/activities-table.component.html - 161 + apps/client/src/app/components/admin-overview/admin-overview.html + 13 - - Details - Ayrıntılar + + Activity Count + İşlem Sayısı - apps/client/src/app/components/access-table/access-table.component.html - 33 + apps/client/src/app/components/admin-overview/admin-overview.html + 19 - - Revoke - Geri Al + + per User + Kullanıcı başına - apps/client/src/app/components/access-table/access-table.component.html - 75 + apps/client/src/app/components/admin-overview/admin-overview.html + 28 - - Do you really want to revoke this granted access? - Bu erişim iznini geri almayı gerçekten istiyor musunuz? + + Add Currency + Para Birimi Ekle - apps/client/src/app/components/access-table/access-table.component.ts - 67 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 - - Cash Balance - Nakit Bakiye + + Tags + Etiketler - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 47 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 136 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 + + + + User Signup + Kullanıcı Kaydı + + apps/client/src/app/components/admin-overview/admin-overview.html 34 - - Equity - Menkul Kıymet + + Read-only Mode + Salt okunur mod - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + apps/client/src/app/components/admin-overview/admin-overview.html + 48 - - Platform - Platform + + System Message + Sistem Mesajı - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 67 + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + Set Message + Mesaj Belirle - apps/client/src/app/components/accounts-table/accounts-table.component.html - 86 + apps/client/src/app/components/admin-overview/admin-overview.html + 94 + + + Coupons + Kupon - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 48 + apps/client/src/app/components/admin-overview/admin-overview.html + 102 - - Activities - İşlemler + + Add + Ekle - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 + apps/client/src/app/components/admin-overview/admin-overview.html + 176 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + + + Housekeeping + Genel Ayarlar - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 + apps/client/src/app/components/admin-overview/admin-overview.html + 184 + + + Flush Cache + Önbelleği temizle - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 + apps/client/src/app/components/admin-overview/admin-overview.html + 200 + + + Add Platform + Platform Ekle - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + Url + Url - apps/client/src/app/components/admin-users/admin-users.html - 135 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 38 - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 25 - - Name - Ad + + Do you really want to delete this platform? + Bu platformu silmeyi gerçekten istiyor musunuz? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 43 + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + Update platform + Platformu Güncelle - apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + Add platform + Platform Ekle - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + Platforms + Platformlar - apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + Do you really want to delete this user? + Bu kullanıcıyı silmeyi gerçekten istiyor musunuz? - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 15 + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + User + Kullanıcı apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + 31 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 15 + apps/client/src/app/components/header/header.component.html + 231 + + + Engagement per Day + Günlük etkileşim - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 15 + apps/client/src/app/components/admin-users/admin-users.html + 158 + + + Last Request + Son Talep - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + Impersonate User + Kullanıcıyı Taklit Et - libs/ui/src/lib/activities-table/activities-table.component.html - 138 + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + Delete User + Kullanıcıyı Sil - libs/ui/src/lib/holdings-table/holdings-table.component.html - 28 + apps/client/src/app/components/admin-users/admin-users.html + 261 + + + Compare with... + Karşılaştır... - libs/ui/src/lib/top-holdings/top-holdings.component.html - 16 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + Manage Benchmarks + Karşılaştırma Ölçütlerini Yönet - libs/ui/src/lib/top-holdings/top-holdings.component.html - 88 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 - - Total - Toplam + + Portfolio + Portföy - apps/client/src/app/components/accounts-table/accounts-table.component.html - 55 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 - - - Currency - Para Birimi - apps/client/src/app/components/accounts-table/accounts-table.component.html - 65 + apps/client/src/app/components/header/header.component.html + 44 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + apps/client/src/app/components/header/header.component.html + 258 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 46 + libs/common/src/lib/routes/routes.ts + 151 + + + Benchmark + Karşılaştırma Ölçütü - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 25 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + Current Market Mood + Piyasa Psikolojisi - libs/ui/src/lib/activities-table/activities-table.component.html - 276 + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 - - Value - Değer + + About Ghostfolio + Ghostfolio Hakkında - apps/client/src/app/components/accounts-table/accounts-table.component.html - 171 + apps/client/src/app/components/header/header.component.html + 326 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 206 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 + + + Get started + Haydi Başlayalım - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 53 + apps/client/src/app/components/header/header.component.html + 432 + + + Sign in + Giriş - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + libs/common/src/lib/routes/routes.ts + 157 + + + Oops! Incorrect Security Token. + Hay Allah! Güvenlik anahtarı yanlış. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + apps/client/src/app/components/header/header.component.ts + 274 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - libs/ui/src/lib/account-balances/account-balances.component.html - 34 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 + + + Manage Activities + İşlemleri Yönet - libs/ui/src/lib/activities-table/activities-table.component.html - 257 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Fear + Korku - libs/ui/src/lib/activities-table/activities-table.component.html - 293 + apps/client/src/app/components/home-market/home-market.component.ts + 42 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 74 + apps/client/src/app/components/markets/markets.component.ts + 47 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 25 + libs/ui/src/lib/i18n.ts + 105 + + + Greed + Açgözlülük - libs/ui/src/lib/top-holdings/top-holdings.component.html - 102 + apps/client/src/app/components/home-market/home-market.component.ts + 43 - - - Edit - Düzenle - apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + apps/client/src/app/components/markets/markets.component.ts + 48 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 + libs/ui/src/lib/i18n.ts + 106 + + + Last Days + Son Gün - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + apps/client/src/app/components/markets/markets.html + 17 + + + Welcome to Ghostfolio + Ghostfolio’ya Hoşgeldiniz. - apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + apps/client/src/app/components/home-overview/home-overview.html + 11 + + + Ready to take control of your personal finances? + Kişisel finansal yönetiminizi ele almaya hazır mısınız? - libs/ui/src/lib/activities-table/activities-table.component.html - 430 + apps/client/src/app/components/home-overview/home-overview.html + 12 - - Delete - Sil + + Setup your accounts + Hesaplarınızı kurun - apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + apps/client/src/app/components/home-overview/home-overview.html + 19 + + + Get a comprehensive financial overview by adding your bank and brokerage accounts. + Banka ve yatırım hesaplarınızı ekleyerek kapsamlı finansal durumunuzu görün. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + apps/client/src/app/components/home-overview/home-overview.html + 21 + + + Capture your activities + İşlemlerinizi kaydedin - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 + apps/client/src/app/components/home-overview/home-overview.html + 28 + + + Record your investment activities to keep your portfolio up to date. + Yatırım işlemlerinizi kaydederek portföyünüzü güncel tutun. - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + apps/client/src/app/components/home-overview/home-overview.html + 30 + + + Monitor and analyze your portfolio + Portföyünüzü izleyin ve analiz edin. - apps/client/src/app/components/admin-overview/admin-overview.html - 206 + apps/client/src/app/components/home-overview/home-overview.html + 37 + + + Track your progress in real-time with comprehensive analysis and insights. + Kapsamlı analiz ve içgörülerle ilerleme durumunuzu gerçek zamanlı olarak takip edin. - apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + apps/client/src/app/components/home-overview/home-overview.html + 39 + + + Setup accounts + Hesaplarınızı kurunuz - apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + apps/client/src/app/components/home-overview/home-overview.html + 52 + + + Add activity + İşlem ekle. - libs/ui/src/lib/account-balances/account-balances.component.html - 80 + apps/client/src/app/components/home-overview/home-overview.html + 60 - libs/ui/src/lib/activities-table/activities-table.component.html - 457 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 8 - - Do you really want to delete this account? - Bu hesabı silmeyi gerçekten istiyor musunuz? + + Total Amount + Toplam Tutar - apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 - - Symbol - Sembol + + Savings Rate + Tasarruf Oranı - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 + + + Security Token + Güvenlik Jetonu - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - - - Data Source - Veri Kaynağı - apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 + + + or + veya - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - - - Attempts - Deneme - apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + apps/client/src/app/pages/landing/landing-page.html + 48 - - - Created - Oluşturuldu - apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + apps/client/src/app/pages/landing/landing-page.html + 451 - - - Finished - Tamamlandı - apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - - - Status - Durum - apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + apps/client/src/app/pages/register/register-page.html + 31 + + + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 - - Delete Jobs - İşleri Sil + + Sign in with Internet Identity + İnternet Kimliği (Internet Identity) ile Oturum Aç - apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 - - Asset Profiles - Varlık Profili + + Sign in with Google + Google ile Oturum Aç - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Historical Market Data - Tarihsel Piyasa Verisi + + Stay signed in + Oturumu açık tut - apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 - - View Data - Veri Gör + + Time in Market + Yatırım Süresi - apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 - - View Stacktrace - Hata İzini Görüntüle + + Absolute Gross Performance + Toplam Brüt Performans - apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 - - Delete Job - İşleri Sil + + Absolute Net Performance + Toplam Net Performans - apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 - - Details for - Detaylar + + Net Performance + Net Performans - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 2 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 - - Date - Tarih + + Total Assets + Toplam Varlıklar - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + Assets + Varlıklar - libs/ui/src/lib/account-balances/account-balances.component.html - 12 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 + + + Buying Power + Alım Limiti - libs/ui/src/lib/activities-table/activities-table.component.html - 170 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 + + + Excluded from Analysis + Analize Dahil Edilmemiştir. - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 6 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 - - Market Price - Piyasa Fiyatı + + Liabilities + Yükümlülükler - apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + apps/client/src/app/pages/features/features-page.html + 102 + + + Net Worth + Toplam Varlık - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 26 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 - - Cancel - İptal + + Annualized Performance + Yıllıklandırılmış Performans - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 + + + Please set the amount of your emergency fund. + Lütfen acil durum yedeği meblağını giriniz: - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 + + + Minimum Price + Asgari Fiyat - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 + + + Maximum Price + Azami Fiyat - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + Quantity + Miktar - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 153 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 189 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + libs/ui/src/lib/activities-table/activities-table.component.html + 186 + + + Fees + Komisyon - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 - - Save - Kaydet + + Report Data Glitch + Rapor Veri Sorunu - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 446 + + + Are you an ambitious investor who needs the full picture? + Tüm ayrıntılara hakim olmak isteyen iddialı bir yatırımcı mısınız? - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 + + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + Bugün Ghostfolio Premium’a yükseltin ve yatırım deneyiminizi geliştirmek için ayrıcalıklı özelliklere erişim kazanın: - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 + + + Portfolio Summary + Portföy Özeti - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 + apps/client/src/app/pages/pricing/pricing-page.html + 44 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 + apps/client/src/app/pages/pricing/pricing-page.html + 205 + + + Portfolio Allocations + Portföy Dağılımı - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + apps/client/src/app/pages/features/features-page.html + 161 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + apps/client/src/app/pages/pricing/pricing-page.html 48 - - - Currencies - Para Birimleri - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + apps/client/src/app/pages/pricing/pricing-page.html + 209 - - ETFs without Countries - Ülkesi Olmayan ETF’ler + + Performance Benchmarks + Performans Ölçütleri - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 - - - ETFs without Sectors - Sektörü Olmayan ETF’ler - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + apps/client/src/app/pages/pricing/pricing-page.html + 52 - - - Filter by... - Filtrele... - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + apps/client/src/app/pages/pricing/pricing-page.html + 213 - - Asset Class - Varlık Sınıfı - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 - + + FIRE Calculator + FIRE Hesaplayıcı - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + apps/client/src/app/pages/pricing/pricing-page.html + 56 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/pages/pricing/pricing-page.html + 217 + + + Professional Data Provider + Profesyonel Veri Sağlayıcı - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/pages/pricing/pricing-page.html + 237 - - Asset Sub Class - Varlık Alt Sınıfı + + and more Features... + ve daha fazla Özellik... - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 + apps/client/src/app/pages/pricing/pricing-page.html + 72 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 + apps/client/src/app/pages/pricing/pricing-page.html + 261 + + + Get the tools to effectively manage your finances and refine your personal investment strategy. + Mali durumunuzu etkili bir şekilde yönetecek ve kişisel yatırım stratejinizi geliştirecek Araçları edinin. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 + + + Skip + Geç - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 - - - First Activity - İlk İşlem - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + Upgrade Plan + Üyeliğinizi Yükseltin - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + apps/client/src/app/components/header/header.component.html + 193 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 70 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 - - - Activities Count - İşlem Sayısı - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + apps/client/src/app/pages/pricing/pricing-page.html + 299 - - Historical Data - Tarihsel Veri + + Today + Bugün - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + apps/client/src/app/pages/public/public-page.html + 24 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 + libs/ui/src/lib/assistant/assistant.component.ts + 348 - - Sectors Count - Sektör Sayısı + + YTD + YTD - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Countries Count - Ülke Sayısı + + 1Y + 1Y - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - Gather Recent Data - Son Veriyi Getir + + 5Y + 5Y - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Gather All Data - Tüm Veriyi Getir + + Max + Maks. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + libs/ui/src/lib/assistant/assistant.component.ts + 401 - - Gather Profile Data - Profil Verisini Getir + + This feature is currently unavailable. + Bu özellik şu an için mevcut değil. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + apps/client/src/app/core/http-response.interceptor.ts + 55 + + + Please try again later. + Daha sonra tekrar deneyiniz. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 + apps/client/src/app/core/http-response.interceptor.ts + 57 - - - Refresh - Yenile - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + apps/client/src/app/core/http-response.interceptor.ts + 88 - - - Gather Historical Data - Tarihsel Veriyi Getir - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 - - Sector - Sektör + + Oops! Something went wrong. + Hay Allah! Bir şeyler yanlış gitti. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + apps/client/src/app/core/http-response.interceptor.ts + 86 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 - - Country - Ülke + + Okay + Tamam - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 - apps/client/src/app/components/admin-users/admin-users.html - 77 + apps/client/src/app/core/http-response.interceptor.ts + 89 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 - - Sectors - Sektörler + + About + Hakkında - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + apps/client/src/app/app.component.html + 70 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + apps/client/src/app/components/header/header.component.html + 375 - apps/client/src/app/pages/public/public-page.html - 106 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 220 - - Countries - Ülkeler + + Changelog + Değişiklik Günlüğü - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + apps/client/src/app/app.component.html + 77 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + libs/common/src/lib/routes/routes.ts + 185 - - Symbol Mapping - Sembol Eşleştirme + + License + Lisans - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + apps/client/src/app/app.component.html + 89 - - - Scraper Configuration - Veri Toplayıcı Yapılandırması - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + apps/client/src/app/pages/about/license/license-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 193 - - Note - Not + + Privacy Policy + Gizlilik Politikası - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + apps/client/src/app/app.component.html + 105 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 78 + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + libs/common/src/lib/routes/routes.ts + 209 - - Add Asset Profile - Varlık Profili Ekle + + Our + Bizim - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 7 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 - - Name, symbol or ISIN - Ad, sembol ya da ISIN + + Discover other exciting Open Source Software projects + Diğer heyecan verici Açık Kaynak Yazılım projelerini keşfedin - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 29 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 + + + Visit + Ziyaret et - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 - - Please add a currency: - Lütfen bir para birimi giriniz: + + Accounts + Hesaplar - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - Do you really want to delete this coupon? - Önbelleği temizlemeyi gerçekten istiyor musunuz? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + apps/client/src/app/components/admin-users/admin-users.html + 115 - - - Do you really want to delete this currency? - Bu para birimini silmeyi gerçekten istiyor musunuz? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + apps/client/src/app/components/header/header.component.html + 58 - - - Do you really want to flush the cache? - Önbelleği temizlemeyi gerçekten istiyor musunuz - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + apps/client/src/app/components/header/header.component.html + 268 - - - Please set your system message: - Lütfen sistem mesajınızı belirleyin: - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 - - - User Count - Kullanıcı Sayısı - apps/client/src/app/components/admin-overview/admin-overview.html - 13 + apps/client/src/app/pages/accounts/accounts-page.html + 4 - - - Activity Count - İşlem Sayısı - apps/client/src/app/components/admin-overview/admin-overview.html - 19 + libs/common/src/lib/routes/routes.ts + 69 - - per User - Kullanıcı başına + + Update account + Hesabı Güncelle - apps/client/src/app/components/admin-overview/admin-overview.html - 28 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 - - Exchange Rates - Döviz Kurları + + Add account + Hesap ekle - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - - Add Currency - Para Birimi Ekle + + Account ID + Hesap Kimliği - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 22 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 + + + Admin Control + Yönetici Denetimleri - apps/client/src/app/components/admin-overview/admin-overview.html - 105 + apps/client/src/app/components/header/header.component.html + 74 - - - Tags - Etiketler - apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 + apps/client/src/app/components/header/header.component.html + 289 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + libs/common/src/lib/routes/routes.ts + 64 + + + Market Data + Piyasa Verileri apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + 393 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/common/src/lib/routes/routes.ts + 51 - - User Signup - Kullanıcı Kaydı + + Settings + Ayarlar - apps/client/src/app/components/admin-overview/admin-overview.html - 111 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - - - Read-only Mode - Salt okunur mod - apps/client/src/app/components/admin-overview/admin-overview.html - 125 + libs/common/src/lib/routes/routes.ts + 34 - - - System Message - Sistem Mesajı - apps/client/src/app/components/admin-overview/admin-overview.html - 149 + libs/common/src/lib/routes/routes.ts + 56 - - Set Message - Mesaj Belirle + + Users + Kullanıcılar - apps/client/src/app/components/admin-overview/admin-overview.html - 171 + libs/common/src/lib/routes/routes.ts + 61 - - Coupons - Kupon + + Overview + Özet - apps/client/src/app/components/admin-overview/admin-overview.html - 179 + apps/client/src/app/components/header/header.component.html + 30 - - - Add - Ekle - apps/client/src/app/components/admin-overview/admin-overview.html - 239 + apps/client/src/app/components/header/header.component.html + 248 - libs/ui/src/lib/account-balances/account-balances.component.html - 93 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 - - - Housekeeping - Genel Ayarlar - apps/client/src/app/components/admin-overview/admin-overview.html - 247 + apps/client/src/app/pages/admin/admin-page.component.ts + 48 - - - Flush Cache - Önbelleği temizle - apps/client/src/app/components/admin-overview/admin-overview.html - 251 + apps/client/src/app/pages/resources/resources-page.component.ts + 30 - - - Add Platform - Platform Ekle - apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + libs/common/src/lib/routes/routes.ts + 113 - - - Url - Url - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + libs/common/src/lib/routes/routes.ts + 170 + + + Blog + Blog - apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + apps/client/src/app/app.component.html + 74 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 25 + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 - - - Accounts - Hesaplar - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 - apps/client/src/app/components/header/header.component.html - 263 + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 - - - Do you really want to delete this platform? - Bu platformu silmeyi gerçekten istiyor musunuz? - apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 - - - Update platform - Platformu Güncelle - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 8 + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 - - - Add platform - Platform Ekle - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 10 + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 - - - Platforms - Platformlar - apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 - - - Do you really want to delete this user? - Bu kullanıcıyı silmeyi gerçekten istiyor musunu? - apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 - - - User - Kullanıcı - apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 - apps/client/src/app/components/header/header.component.html - 229 + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 - - - Registration - Kayıt - apps/client/src/app/components/admin-users/admin-users.html - 97 + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 - - - Engagement per Day - Günlük etkileşim - apps/client/src/app/components/admin-users/admin-users.html - 157 + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 - - - Last Request - Son Talep - apps/client/src/app/components/admin-users/admin-users.html - 202 + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 - - - Impersonate User - Kullanıcıyı Taklit Et - apps/client/src/app/components/admin-users/admin-users.html - 239 + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 - - - Delete User - Kullanıcıyı Sil - apps/client/src/app/components/admin-users/admin-users.html - 251 + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 - - - Performance - Performans - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 - - Compare with... - Karşılaştır... + + Discover the latest Ghostfolio updates and insights on personal finance + Son Ghostfolio güncellemelerini ve kişisel finans hakkındaki en son bilgileri keşfedin. - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 18 + apps/client/src/app/pages/blog/blog-page.html + 7 - - Manage Benchmarks - Karşılaştırma Ölçütlerini Yönet + + As you are already logged in, you cannot access the demo account. + Oturum açmış olduğunuz için demo hesabına erişemezsiniz. - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + apps/client/src/app/pages/demo/demo-page.component.ts 35 - - Portfolio - Portföy + + Frequently Asked Questions (FAQ) + Sıkça Sorulan Sorular (SSS) - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 - - - Benchmark - Karşılaştırma Ölçütü - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + libs/common/src/lib/routes/routes.ts + 251 - - Current Market Mood - Piyasa Psikolojisi + + Features + Özellikler - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 + apps/client/src/app/app.component.html + 79 - - - Overview - Genel Bakış apps/client/src/app/components/header/header.component.html - 28 + 361 - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 - - Portfolio - Portföy + + Check out the numerous features of Ghostfolio to manage your wealth + Varlıklarınızı yönetmek için Ghostfolio’nun özelliklerini keşfedin - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 7 + + + ETFs + ETF’ler - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/features/features-page.html + 25 - - Admin Control - Yönetici Kontrolü + + Bonds + Tahviller - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/pages/features/features-page.html + 38 + + + Wealth Items + Varlık Kalemleri - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/pages/features/features-page.html + 76 - - Me - Ben + + Import and Export + İçe Aktar / Dışa Aktar - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/features/features-page.html + 116 - - My Ghostfolio - Ghostfolio’m + + Multi-Accounts + Çoklu Hesaplar - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/features/features-page.html + 127 - - About Ghostfolio - Ghostfolio Hakkında + + Portfolio Calculations + Portföy Hesaplama - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/pages/features/features-page.html + 141 + + + Dark Mode + Karanlık Mod - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/features/features-page.html + 233 - - Sign in - Giriş + + Zen Mode + Zen Modu - apps/client/src/app/components/header/header.component.html - 412 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + apps/client/src/app/pages/features/features-page.html + 246 - - Get started - Haydi Başlayalım + + Market Mood + Piyasa Modu - apps/client/src/app/components/header/header.component.html - 422 + apps/client/src/app/pages/features/features-page.html + 215 - - Sign in - Giriş + + Static Analysis + Statik Analiz - apps/client/src/app/app-routing.module.ts - 150 + apps/client/src/app/pages/features/features-page.html + 179 + + + Multi-Language + Çoklu Dil - apps/client/src/app/components/header/header.component.ts - 230 + apps/client/src/app/pages/features/features-page.html + 259 - - Oops! Incorrect Security Token. - Hay Allah! Güvenlik anahtarı yanlış. + + Open Source Software + Açık Kaynak Yazılım - apps/client/src/app/components/header/header.component.ts - 245 + apps/client/src/app/pages/features/features-page.html + 295 + + + Get Started + Başla - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + apps/client/src/app/pages/features/features-page.html + 320 - - - Manage Activities - İşlemleri Yönet - apps/client/src/app/components/home-holdings/home-holdings.html - 63 + apps/client/src/app/pages/public/public-page.html + 220 - - Fear - Korku + + Holdings + Varlıklar - apps/client/src/app/components/home-market/home-market.component.ts - 27 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - libs/ui/src/lib/i18n.ts - 98 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - - - Greed - Açgözlülük - apps/client/src/app/components/home-market/home-market.component.ts - 28 + apps/client/src/app/pages/public/public-page.html + 70 - libs/ui/src/lib/i18n.ts - 99 + libs/common/src/lib/routes/routes.ts + 90 - - - Last Days - Son Gün - apps/client/src/app/components/home-market/home-market.html - 7 + libs/common/src/lib/routes/routes.ts + 167 - - Welcome to Ghostfolio - Ghostfolio’ya Hoşgeldiniz. + + Summary + Özet - apps/client/src/app/components/home-overview/home-overview.html - 7 + apps/client/src/app/components/home-summary/home-summary.html + 2 - - - Ready to take control of your personal finances? - Kişisel finansal yönetiminizi ele almaya hazır mısınız? - apps/client/src/app/components/home-overview/home-overview.html - 8 + libs/common/src/lib/routes/routes.ts + 105 - - Setup your accounts - Hesaplarınızı kurun + + Markets + Piyasalar - apps/client/src/app/components/home-overview/home-overview.html - 15 + apps/client/src/app/app.component.html + 61 - - - Get a comprehensive financial overview by adding your bank and brokerage accounts. - Banka ve yatırım hesaplarınızı ekleyerek kapsamlı finansal durumunuzu görün. - apps/client/src/app/components/home-overview/home-overview.html - 17 + apps/client/src/app/components/header/header.component.html + 408 - - - Capture your activities - İşlemlerinizi kaydedin - apps/client/src/app/components/home-overview/home-overview.html - 24 + apps/client/src/app/components/home-market/home-market.html + 2 - - - Record your investment activities to keep your portfolio up to date. - Yatırım işlemlerinizi kaydederek portföyünüzü güncel tutun. - apps/client/src/app/components/home-overview/home-overview.html - 26 + apps/client/src/app/components/markets/markets.html + 2 - - - Monitor and analyze your portfolio - Portföyünüzü izleyin ve analiz edin. - apps/client/src/app/components/home-overview/home-overview.html - 33 + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 - - - Track your progress in real-time with comprehensive analysis and insights. - Kapsamlı analiz ve içgörülerle ilerleme durumunuzu gerçek zamanlı olarak takip edin. - apps/client/src/app/components/home-overview/home-overview.html - 35 + apps/client/src/app/pages/resources/resources-page.component.ts + 40 - - - Setup accounts - Hesaplarınızı kurunuz - apps/client/src/app/components/home-overview/home-overview.html - 44 + libs/common/src/lib/routes/routes.ts + 95 - - - Add activity - İşlem ekle. - apps/client/src/app/components/home-overview/home-overview.html - 52 + libs/common/src/lib/routes/routes.ts + 100 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 8 + libs/common/src/lib/routes/routes.ts + 261 - - - Summary - Özet - apps/client/src/app/components/home-summary/home-summary.html - 2 + libs/common/src/lib/routes/routes.ts + 309 - - Total Amount - Toplam Tutar + + Manage your wealth like a boss + Varlıklarınızı bir patron gibi yönetin - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + apps/client/src/app/pages/landing/landing-page.html + 6 - - Savings Rate - Tasarruf Oranı + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio, mali durumunuz için gizlilik odaklı, açık kaynaklı bir kontrol panelidir. Varlık dağılımınızı analiz edin, net değerinizi öğrenin ve sağlam, veriye dayalı yatırım kararları alın. - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + apps/client/src/app/pages/landing/landing-page.html + 10 - - Security Token - Güvenlik Jetonu - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - + + Get Started + Başla - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 + apps/client/src/app/pages/landing/landing-page.html + 42 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/pages/landing/landing-page.html + 447 - - - or - veya - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/pages/pricing/pricing-page.html + 351 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 + + + Monthly Active Users + Aylık Aktif Kullanıcılar apps/client/src/app/pages/landing/landing-page.html - 47 + 70 + + + Stars on GitHub + GitHub’daki Beğeniler apps/client/src/app/pages/landing/landing-page.html - 450 + 88 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 + apps/client/src/app/pages/open/open-page.html + 103 + + + Pulls on Docker Hub + Docker Hub’ta Çekmeler - apps/client/src/app/pages/register/register-page.html - 30 + apps/client/src/app/pages/landing/landing-page.html + 106 - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + apps/client/src/app/pages/open/open-page.html + 117 - - Sign in with Internet Identity - İnternet Kimliği (Internet Identity) ile Oturum Aç + + As seen in + Şurada görüldüğü gibi - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 + apps/client/src/app/pages/landing/landing-page.html + 115 - - Sign in with Google - Google ile Oturum Aç + + Protect your assets. Refine your personal investment strategy. + varlıklarınızı koruyun. Kişisel yatırım stratejinizi geliştirin. - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 + apps/client/src/app/pages/landing/landing-page.html + 226 - - Stay signed in - Oturumu açık tut + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio, takip edilmeden hisse senetleri, ETF’ler veya kripto paraları izlemek isteyen yoğun insanlara güç verir. - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 230 - - Time in Market - Yatırım Süresi + + 360° View + 360° Görünüm - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 + apps/client/src/app/pages/landing/landing-page.html + 240 - - Buy - Al + + Get the full picture of your personal finances across multiple platforms. + Kişisel finansınızın tam resmini birden fazla platformda edinin. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + apps/client/src/app/pages/landing/landing-page.html + 243 - - Sell - Sat + + Web3 Ready + Web3 Hazır - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + apps/client/src/app/pages/landing/landing-page.html + 251 - - Investment - Yatırım - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 - + + Use Ghostfolio anonymously and own your financial data. + Ghostfolio’yu anonim olarak kullanın ve finansal verilerinize sahip çıkın. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 + apps/client/src/app/pages/landing/landing-page.html + 254 - - Absolute Gross Performance - Toplam Brüt Performans + + Benefit from continuous improvements through a strong community. + Güçlü bir topluluk aracılığıyla sürekli gelişmelerden faydalanın. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 + apps/client/src/app/pages/landing/landing-page.html + 264 - - Absolute Net Performance - Toplam Net Performans + + Why Ghostfolio? + Neden Ghostfolio? - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 + apps/client/src/app/pages/landing/landing-page.html + 272 - - Net Performance - Net Performans + + Ghostfolio is for you if you are... + Ghostfolio tam size göre, - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/pages/landing/landing-page.html + 274 - - Total Assets - Toplam Varlıklar + + trading stocks, ETFs or cryptocurrencies on multiple platforms + Birden fazla platformda hisse senedi, ETF veya kripto para ticareti yapıyorsanız, - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 143 + apps/client/src/app/pages/landing/landing-page.html + 280 - - Valuables - Yatırım Varlıkları + + pursuing a buy & hold strategy + al ve tut stratejisi izliyorsanız, - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 + apps/client/src/app/pages/landing/landing-page.html + 286 - - Emergency Fund - Acil Durum Yedeği + + interested in getting insights of your portfolio composition + Portföy bileşimine dair içgörüleri edinmek istiyorsanız, - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 + apps/client/src/app/pages/landing/landing-page.html + 291 + + + valuing privacy and data ownership + Gizliliğe ve verilerinize sahip çıkmayı önemsiyorsanız - apps/client/src/app/pages/features/features-page.html - 89 + apps/client/src/app/pages/landing/landing-page.html + 296 + + + into minimalism + minimalizme ilgi duyuyorsanız - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 + apps/client/src/app/pages/landing/landing-page.html + 299 - - Cash - Nakit + + caring about diversifying your financial resources + finansal kaynaklarınızı çeşitlendirmeye önem veriyorsanız - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/pages/landing/landing-page.html + 303 - - Assets - Varlıklar + + interested in financial independence + finansal özgürlük peşindeyseniz - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + apps/client/src/app/pages/landing/landing-page.html + 307 - - Buying Power - Alım Limiti + + saying no to spreadsheets in + elektronik tablo uygulamalarına hayır diyorsanız - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + apps/client/src/app/pages/landing/landing-page.html + 311 - - Excluded from Analysis - Analize Dahil Edilmemiştir. + + still reading this list + bu listeyi hala okuyorsanız - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + apps/client/src/app/pages/landing/landing-page.html + 314 - - Liabilities - Yükümlülükler + + Learn more about Ghostfolio + Ghostfolio hakkında daha fazla bilgi edinin - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + apps/client/src/app/pages/landing/landing-page.html + 319 + + + What our users are saying + Kullanıcılarımızın görüşleri - apps/client/src/app/pages/features/features-page.html - 102 + apps/client/src/app/pages/landing/landing-page.html + 328 - - Net Worth - Toplam Varlık + + Members from around the globe are using Ghostfolio Premium + Dünyanın dört bir yanındaki kullanıcılar Ghostfolio Premium kullanıyorlar. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + apps/client/src/app/pages/landing/landing-page.html + 367 - - Annualized Performance - Yıllıklandırılmış Performans + + How does Ghostfolio work? + NasılGhostfolio çalışır? - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 + apps/client/src/app/pages/landing/landing-page.html + 384 - - Dividend - Temettü + + Get started in only 3 steps + Sadece 3 adımda başlayın - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 + apps/client/src/app/pages/landing/landing-page.html + 386 + + + Sign up anonymously* + Anonim olarak kaydolun* - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 + apps/client/src/app/pages/landing/landing-page.html + 392 + + + * no e-mail address nor credit card required + * e-posta adresi veya kredi kartı gerekmez - apps/client/src/app/pages/features/features-page.html - 63 + apps/client/src/app/pages/landing/landing-page.html + 394 + + + Add any of your historical transactions + Herhangi bir geçmiş işleminizi ekleyin - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + apps/client/src/app/pages/landing/landing-page.html + 406 + + + Get valuable insights of your portfolio composition + Portföy bileşiminizle ilgili değerli bilgiler edinin - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + apps/client/src/app/pages/landing/landing-page.html + 418 - - Please set the amount of your emergency fund. - Lütfen acil durum yedeği meblağını giriniz: + + Are you ready? + Hazır mısınız? - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + apps/client/src/app/pages/landing/landing-page.html + 432 - - Change - Para Birimi + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + Ghostfolio’da şeffaflık, değerlerimizin temelinde yer alır. Kaynak kodunu açık kaynak yazılım (OSS) olarak AGPL-3.0 lisansı altında yayınlıyoruz ve platformun işletme durumunun toplu anahtar metriklerini açıkça paylaşıyoruz. - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + apps/client/src/app/pages/open/open-page.html + 7 - - Average Unit Price - Ortalama Birim Fiyat + + Active Users + Aktif Kullanıcılar - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + apps/client/src/app/pages/open/open-page.html + 40 - - - Minimum Price - Asgari Fiyat - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + apps/client/src/app/pages/open/open-page.html + 62 - - Maximum Price - Azami Fiyat + + New Users + Yeni Kullanıcılar - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + apps/client/src/app/pages/open/open-page.html + 51 - - Quantity - Miktar + + Users in Slack community + Slack topluluğundaki kullanıcılar - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + apps/client/src/app/pages/open/open-page.html + 75 + + + Contributors on GitHub + GitHub’da Katkıda Bulunanlar - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + apps/client/src/app/pages/open/open-page.html + 89 + + + Uptime + Çalışma Süresi - libs/ui/src/lib/activities-table/activities-table.component.html - 186 + apps/client/src/app/pages/open/open-page.html + 132 - - Fees - Komisyon + + Activities + İşlemler - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 84 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 - - - Report Data Glitch - Rapor Veri Sorunu - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 - - - Are you an ambitious investor who needs the full picture? - Tüm ayrıntılara hakim olmak isteyen iddialı bir yatırımcı mısınız? - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - - - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - Bugün Ghostfolio Premium’a yükseltin ve yatırım deneyiminizi geliştirmek için ayrıcalıklı özelliklere erişim kazanın: - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + apps/client/src/app/components/admin-users/admin-users.html + 136 - - - Portfolio Summary - Portföy Özeti - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 24 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - apps/client/src/app/pages/pricing/pricing-page.html - 57 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - apps/client/src/app/pages/pricing/pricing-page.html - 213 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 - - - Portfolio Allocations - Portföy Dağılımı - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 28 + libs/common/src/lib/routes/routes.ts + 128 + + + Do you really want to delete these activities? + Tüm işlemlerinizi silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/features/features-page.html - 161 - - - apps/client/src/app/pages/pricing/pricing-page.html - 61 + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 + + + Update activity + İşlemi Güncelle - apps/client/src/app/pages/pricing/pricing-page.html - 217 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 - - Performance Benchmarks - Performans Ölçütleri + + Stocks, ETFs, bonds, cryptocurrencies, commodities + Hisse senetleri, ETF’ler, tahviller, kripto paralar, emtialar - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 32 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 - apps/client/src/app/pages/pricing/pricing-page.html + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 65 - - apps/client/src/app/pages/pricing/pricing-page.html - 221 - - - FIRE Calculator - FIRE Hesaplayıcı + + Mortgages, personal loans, credit cards + Mortgage, kişisel krediler, kredi kartları - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 36 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 + + + Luxury items, real estate, private companies + Lüks eşyalar, gayrimenkuller, özel şirketler - apps/client/src/app/pages/pricing/pricing-page.html - 69 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 + + + Update Cash Balance + Nakit Bakiyesini Güncelle - apps/client/src/app/pages/pricing/pricing-page.html - 225 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 - - Professional Data Provider - Profesyonel Veri Sağlayıcı + + Unit Price + Birim Fiyat - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 40 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 - apps/client/src/app/pages/pricing/pricing-page.html - 240 + libs/ui/src/lib/activities-table/activities-table.component.html + 210 - - and more Features... - ve daha fazla Özellik... - - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 44 - + + Import Activities + İşlemleri İçe Aktar - apps/client/src/app/pages/pricing/pricing-page.html - 85 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 - apps/client/src/app/pages/pricing/pricing-page.html - 252 + libs/ui/src/lib/activities-table/activities-table.component.html + 9 - - - Get the tools to effectively manage your finances and refine your personal investment strategy. - Mali durumunuzu etkili bir şekilde yönetecek ve kişisel yatırım stratejinizi geliştirecek Araçları edinin. - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - - Skip - Geç + + Import Dividends + Temettüleri İçe Aktar - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 129 - - - Upgrade Plan - Üyeliğinizi Yükseltin - apps/client/src/app/components/header/header.component.html - 185 + libs/ui/src/lib/activities-table/activities-table.component.html + 29 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + libs/ui/src/lib/activities-table/activities-table.component.html + 383 + + + Importing data... + Veri içe aktarılıyor... - apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 167 + + + Import has been completed + İçe aktarma tamamlandı - apps/client/src/app/pages/pricing/pricing-page.html - 288 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 176 - - Today - Bugün + + Validating data... + Veri doğrulanıyor... - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 + + + Select Holding + Varlık Seç - libs/ui/src/lib/assistant/assistant.component.ts - 221 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 - - YTD - YTD + + Select File + Dosya Seç - apps/client/src/app/components/toggle/toggle.component.ts + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 22 - - libs/ui/src/lib/assistant/assistant.component.ts - 231 - - - 1Y - 1Y + + Holding + Varlık - apps/client/src/app/components/toggle/toggle.component.ts - 23 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/assistant/assistant.html + 179 - - 5Y - 5Y - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - + + Load Dividends + Temettü Yükle - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 - - Max - Maks. + + The following file formats are supported: + Aşağıdaki dosya formatları desteklenmektedir: - apps/client/src/app/components/toggle/toggle.component.ts - 25 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 + + + Select Dividends + Temettü Seç - libs/ui/src/lib/assistant/assistant.component.ts - 260 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 - - This feature is currently unavailable. - Bu özellik şu an için mevcut değil. + + Select Activities + İşlemleri Seç - apps/client/src/app/core/http-response.interceptor.ts - 53 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 - - Please try again later. - Daha sonra tekrar deneyiniz. + + Back + Geri - apps/client/src/app/core/http-response.interceptor.ts - 55 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 - apps/client/src/app/core/http-response.interceptor.ts - 80 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 + + + Import + İçe Aktar - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 - - - Oops! Something went wrong. - Hay Allah! Bir şeyler yanlış gitti. - apps/client/src/app/core/http-response.interceptor.ts - 78 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 - - Okay - Tamam + + Allocations + Dağılımlar - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - apps/client/src/app/core/http-response.interceptor.ts - 81 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + libs/common/src/lib/routes/routes.ts + 133 - - About - Hakkında + + Proportion of Net Worth + Net Değer Oranı - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 + + + By Platform + Platforma Göre - apps/client/src/app/pages/about/about-page.component.ts + apps/client/src/app/pages/portfolio/allocations/allocations-page.html 44 - - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 - - - Changelog - Değişiklik Günlüğü + + By Currency + Para Birimine Göre - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 + + + By Asset Class + Varlık Sınıfına Göre - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 - - License - Lisans + + By Holding + Varlığa Göre - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 + + + By Sector + Sektöre Göre - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 - - Privacy Policy - Gizlilik Politikası + + By Continent + Kıtaya Göre - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 + + + By Market + Piyasaya Göre - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 175 - - Our - Bizim + + Regions + Bölgeler - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 - - - Discover other exciting Open Source Software projects - Diğer heyecan verici Açık Kaynak Yazılım projelerini keşfedin - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + apps/client/src/app/pages/public/public-page.html + 143 - - Visit - Ziyaret et + + Developed Markets + Gelişmiş Piyasalar - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 - - - Accounts - Hesaplar - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/pages/public/public-page.html + 160 - - Update account - Hesabı Güncelle + + Emerging Markets + Gelişmekte Olan Piyasalar - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 - - - Add account - Hesap ekle - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/pages/public/public-page.html + 169 - - Account ID - Hesap Kimliği + + Other Markets + Diğer Piyasalar - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 96 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 + + + apps/client/src/app/pages/public/public-page.html + 178 - - Admin Control - Yönetici Denetimleri + + By Account + Hesaba Göre - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 - - Market Data - Piyasa Verileri + + By ETF Provider + ETF Sağlayıcısına Göre - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 + + + By Country + Ülkeye Göre - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 - - Settings - Ayarlar + + Analysis + Analiz - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 - apps/client/src/app/pages/admin/admin-page.component.ts - 32 + libs/common/src/lib/routes/routes.ts + 138 + + + Dividend + Temettü - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 - - - Users - Kullanıcılar - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/pages/features/features-page.html + 63 - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 - - - Overview - Özet - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 - apps/client/src/app/pages/home/home-page.component.ts - 37 + libs/ui/src/lib/i18n.ts + 36 + + + Deposit + Para Yatırma - apps/client/src/app/pages/resources/resources-page.component.ts - 16 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 + + + Monthly + Aylık - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 + + + Yearly + Yıllık - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 - - Blog - Blog + + Top + Üst - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 - - Discover the latest Ghostfolio updates and insights on personal finance - Son Ghostfolio güncellemelerini ve kişisel finans hakkındaki en son bilgileri keşfedin. + + Bottom + Alt - apps/client/src/app/pages/blog/blog-page.html - 7 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 - - As you are already logged in, you cannot access the demo account. - Oturum açmış olduğunuz için demo hesabına erişemezsiniz. + + Portfolio Evolution + Portföyün Gelişimi - apps/client/src/app/pages/demo/demo-page.component.ts - 35 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 - - Frequently Asked Questions (FAQ) - Sıkça Sorulan Sorular (SSS) + + Investment Timeline + Yatırım Zaman Çizelgesi - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 + + + Current Streak + Güncel Seri - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 - - Frequently Asked Questions (FAQ) - Sıkça Sorulan Sorular (SSS) + + Longest Streak + En Uzun Seri - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 + + + Dividend Timeline + Temettü Zaman Çizelgesi - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 + + + FIRE + Finansal Özgürlük ve Erken Emeklilik (FIRE) - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + apps/client/src/app/pages/portfolio/fire/fire-page.html 4 - - Features - Özellikler + + Calculator + Hesap Makinesi - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 - - Check out the numerous features of Ghostfolio to manage your wealth - Varlıklarınızı yönetmek için Ghostfolio’nun özelliklerini keşfedin + + 4% Rule + %4 Kuralı - apps/client/src/app/pages/features/features-page.html - 6 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 - - Stocks - Hisse Senetleri + + Holdings + Varlıklar - apps/client/src/app/pages/features/features-page.html - 15 - - - - ETFs - ETF’ler - - apps/client/src/app/pages/features/features-page.html - 25 + libs/ui/src/lib/assistant/assistant.html + 82 - - Bonds - Tahviller + + Pricing + Fiyatlandırma - apps/client/src/app/pages/features/features-page.html - 38 + apps/client/src/app/app.component.html + 99 - - - Cryptocurrencies - Kripto paralar - apps/client/src/app/pages/features/features-page.html - 51 + apps/client/src/app/components/header/header.component.html + 105 - - - Wealth Items - Varlık Kalemleri - apps/client/src/app/pages/features/features-page.html - 76 + apps/client/src/app/components/header/header.component.html + 313 - - - Import and Export - İçe Aktar / Dışa Aktar - apps/client/src/app/pages/features/features-page.html - 115 + apps/client/src/app/components/header/header.component.html + 389 - - - Multi-Accounts - Çoklu Hesaplar - apps/client/src/app/pages/features/features-page.html - 127 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts + 13 - - - Portfolio Calculations - Portföy Hesaplama - apps/client/src/app/pages/features/features-page.html - 141 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 - - - Dark Mode - Karanlık Mod - apps/client/src/app/pages/features/features-page.html - 178 + libs/common/src/lib/routes/routes.ts + 271 - - Zen Mode - Zen Modu - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 - + + Pricing Plans + Fiyatlandırma Planları - apps/client/src/app/pages/features/features-page.html - 191 + apps/client/src/app/pages/pricing/pricing-page.html + 4 - - Market Mood - Piyasa Modu + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Resmi Ghostfolio Premium bulut teklifimiz bir başlangıç yapmanın en kolay yoludur. Zaman tasarrufu sağladığı için çoğu insan için en iyi seçenek olacaktır. Gelir, barındırma altyapısının maliyetlerini karşılamak ve süregiden geliştirme işlerini finanse etmek için kullanılmaktadır. - apps/client/src/app/pages/features/features-page.html - 206 + apps/client/src/app/pages/pricing/pricing-page.html + 7 - - Static Analysis - Statik Analiz + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Ghostfolio’yu kendi altyapınızda çalıştırmayı tercih ederseniz, lütfen kaynak kodunu ve daha fazla talimatı GitHub adresinde bulun. - apps/client/src/app/pages/features/features-page.html - 225 + apps/client/src/app/pages/pricing/pricing-page.html + 14 - - Multi-Language - Çoklu Dil + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + Kendi altyapılarında Ghostfolio’yu çalıştırmayı tercih eden teknolojiye hakim yatırımcılar için. - apps/client/src/app/pages/features/features-page.html - 242 + apps/client/src/app/pages/pricing/pricing-page.html + 26 - - Open Source Software - Açık Kaynak Yazılım + + Unlimited Transactions + Sınırsız İşlem - apps/client/src/app/pages/features/features-page.html - 278 + apps/client/src/app/pages/pricing/pricing-page.html + 32 - - - Get Started - Başla - apps/client/src/app/pages/features/features-page.html - 303 + apps/client/src/app/pages/pricing/pricing-page.html + 121 - apps/client/src/app/pages/public/public-page.html - 220 + apps/client/src/app/pages/pricing/pricing-page.html + 193 - - Holdings - Varlıklar - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - + + Unlimited Accounts + Kısıtsız Hesaplar - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + apps/client/src/app/pages/pricing/pricing-page.html + 36 - apps/client/src/app/pages/home/home-page.component.ts - 42 + apps/client/src/app/pages/pricing/pricing-page.html + 125 - apps/client/src/app/pages/zen/zen-page.component.ts - 39 + apps/client/src/app/pages/pricing/pricing-page.html + 197 - - Summary - Özet + + Portfolio Performance + Portföy Performansı - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/pages/pricing/pricing-page.html + 40 - apps/client/src/app/pages/home/home-page.component.ts - 47 + apps/client/src/app/pages/pricing/pricing-page.html + 129 - - - Markets - Piyasalar - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/pages/pricing/pricing-page.html + 201 + + + Data Import and Export + Veri İçe Aktarma ve Dışa Aktarma - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/pages/pricing/pricing-page.html + 60 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 133 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/pages/pricing/pricing-page.html + 221 + + + Community Support + Topluluk Desteği - apps/client/src/app/pages/resources/resources-page.component.ts - 26 + apps/client/src/app/pages/pricing/pricing-page.html + 77 - - Manage your wealth like a boss - Varlıklarınızı bir patron gibi yönetin + + Self-hosted, update manually. + Tarafınızca barındırılıyor, elle güncelleyiniz. - apps/client/src/app/pages/landing/landing-page.html - 5 + apps/client/src/app/pages/pricing/pricing-page.html + 81 - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio, mali durumunuz için gizlilik odaklı, açık kaynaklı bir kontrol panelidir. Varlık dağılımınızı analiz edin, net değerinizi öğrenin ve sağlam, veriye dayalı yatırım kararları alın. + + Free + Ücretsiz - apps/client/src/app/pages/landing/landing-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 83 - - - Get Started - Başla - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/pages/pricing/pricing-page.html + 146 + + + For new investors who are just getting started with trading. + Alım satıma henüz başlamış yeni yatırımcılar için. apps/client/src/app/pages/pricing/pricing-page.html - 324 + 116 - - Live Demo - Canlı Deneme + + Fully managed Ghostfolio cloud offering. + Eksiksiz yönetilen Ghostfolio bulut teklifi. - apps/client/src/app/pages/landing/landing-page.html - 49 + apps/client/src/app/pages/pricing/pricing-page.html + 144 - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/pricing/pricing-page.html + 270 - - Monthly Active Users - Aylık Aktif Kullanıcılar + + For ambitious investors who need the full picture of their financial assets. + Finansal varlıklarının tamamını görmeye ihtiyaç duyan hırslı yatırımcılar için. - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/pricing/pricing-page.html + 187 - - Stars on GitHub - GitHub’daki Beğeniler + + Email and Chat Support + E-posta ve Sohbet Desteği - apps/client/src/app/pages/landing/landing-page.html - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 266 + + + Renew Plan + Aboneliği Yenile - apps/client/src/app/pages/open/open-page.html - 103 + apps/client/src/app/components/header/header.component.html + 191 - - - Pulls on Docker Hub - Docker Hub’ta Çekmeler - apps/client/src/app/pages/landing/landing-page.html - 106 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 18 - apps/client/src/app/pages/open/open-page.html - 117 + apps/client/src/app/pages/pricing/pricing-page.html + 297 - - As seen in - Şurada görüldüğü gibi + + One-time payment, no auto-renewal. + Tek seferlik ödeme, otomatik yenileme yok. - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/pages/pricing/pricing-page.html + 303 - - Protect your assets. Refine your personal investment strategy. - varlıklarınızı koruyun. Kişisel yatırım stratejinizi geliştirin. + + It’s free. + Ücretsiz. - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/pricing/pricing-page.html + 353 - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio, takip edilmeden hisse senetleri, ETF’ler veya kripto paraları izlemek isteyen yoğun insanlara güç verir. + + Hello, has shared a Portfolio with you! + Merhaba, size bir Portföy paylaştı! - apps/client/src/app/pages/landing/landing-page.html - 229 + apps/client/src/app/pages/public/public-page.html + 5 - - 360° View - 360° Görünüm + + Continents + Kıtalar - apps/client/src/app/pages/landing/landing-page.html - 240 + apps/client/src/app/pages/public/public-page.html + 124 - - Get the full picture of your personal finances across multiple platforms. - Kişisel finansınızın tam resmini birden fazla platformda edinin. + + Ghostfolio empowers you to keep track of your wealth. + Ghostfolio, varlıklarınızı takip etmenizi sağlar. - apps/client/src/app/pages/landing/landing-page.html - 242 + apps/client/src/app/pages/public/public-page.html + 216 - - Web3 Ready - Web3 Hazır + + Registration + Kayıt - apps/client/src/app/pages/landing/landing-page.html - 251 + apps/client/src/app/components/admin-users/admin-users.html + 98 - - - Use Ghostfolio anonymously and own your financial data. - Ghostfolio’yu anonim olarak kullanın ve finansal verilerinize sahip çıkın. - apps/client/src/app/pages/landing/landing-page.html - 253 + libs/common/src/lib/routes/routes.ts + 281 - - Open Source - Açık Kaynak + + Create Account + Hesap Oluştur - apps/client/src/app/pages/landing/landing-page.html - 261 + apps/client/src/app/app.component.html + 13 - - - Benefit from continuous improvements through a strong community. - Güçlü bir topluluk aracılığıyla sürekli gelişmelerden faydalanın. - apps/client/src/app/pages/landing/landing-page.html - 263 + apps/client/src/app/pages/register/register-page.html + 27 - - - Why Ghostfolio? - Neden Ghostfolio? - apps/client/src/app/pages/landing/landing-page.html - 272 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 2 - - - Ghostfolio is for you if you are... - Ghostfolio tam size göre, - apps/client/src/app/pages/landing/landing-page.html - 273 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 - - trading stocks, ETFs or cryptocurrencies on multiple platforms - Birden fazla platformda hisse senedi, ETF veya kripto para ticareti yapıyorsanız, + + Continue with Internet Identity + İnternet Kimliği ile Devam Et - apps/client/src/app/pages/landing/landing-page.html - 280 + apps/client/src/app/pages/register/register-page.html + 42 - - pursuing a buy & hold strategy - al ve tut stratejisi izliyorsanız, + + Continue with Google + Google ile Devam Et - apps/client/src/app/pages/landing/landing-page.html - 286 + apps/client/src/app/pages/register/register-page.html + 53 - - interested in getting insights of your portfolio composition - Portföy bileşimine dair içgörüleri edinmek istiyorsanız, + + Copy to clipboard + Panoya Kopyala - apps/client/src/app/pages/landing/landing-page.html - 291 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 - - valuing privacy and data ownership - Gizliliğe ve verilerinize sahip çıkmayı önemsiyorsanız + + Personal Finance Tools + Kişisel Finans Araçları - apps/client/src/app/pages/landing/landing-page.html - 296 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 - - - into minimalism - minimalizme ilgi duyuyorsanız - apps/client/src/app/pages/landing/landing-page.html - 299 + libs/common/src/lib/routes/routes.ts + 329 - - caring about diversifying your financial resources - finansal kaynaklarınızı çeşitlendirmeye önem veriyorsanız + + open-source-alternative-to + acik-kaynak-alternatif + kebab-case - apps/client/src/app/pages/landing/landing-page.html - 303 + libs/common/src/lib/routes/routes.ts + 320 - - - interested in financial independence - finansal özgürlük peşindeyseniz - apps/client/src/app/pages/landing/landing-page.html - 307 + libs/common/src/lib/routes/routes.ts + 324 - - saying no to spreadsheets in - elektronik tablo uygulamalarına hayır diyorsanız + + Discover Open Source Alternatives for Personal Finance Tools + Açık Kaynak Kişisel Finans Seçeneklerini Keşfet - apps/client/src/app/pages/landing/landing-page.html - 311 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 - - still reading this list - bu listeyi hala okuyorsanız + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Bu genel bakış sayfası, diğer kişisel finans araçlarının seçilmiş bir koleksiyonunun açık kaynak alternatifiGhostfolio ile karşılaştırmasını sunmaktadır.. Şeffaflığa, veri gizliliğine ve topluluk işbirliğine değer veriyorsanız Ghostfolio, finansal yönetiminizin kontrolünü ele almak için mükemmel Şeffaflığa, veri gizliliğine ve topluluk işbirliğine değer veriyorsanız Ghostfolio, finansal yönetiminizin kontrolünü ele almak için mükemmel bir fırsat sunuyor. - apps/client/src/app/pages/landing/landing-page.html - 314 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 - - Learn more about Ghostfolio - Ghostfolio hakkında daha fazla bilgi edinin + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Aşağıdaki bağlantıları keşfedin, çeşitli kişisel finans araçlarını Ghostfolio ile karşılaştırın. - apps/client/src/app/pages/landing/landing-page.html - 319 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 - - What our users are saying - What our users are saying + + Open Source Alternative to + için Açık Kaynak Alternatifi - apps/client/src/app/pages/landing/landing-page.html - 327 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 - - Members from around the globe are using Ghostfolio Premium - Dünyanın dört bir yanındaki kullanıcılar Ghostfolio Premium kullanıyorlar. + + The Open Source Alternative to + Açık Kaynak Alternatifi - apps/client/src/app/pages/landing/landing-page.html - 366 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 - - How does Ghostfolio work? - How does Ghostfolio work? + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Açık kaynaklı bir alternatif mi arıyorsunuz ? Ghostfolio güçlü bir portföy yönetim aracıdır ve bireylere yatırımlarını takip etmek, analiz etmek ve optimize etmek için kapsamlı bir platform sunar. İster deneyimli bir yatırımcı olun ister yeni başlıyor olun, Ghostfolio, bilinçli kararlar almanıza ve finansal geleceğinizi kontrol etmenize yardımcı olmak için sezgisel bir kullanıcı arayüzü ve geniş bir işlevsellik yelpazesi sunmaktadır. - apps/client/src/app/pages/landing/landing-page.html - 383 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 - - Get started in only 3 steps - Sadece 3 adımda başlayın + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio, karşısında açık kaynak kodlu maliyet etkin bir seçenek sunmaktadır. gibi kısıtlı bütçeye sahip, finansal özgürlük ve erken emeklilik (FIRE) amaçlayan kulanıcılar için özellikle uygundur. Ghostfolio, topluluk içindeki geliştiricilerin ve kişisel finans meraklılarının kolektif çabası sayesinde yeteneklerini, güvenliğini ve kullanıcı deneyimini sürekli olarak geliştirmektedir. - apps/client/src/app/pages/landing/landing-page.html - 386 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 - - Sign up anonymously* - Anonim olarak kaydolun* + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Ghostfolio ve arasındaki ayrıntılı karşılaştırmanın yer aldığı aşağıdaki tabloya daha yakından bakarak Ghostfolio’nun karşısında kendisini nasıl konumlandırdığını kapsamlı bir şekilde değerlendirelim. Bu kapsamda özellikler, veri güvenliği, fiyat vb. hususları inceleyerek kişisel gereksinimleriniz için bilgiye dayalı bir seçim yapmanızı sağlayabileceği. - apps/client/src/app/pages/landing/landing-page.html - 392 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - * no e-mail address nor credit card required - * e-posta adresi veya kredi kartı gerekmez + + Founded + Kuruluş - apps/client/src/app/pages/landing/landing-page.html - 394 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 - - Add any of your historical transactions - Herhangi bir geçmiş işleminizi ekleyin + + Origin + Köken - apps/client/src/app/pages/landing/landing-page.html - 405 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 - - Get valuable insights of your portfolio composition - Portföy bileşiminizle ilgili değerli bilgiler edinin + + Region + Bölge - apps/client/src/app/pages/landing/landing-page.html - 417 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 - - Are you ready? - Are you ready? + + Available in + Mevcut - apps/client/src/app/pages/landing/landing-page.html - 431 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 - - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - Ghostfolio’da şeffaflık, değerlerimizin temelinde yer alır. Kaynak kodunu açık kaynak yazılım (OSS) olarak AGPL-3.0 lisansı altında yayınlıyoruz ve platformun işletme durumunun toplu anahtar metriklerini açıkça paylaşıyoruz. + + ✅ Yes + ✅ Evet - apps/client/src/app/pages/open/open-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 - - - Active Users - Aktif Kullanıcılar - apps/client/src/app/pages/open/open-page.html - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 - apps/client/src/app/pages/open/open-page.html - 62 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 - - - New Users - Yeni Kullanıcılar - apps/client/src/app/pages/open/open-page.html - 51 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 - - - Users in Slack community - Slack topluluğundaki kullanıcılar - apps/client/src/app/pages/open/open-page.html - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 - - - Contributors on GitHub - GitHub’da Katkıda Bulunanlar - apps/client/src/app/pages/open/open-page.html - 89 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 - - - Uptime - Çalışma Süresi - apps/client/src/app/pages/open/open-page.html - 132 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 - - Activities - İşlemler + + ❌ No + ❌ Hayır - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 - - - Do you really want to delete these activities? - Tüm işlemlerinizi silmeyi gerçekten istiyor musunuz? - libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 - - - Update activity - İşlemi Güncelle - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 - - - Stocks, ETFs, bonds, cryptocurrencies, commodities - Hisse senetleri, ETF’ler, tahviller, kripto paralar, emtialar - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 65 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 - - - Mortgages, personal loans, credit cards - Mortgage, kişisel krediler, kredi kartları - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 57 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 - - - Luxury items, real estate, private companies - Lüks eşyalar, gayrimenkuller, özel şirketler - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 73 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 - - Account - Hesap + + Self-Hosting + Tarafınızca Barındırma - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 + + + Use anonymously + Anonim olarak kullan - libs/ui/src/lib/activities-table/activities-table.component.html - 308 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 210 + + + Free Plan + Ücretsiz Plan - libs/ui/src/lib/assistant/assistant.html - 107 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 - - Update Cash Balance - Nakit Bakiyesini Güncelle + + Notes + Notlar - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 112 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 - - Unit Price - Birim Fiyat + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Lütfen dikkat, Ghostfolio ve arasındaki karşılaştırmanın yer aldığı tablodaki bilgiler bağımsız araştırmalarımıza dayanmaktadır. Websitemizin ile ya da bu karşılaştırmada adı geçen herhangi bir ürün ve hizmet ile ilişkisi bulunmamaktadır. Kişisel finans araçlarının kapsamı geliştikçe, belirli ayrıntıların veya değişikliklerin doğrudan ilgili ürün sayfasından doğrulanması önemlidir. Verilerin yenilenmesi mi gerekiyor? Doğru verileri sağlamamıza yardımcı olmak için sayfamızı ziyaret edin. GitHub. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 + + + Ready to take your investments to the next level? + Yatırımlarınızı bir sonraki seviyeye taşımaya hazır mısınız? - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + Ghostfolio ile varlıklarınızı kolaylıkla takip edin, analiz edin ve görselleştirin. - libs/ui/src/lib/activities-table/activities-table.component.html - 210 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 - - Oops! Could not get the historical exchange rate from - Hay Allah! Geçmiş döviz kuru alınamadı: + + Switzerland + İsviçre - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - - - Fee - Komisyon - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 + libs/ui/src/lib/i18n.ts + 96 + + + Global + Küresel - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - libs/ui/src/lib/activities-table/activities-table.component.html - 234 + libs/ui/src/lib/i18n.ts + 16 - - Import Activities - İşlemleri İçe Aktar + + Resources + Kaynaklar - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + apps/client/src/app/app.component.html + 64 - - - Import Dividends - Temettüleri İçe Aktar - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + apps/client/src/app/components/header/header.component.html + 88 - - - Importing data... - Veri içe aktarılıyor... - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + apps/client/src/app/components/header/header.component.html + 301 - - - Import has been completed - İçe aktarma tamamlandı - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 - - - Validating data... - Veri doğrulanıyor... - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + libs/common/src/lib/routes/routes.ts + 332 - - Select Holding - Varlık Seç + + Grant access + Erişim izni ver - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 20 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 7 - - Select File - Dosya Seç + + Public + Halka açık - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 22 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 25 - - Holding - Varlık + + My Ghostfolio + Benim Ghostfolio’m - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 32 + apps/client/src/app/components/header/header.component.html + 277 - libs/ui/src/lib/assistant/assistant.html - 127 + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 - - Load Dividends - Temettü Yükle + + Auto + Otomatik - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 68 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 - - - The following file formats are supported: - Aşağıdaki dosya formatları desteklenmektedir: - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 90 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 - - Select Dividends - Temettü Seç + + Please enter your coupon code. + Lütfen kupon kodunuzu girin: - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 113 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 - - Select Activities - İşlemleri Seç + + Could not redeem coupon code + Kupon kodu kullanılamadı - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 115 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 - - Back - Geri + + Coupon code has been redeemed + Kupon kodu kullanıldı - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 144 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 + + + Reload + Yeniden Yükle - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 178 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 - - Import - İçe Aktar + + Do you really want to remove this sign in method? + Bu giriş yöntemini kaldırmayı gerçekten istiyor musunuz? - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 153 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 + + + Valid until + Geçerli tarih - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 186 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 70 + libs/ui/src/lib/membership-card/membership-card.component.html + 42 - - Allocations - Dağılımlar + + per year + yıllık - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + apps/client/src/app/pages/pricing/pricing-page.html + 283 - - Allocations - Dağılımlar + + Try Premium + Premium’u Deneyin - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 - - Proportion of Net Worth - Net Değer Oranı + + Redeem Coupon + Kupon Kullan - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 12 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 - - By Platform - Platforma Göre + + Presenter View + Sunum Görünümü - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 44 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 - - By Currency - Para Birimine Göre + + Protection for sensitive information like absolute performances and quantity values + Gerçek performans ve miktar değerleri gibi hassas bilgilerin saklanması için - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 63 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 - - By Asset Class - Varlık Sınıfına Göre + + Base Currency + Temel Para Birimi - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 85 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 - - By Holding - Varlığa Göre + + Language + Dil - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 107 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 - - By Sector - Sektöre Göre + + Locale + Yerel Ayarlar - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 130 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 - - - By Continent - Kıtaya Göre - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 153 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 - - By Market - Piyasaya Göre + + Date and number format + Tarih ve Sayı Formatları - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 175 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 - - Regions - Bölgeler + + Appearance + Görünüm - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 198 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 + + + Light + Açık - apps/client/src/app/pages/public/public-page.html - 143 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 - - Developed Markets - Gelişmiş Piyasalar + + Dark + Koyu - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 222 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 + + + Distraction-free experience for turbulent times + Çalkantılı zamanlar için dikkat dağıtmayan bir deneyim - apps/client/src/app/pages/public/public-page.html - 160 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 - - Emerging Markets - Gelişmekte Olan Piyasalar + + Biometric Authentication + Biyometrik Kimlik Doğrulama - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 231 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 + + + Sign in with fingerprint + Parmak iziyle oturum aç - apps/client/src/app/pages/public/public-page.html - 169 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 - - Other Markets - Diğer Piyasalar + + Experimental Features + Deneysel Özellikler - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 240 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 + + + Sneak peek at upcoming functionality + Gelecek özelliklere göz atın - apps/client/src/app/pages/public/public-page.html - 178 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 - - No data available - Veri mevcut değil + + User ID + Kullanıcı Kimliği - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 - apps/client/src/app/pages/public/public-page.html - 188 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 + + + Export Data + Verileri Dışa Aktar - libs/ui/src/lib/benchmark/benchmark.component.html - 137 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 + + + Granted Access + xErişim İzni Verildi - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + apps/client/src/app/components/user-account-access/user-account-access.html + 57 - - By Account - Hesaba Göre + + Oops, authentication has failed. + Hay Allah, kimlik doğrulaması başarısız oldu. - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 286 + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 - - By ETF Provider - ETF Sağlayıcısına Göre + + Try again + Yeniden dene - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 306 + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 - - By Country - Ülkeye Göre + + Go back to Home Page + Ana Sayfaya Geri Dön - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 264 + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 - - Analysis - Analiz + + Export Activities + İşlemleri Dışa Aktar - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + libs/ui/src/lib/activities-table/activities-table.component.html + 41 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/ui/src/lib/activities-table/activities-table.component.html + 396 - - Dividend - Temettü + + Export Drafts as ICS + Taslakları ICS Olarak Dışa Aktar - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + libs/ui/src/lib/activities-table/activities-table.component.html + 54 - libs/ui/src/lib/i18n.ts - 36 + libs/ui/src/lib/activities-table/activities-table.component.html + 409 - - Deposit - Para Yatırma + + Draft + Taslak - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + libs/ui/src/lib/activities-table/activities-table.component.html + 145 - - Monthly - Aylık + + Clone + Klonla - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + libs/ui/src/lib/activities-table/activities-table.component.html + 436 - - Yearly - Yıllık + + Export Draft as ICS + Taslakları ICS Olarak Dışa Aktar - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + libs/ui/src/lib/activities-table/activities-table.component.html + 446 - - Analysis - Analiz + + Do you really want to delete this activity? + TBu işlemi silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 - - Top - Üst + + Change from All Time High + Tüm Zamanların En Yüksek Seviyesinden (ATH) Değişim - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + libs/ui/src/lib/benchmark/benchmark.component.html + 110 - - Bottom - Alt + + from ATH + Tüm Zamanların En Yüksek Seviyesinden - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + libs/ui/src/lib/benchmark/benchmark.component.html + 112 - - Portfolio Evolution - Portföyün Gelişimi + + Market data provided by + Piyasa verileri tarafından sağlanmıştır - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 - - Investment Timeline - Yatırım Zaman Çizelgesi + + Savings Rate per Month + Aylık Tasarruf Oranı - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 - - Current Streak - Güncel Seri + + Annual Interest Rate + Yıllık Faiz Oranı - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 - - Longest Streak - En Uzun Seri + + Retirement Date + Emeklilik Tarihi - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 - - Dividend Timeline - Temettü Zaman Çizelgesi + + Projected Total Amount + Hesaplanan Toplam Tutar - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 - - FIRE - Finansal Özgürlük ve Erken Emeklilik (FIRE) + + Interest + Faiz - apps/client/src/app/pages/portfolio/fire/fire-page.html - 4 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 + + + libs/ui/src/lib/i18n.ts + 38 - - Calculator - Hesap Makinesi + + Savings + Tasarruflar - apps/client/src/app/pages/portfolio/fire/fire-page.html - 7 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 - - 4% Rule - %4 Kuralı + + Allocation + Dağılım - apps/client/src/app/pages/portfolio/fire/fire-page.html + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html 40 + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 + - - Holdings - Varlıklar + + Show all + Tümünü göster - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 + + + Account + Hesap - apps/client/src/app/components/home-holdings/home-holdings.html + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + + + libs/ui/src/lib/i18n.ts 4 + + + Asia-Pacific + Asya Pasifik - apps/client/src/app/pages/public/public-page.html - 70 + libs/ui/src/lib/i18n.ts + 5 + + + + Asset Class + Varlık Sınıfı + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 libs/ui/src/lib/assistant/assistant.html - 46 + 218 + + + libs/ui/src/lib/i18n.ts + 6 - - Pricing - Fiyatlandırma + + Asset Sub Class + AVarlık Alt Sınıfı - apps/client/src/app/pages/pricing/pricing-page-routing.module.ts + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + + + libs/ui/src/lib/i18n.ts + 7 + + + + Core + Temel + + libs/ui/src/lib/i18n.ts + 10 + + + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily + Ghostfolio Premium veya Ghostfolio Open Source’a kolayca geçin + + libs/ui/src/lib/i18n.ts + 12 + + + + Switch to Ghostfolio Premium easily + Ghostfolio Premium’a kolayca geçin + + libs/ui/src/lib/i18n.ts 13 - - Pricing Plans - Fiyatlandırma Planları + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily + Ghostfolio Açık Kaynak veya Ghostfolio Temel’e kolayca geçin. - apps/client/src/app/pages/pricing/pricing-page.html - 4 + libs/ui/src/lib/i18n.ts + 14 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - Resmi Ghostfolio Premium bulut teklifimiz bir başlangıç yapmanın en kolay yoludur. Zaman tasarrufu sağladığı için çoğu insan için en iyi seçenek olacaktır. Gelir, barındırma altyapısının maliyetlerini karşılamak ve süregiden geliştirme işlerini finanse etmek için kullanılmaktadır. + + Emergency Fund + Acil Durum Fonu - apps/client/src/app/pages/pricing/pricing-page.html - 6 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + + + libs/ui/src/lib/i18n.ts + 15 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - Ghostfolio’yu kendi altyapınızda çalıştırmayı tercih ederseniz, lütfen kaynak kodunu ve daha fazla talimatı GitHub adresinde bulun. + + Grant + Hibe - apps/client/src/app/pages/pricing/pricing-page.html + libs/ui/src/lib/i18n.ts + 17 + + + + Higher Risk + Daha Yüksek Risk + + libs/ui/src/lib/i18n.ts + 18 + + + + This activity already exists. + Bu işlem zaten mevcut. + + libs/ui/src/lib/i18n.ts + 19 + + + + Japan + Japonya + + libs/ui/src/lib/i18n.ts + 89 + + + + Lower Risk + Daha Düşük Risk + + libs/ui/src/lib/i18n.ts + 20 + + + + Month + Ay + + libs/ui/src/lib/i18n.ts + 21 + + + + Months + Ay + + libs/ui/src/lib/i18n.ts + 22 + + + + Other + Diğer + + libs/ui/src/lib/i18n.ts + 23 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 + + + + Preset + Önceden Ayarlanmış + + libs/ui/src/lib/i18n.ts + 25 + + + + Retirement Provision + Yaşlılık Provizyonu + + libs/ui/src/lib/i18n.ts 26 - - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - Kendi altyapılarında Ghostfolio’yu çalıştırmayı tercih eden teknolojiye hakim yatırımcılar için. + + Satellite + Uydu - apps/client/src/app/pages/pricing/pricing-page.html - 38 + libs/ui/src/lib/i18n.ts + 27 - - Unlimited Transactions - Sınırsız İşlem + + Symbol + Sembol - apps/client/src/app/pages/pricing/pricing-page.html - 45 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 - apps/client/src/app/pages/pricing/pricing-page.html - 134 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 - apps/client/src/app/pages/pricing/pricing-page.html - 201 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + + + libs/ui/src/lib/i18n.ts + 28 - - Unlimited Accounts - Kısıtsız Hesaplar + + Tag + Etiket - apps/client/src/app/pages/pricing/pricing-page.html - 49 + libs/ui/src/lib/assistant/assistant.html + 207 - apps/client/src/app/pages/pricing/pricing-page.html - 138 + libs/ui/src/lib/i18n.ts + 29 + + + Year + Yıl - apps/client/src/app/pages/pricing/pricing-page.html - 205 + libs/ui/src/lib/i18n.ts + 30 - - Portfolio Performance - Portföy Performansı + + Years + Yıl - apps/client/src/app/pages/pricing/pricing-page.html + libs/ui/src/lib/i18n.ts + 31 + + + + Buy + Al + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + + + libs/ui/src/lib/i18n.ts + 35 + + + + Valuable + Kıymet + + libs/ui/src/lib/i18n.ts + 39 + + + + Liability + Yükümlülük + + libs/ui/src/lib/i18n.ts + 40 + + + + Sell + Sat + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + + + libs/ui/src/lib/i18n.ts + 41 + + + + Cash + Nakit + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + + + libs/ui/src/lib/i18n.ts 53 + + + Commodity + Emtia - apps/client/src/app/pages/pricing/pricing-page.html - 142 + libs/ui/src/lib/i18n.ts + 45 + + + Equity + Menkul Kıymet - apps/client/src/app/pages/pricing/pricing-page.html - 209 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + + + libs/ui/src/lib/i18n.ts + 46 - - Data Import and Export - Veri İçe Aktarma ve Dışa Aktarma + + Fixed Income + Sabit Gelir - apps/client/src/app/pages/pricing/pricing-page.html - 73 + libs/ui/src/lib/i18n.ts + 47 + + + + Real Estate + Gayrimenkul + + libs/ui/src/lib/i18n.ts + 49 + + + Bond + Bono - apps/client/src/app/pages/pricing/pricing-page.html - 146 + libs/ui/src/lib/i18n.ts + 52 + + + + Cryptocurrency + Kriptopara + + libs/ui/src/lib/i18n.ts + 55 + + + + ETF + Borsada İşlem Gören Fonlar (ETF) + + libs/ui/src/lib/i18n.ts + 56 + + + Mutual Fund + Borsada İşlem Görmeyen Fonlar (Mutual Fund) - apps/client/src/app/pages/pricing/pricing-page.html - 229 + libs/ui/src/lib/i18n.ts + 57 - - Community Support - Topluluk Desteği + + Precious Metal + Kıymetli Metaller - apps/client/src/app/pages/pricing/pricing-page.html - 90 + libs/ui/src/lib/i18n.ts + 58 - - Self-hosted, update manually. - Tarafınızca barındırılıyor, elle güncelleyiniz. + + Private Equity + Özel Menkul Kıymetler - apps/client/src/app/pages/pricing/pricing-page.html - 94 + libs/ui/src/lib/i18n.ts + 59 - - Free - Ücretsiz + + Stock + Hisse Senetleri - apps/client/src/app/pages/pricing/pricing-page.html - 95 + libs/ui/src/lib/i18n.ts + 60 + + + Africa + Afrika - apps/client/src/app/pages/pricing/pricing-page.html - 158 + libs/ui/src/lib/i18n.ts + 67 - - For new investors who are just getting started with trading. - Alım satıma henüz başlamış yeni yatırımcılar için. + + Asia + Asya - apps/client/src/app/pages/pricing/pricing-page.html - 128 + libs/ui/src/lib/i18n.ts + 68 - - Fully managed Ghostfolio cloud offering. - Eksiksiz yönetilen Ghostfolio bulut teklifi. + + Europe + Avrupa - apps/client/src/app/pages/pricing/pricing-page.html - 157 + libs/ui/src/lib/i18n.ts + 69 + + + North America + Kuzey Amerika - apps/client/src/app/pages/pricing/pricing-page.html - 261 + libs/ui/src/lib/i18n.ts + 70 - - For ambitious investors who need the full picture of their financial assets. - Finansal varlıklarının tamamını görmeye ihtiyaç duyan hırslı yatırımcılar için. + + Oceania + Okyanusya - apps/client/src/app/pages/pricing/pricing-page.html - 194 + libs/ui/src/lib/i18n.ts + 71 - - Email and Chat Support - E-posta ve Sohbet Desteği + + South America + Güney Amerika - apps/client/src/app/pages/pricing/pricing-page.html - 257 + libs/ui/src/lib/i18n.ts + 72 - - Renew Plan - Aboneliği Yenile + + Time to add your first activity. + İlk işleminizi girmanin tam zamanı. - apps/client/src/app/components/header/header.component.html - 191 + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 + + + No data available + Veri mevcut değil - apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 - apps/client/src/app/pages/pricing/pricing-page.html - 294 + apps/client/src/app/pages/public/public-page.html + 188 - - - One-time payment, no auto-renewal. - Tek seferlik ödeme, otomatik yenileme yok. - apps/client/src/app/pages/pricing/pricing-page.html - 298 + libs/ui/src/lib/benchmark/benchmark.component.html + 202 - - - Get Started - Başla - apps/client/src/app/pages/landing/landing-page.html - 446 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 - - - It’s free. - Ücretsiz. - apps/client/src/app/pages/pricing/pricing-page.html - 327 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 - - - Hello, has shared a Portfolio with you! - Merhaba, size bir Portföy paylaştı! - apps/client/src/app/pages/public/public-page.html - 4 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - - Currencies - Para birimleri + + You are using the Live Demo. + Canlı demoyu kullanmaktasınız. - apps/client/src/app/pages/public/public-page.html - 88 + apps/client/src/app/app.component.html + 12 - - Continents - Kıtalar + + (Last 24 hours) + (Son 24 saat) - apps/client/src/app/pages/public/public-page.html - 124 + apps/client/src/app/pages/open/open-page.html + 37 - - Ghostfolio empowers you to keep track of your wealth. - Ghostfolio, varlıklarınızı takip etmenizi sağlar. + + (Last 30 days) + (Son 30 gün) - apps/client/src/app/pages/public/public-page.html - 215 + apps/client/src/app/pages/open/open-page.html + 48 - - - Registration - Kayıt - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/pages/open/open-page.html + 59 - - Create Account - Hesap Oluştur + + (Last 90 days) + (Son 90 gün) - apps/client/src/app/app.component.html - 13 + apps/client/src/app/pages/open/open-page.html + 127 + + + One-time fee, annual account fees + Tek seferlik ücret, yıllık hesap ücreti - apps/client/src/app/pages/register/register-page.html - 27 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 + + + Distribution of corporate earnings + Şirket gelirinin dağıtımı - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 2 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 - - Continue with Internet Identity - İnternet Kimliği ile Devam Et + + Revenue for lending out money + Borç verme getirisi - apps/client/src/app/pages/register/register-page.html - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 - - Continue with Google - Google ile Devam Et + + Choose or drop a file here + Dosya seçin ya da sürükleyin - apps/client/src/app/pages/register/register-page.html - 53 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 - - Copy to clipboard - Panoya Kopyala + + Fee + Ücret - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 - - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + libs/ui/src/lib/activities-table/activities-table.component.html + 234 - - - Agree and continue - Kabul et ve devam et - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + libs/ui/src/lib/i18n.ts + 37 - - Personal Finance Tools - Kişisel Finans Araçları + + Add Tag + Etiket Ekleyiniz - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 - - open-source-alternative-to - Açık kaynak alternatif + + Do you really want to delete this tag? + Bu etiketi silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + Etiketi güncelle - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 - - Open Source Alternative to - için Açık Kaynak Alternatif + + Add tag + Etiket ekle - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 - - Discover Open Source Alternatives for Personal Finance Tools - Açık Kaynak Kişisel Finans Seçeneklerini Keşfet + + Currency Cluster Risks + Kur Kümelenme Riskleri (Currency Cluster Risks) - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - Bu genel bakış sayfası, diğer kişisel finans araçlarının seçilmiş bir koleksiyonunun açık kaynak alternatifiGhostfolio ile karşılaştırmasını sunmaktadır.. Şeffaflığa, veri gizliliğine ve topluluk işbirliğine değer veriyorsanız Ghostfolio, finansal yönetiminizin kontrolünü ele almak için mükemmel Şeffaflığa, veri gizliliğine ve topluluk işbirliğine değer veriyorsanız Ghostfolio, finansal yönetiminizin kontrolünü ele almak için mükemmel bir fırsat sunuyor. + + Account Cluster Risks + Hesap Kümelenme Riski (Account Cluster Risks) - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - Aşağıdaki bağlantıları keşfedin, çeşitli kişisel finans araçlarını Ghostfolio ile karşılaştırın. + + Transfer Cash Balance + Nakit Bakiyesini Transfer Et - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - - - Open Source Alternative to - Open Source Alternative to - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 - - The Open Source Alternative to - Açık Kaynak Alternatifi + + Version + Versiyon - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + + From + Başlangıç - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio, karşısında açık kaynak kodlu maliyet etkin bir seçenek sunmaktadır. gibi kısıtlı bütçeye sahip, finansal özgürlük ve erken emeklilik (FIRE) amaçlayan kulanıcılar için özellikle uygundur. Ghostfolio, topluluk içindeki geliştiricilerin ve kişisel finans meraklılarının kolektif çabası sayesinde yeteneklerini, güvenliğini ve kullanıcı deneyimini sürekli olarak geliştirmektedir. + + To + Bitiş - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html 32 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - Ghostfolio ve arasındaki ayrıntılı karşılaştırmanın yer aldığı aşağıdaki tabloya daha yakından bakarak Ghostfolio’nun karşısında kendisini nasıl konumlandırdığını kapsamlı bir şekilde değerlendirelim. Bu kapsamda özellikler, veri güvenliği, fiyat vb. hususları inceleyerek kişisel gereksinimleriniz için bilgiye dayalı bir seçim yapmanızı sağlayabileceği. + + Transfer + Transfer - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Founded - Kuruluş + + Membership + Üyelik - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 77 + libs/common/src/lib/routes/routes.ts + 31 - - - Origin - Köken - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 82 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 - - Region - Bölge + + Access + Erişim - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 87 + libs/common/src/lib/routes/routes.ts + 26 - - Available in - Mevcut + + Asset Profile + Varlık Profili - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 - - ✅ Yes - ✅ Evet + + Do you really want to delete this asset profile? + Bu varlık profilini silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 140 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Search + Arama - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 157 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 + + + Add Manually + Elle Giriş - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 179 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio, hisse senetleri, ETF’ler veya kriptopara birimleri gibi varlıklarınızı birden fazla platformda takip etmenizi sağlayan bir kişisel finans kontrol panelidir. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 196 + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + Last All Time High + Son, ATH - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 218 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 + + + User + Kullanıcı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 235 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + Ghostfolio vs comparison table + Ghostfolio ve karşılatırma tablosu apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 257 + 55 + + + Open Source Wealth Management Software + Açık Kaynak Varlık Yönetim Yazılımı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 274 + apps/client/src/app/pages/i18n/i18n-page.html + 224 - - ❌ No - ❌ Hayır + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + app, varlık, kriptopara, kontrol paneli, etf, finans, yönetim, performans, portföy, yazılım, hisse, alım satım, varlık, web3 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 147 + apps/client/src/app/pages/i18n/i18n-page.html + 10 + + + Oops, cash balance transfer has failed. + Hay Allah, Nakit bakiyesi tranferi başarısız oldu. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 164 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Extreme Fear + Aşırı Korku - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 186 + libs/ui/src/lib/i18n.ts + 103 + + + Extreme Greed + Aşırı Açgözlülük - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 203 + libs/ui/src/lib/i18n.ts + 104 + + + Neutral + Nötr - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 225 + libs/ui/src/lib/i18n.ts + 107 + + + Oops! Could not parse historical data. + Hay Allah! Geçmiş veriler ayrıştırılamadı. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 242 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Do you really want to delete this system message? + Bu sistem mesajını silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 264 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + 50-Day Trend + 50 Günlük Trend - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 281 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 - - Self-Hosting - Tarafınızca Barındırma + + 200-Day Trend + 200 Günlük Trend - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 - - Use anonymously - Anonim olarak kullan + + Cash Balances + Nakit Bakiyeleri - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 - - Free Plan - Ücretsiz Plan + + Starting from + Başlangıç apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + 289 - - - Notes - Notlar apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 302 + 294 - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - Lütfen dikkat, Ghostfolio ve arasındaki karşılaştırmanın yer aldığı tablodaki bilgiler bağımsız araştırmalarımıza dayanmaktadır. Websitemizin ile ya da bu karşılaştırmada adı geçen herhangi bir ürün ve hizmet ile ilişkisi bulunmamaktadır. Kişisel finans araçlarının kapsamı geliştikçe, belirli ayrıntıların veya değişikliklerin doğrudan ilgili ürün sayfasından doğrulanması önemlidir. Verilerin yenilenmesi mi gerekiyor? Doğru verileri sağlamamıza yardımcı olmak için sayfamızı ziyaret edin. GitHub. + + Do you really want to delete this account balance? + Bu nakit bakiyesini silmeyi gerçekten istiyor musunuz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - Ready to take your investments to the next level? - Ready to take your investments to the next level? + + If a translation is missing, kindly support us in extending it here. + Eğer bir çeviri eksikse, lütfen bunu genişletmemize yardımcı olun burada. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. - Ghostfolio ile varlıklarınızı kolaylıkla takip edin, analiz edin ve görselleştirin. + + The current market price is + Şu anki piyasa fiyatı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Get Started - Başlayın + + Test + Test - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - Personal Finance Tools - Kişisel Finans Araçları + + Date Range + Tarih Aralığı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 + libs/ui/src/lib/assistant/assistant.html + 143 - - Switzerland - İsviçre + + Permission + Yetki - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + apps/client/src/app/components/access-table/access-table.component.html + 18 - libs/ui/src/lib/i18n.ts - 90 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 - - Global - Küresel + + Restricted view + Kısıtlı görünüm - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/components/access-table/access-table.component.html + 26 - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Resources - Kaynaklar + + Oops! Could not grant access. + Hay Allah! Erişim izni verilemedi. - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 - - Guides - Kılavuzlar + + Private + Özel - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - Glossary - Sözlük + + Job Queue + İş Kuyruğu - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + libs/common/src/lib/routes/routes.ts + 46 - - Grant access - Erişim izni ver + + Market data is delayed for + Piyasa verileri gecikmeli - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 7 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 - - Public - Halka açık + + Investment + Yatırım - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 25 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - - - My Ghostfolio - Benim Ghostfolio’m - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 33 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - - - Auto - Otomatik - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - - - Please enter your coupon code: - Lütfen kupon kodunuzu girin: - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 - - Could not redeem coupon code - Kupon kodu kullanılamadı + + Absolute Asset Performance + Mutlak Varlık Performansı - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Coupon code has been redeemed - Kupon kodu kullanıldı + + Asset Performance + Varlık Performansı - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Reload - Yeniden Yükle + + Absolute Currency Performance + Mutlak Para Performansı - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 - - Do you really want to remove this sign in method? - Bu giriş yöntemini kaldırmayı gerçekten istiyor musunuz? + + Currency Performance + Para Performansı - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 - - Membership - Üyelik + + Absolute Net Performance + Mutlak Net Performans - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 - - Valid until - Geçerli tarih + + Net Performance + Net Performans - apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + Week to date + Hafta içi - libs/ui/src/lib/membership-card/membership-card.component.html - 42 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - per year - yıllık + + WTD + WTD - apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + Month to date + Ay içi - apps/client/src/app/pages/pricing/pricing-page.html - 274 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Try Premium - Premium’u Deneyin + + MTD + MTD - apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Redeem Coupon - Kupon Kullan + + Year to date + Yıl içi - apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Presenter View - Sunum Görünümü + + View + Görünüm - apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - Protection for sensitive information like absolute performances and quantity values - Gerçek performans ve miktar değerleri gibi hassas bilgilerin saklanması için + + Oops! A data provider is experiencing the hiccups. + Oops! Bir veri sağlayıcısı aksaklık yaşıyor. - apps/client/src/app/components/user-account-settings/user-account-settings.html + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html 8 - - Base Currency - Temel Para Birimi + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Eğer bugün emekli olursanız, paranızı çekebilirsiniz yıllık veya aylık, toplam varlıklarınıza göre ve %4’lük bir çekilme oranı. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 - - Language - Dil + + Reset Filters + Filtreleri Sıfırla - apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + libs/ui/src/lib/assistant/assistant.html + 238 - - Locale - Yerel Ayarlar + + year + Yıl - apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - - - Date and number format - Tarih ve Sayı Formatları - apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - - - Appearance - Görünüm - apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - Auto - Otomatik + + years + Yıllar - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Light - Açık + + Apply Filters + Filtreleri Uygula - apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + libs/ui/src/lib/assistant/assistant.html + 248 - - Dark - Koyu + + Data Gathering + Veri Toplama - apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 - - Distraction-free experience for turbulent times - Çalkantılı zamanlar için dikkat dağıtmayan bir deneyim + + General + Genel - apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 - - Biometric Authentication - Biyometrik Kimlik Doğrulama + + Cloud + Bulut - apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 - - - Sign in with fingerprint - Parmak iziyle oturum aç - apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + libs/common/src/lib/routes/routes.ts + 240 - - Experimental Features - Deneysel Özellikler + + Self-Hosting + Kendini Barındırma - apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - - - Sneak peek at upcoming functionality - Gelecek özelliklere göz atın - apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + libs/common/src/lib/routes/routes.ts + 248 - - User ID - Kullanıcı Kimliği + + self-hosting + kendini-barindirma + kebab-case - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 45 + libs/common/src/lib/routes/routes.ts + 243 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + libs/common/src/lib/routes/routes.ts + 246 - - Export Data - Verileri Dışa Aktar + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Oops! Görünüşe göre çok fazla istekte bulunuyorsunuz. Lütfen biraz yavaşlayın. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + apps/client/src/app/core/http-response.interceptor.ts + 106 - - Granted Access - xErişim İzni Verildi + + My Account + Hesabım - apps/client/src/app/components/user-account-access/user-account-access.html - 7 + apps/client/src/app/pages/i18n/i18n-page.html + 13 - - Oops, authentication has failed. - Hay Allah, kimlik doğrulaması başarısız oldu. + + Active + Aktif - apps/client/src/app/pages/webauthn/webauthn-page.html - 19 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 - - Try again - Yeniden dene + + Closed + Kapalı - apps/client/src/app/pages/webauthn/webauthn-page.html - 27 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 - - Go back to Home Page - Ana Sayfaya Geri Dön + + Indonesia + Indonesia - apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + libs/ui/src/lib/i18n.ts + 87 - - Import Activities - İşlemleri İçe Aktar + + Activity + Etkinlik - libs/ui/src/lib/activities-table/activities-table.component.html - 9 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + Dividend Yield + Temettü Getiri - libs/ui/src/lib/activities-table/activities-table.component.html - 371 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 - - Import Dividends - Temettüleri İçe Aktar + + Execute Job + İşlemi Yürüt - libs/ui/src/lib/activities-table/activities-table.component.html - 29 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + Priority + Öncelik - libs/ui/src/lib/activities-table/activities-table.component.html - 383 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 - - Export Activities - İşlemleri Dışa Aktar + + This action is not allowed. + Bu işlem izin verilmiyor. - libs/ui/src/lib/activities-table/activities-table.component.html - 41 + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + Liquidity + Likidite - libs/ui/src/lib/activities-table/activities-table.component.html - 396 + libs/ui/src/lib/i18n.ts + 48 - - Export Drafts as ICS - Taslakları ICS Olarak Dışa Aktar + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {Etkinlik} other {Etkinlikler}} - libs/ui/src/lib/activities-table/activities-table.component.html - 54 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + Buy and sell + Satın ve satın - libs/ui/src/lib/activities-table/activities-table.component.html - 409 + libs/ui/src/lib/i18n.ts + 8 - - Draft - Taslak + + Delete Activities + Etkinlikleri Sil libs/ui/src/lib/activities-table/activities-table.component.html - 145 + 67 - - Clone - Klonla + + Internationalization + İnternasyonalizasyon - libs/ui/src/lib/activities-table/activities-table.component.html - 436 + libs/common/src/lib/routes/routes.ts + 119 - - Export Draft as ICS - Taslakları ICS Olarak Dışa Aktar + + Do you really want to close your Ghostfolio account? + Ghostfolio hesabınızı kapatmak istediğinize emin misiniz? - libs/ui/src/lib/activities-table/activities-table.component.html - 446 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 - - Do you really want to delete this activity? - TBu işlemi silmeyi gerçekten istiyor musunuz? + + Danger Zone + Tehlikeli Alan - libs/ui/src/lib/activities-table/activities-table.component.ts - 229 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 - - Index - Endeks + + Close Account + Hesabı Kapat - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 - - Change from All Time High - Tüm Zamanların En Yüksek Seviyesinden (ATH) Değişim + + By ETF Holding + ETF Portföyü - libs/ui/src/lib/benchmark/benchmark.component.html - 81 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 - - from ATH - Tüm Zamanların En Yüksek Seviyesinden + + Approximation based on the top holdings of each ETF + Her ETF’nin en üst tutarlarına dayalı yaklaşım - libs/ui/src/lib/benchmark/benchmark.component.html - 83 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 - - Market data provided by - Piyasa verileri tarafından sağlanmıştır + + Join now or check out the example account + Hemen katıl ya da örnek hesabı incele - libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html - 2 + apps/client/src/app/pages/landing/landing-page.html + 435 - - Savings Rate per Month - Aylık Tasarruf Oranı + + Oops! There was an error setting up biometric authentication. + Oops! Biyometrik kimlik doğrulama ayarlanırken bir hata oluştu. - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 10 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 - - Annual Interest Rate - Yıllık Faiz Oranı + + Show more + Daha fazla göster - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 21 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 - - Retirement Date - Emeklilik Tarihi + + Benchmarks + Kıyaslamalar - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 32 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 - - Projected Total Amount - Hesaplanan Toplam Tutar + + Delete Profiles + Profilleri Sil - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 - - Interest - Faiz + + Do you really want to delete these profiles? + Bu profilleri silmek istediğinize emin misiniz? - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + Oops! Could not delete profiles. + Oops! Profilleri silmek mümkün olmadı. - libs/ui/src/lib/i18n.ts - 38 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 - - Savings - Tasarruflar + + Table + Tablo - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + apps/client/src/app/components/home-holdings/home-holdings.html + 16 - - Allocation - Dağılım + + Chart + Grafik - libs/ui/src/lib/holdings-table/holdings-table.component.html - 98 + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + Would you like to refine your personal investment strategy? + Senin özel yatırım stratejinizi iyileştirmek ister misin? - libs/ui/src/lib/top-holdings/top-holdings.component.html - 40 + apps/client/src/app/pages/public/public-page.html + 212 + + + Alternative + Alternatif - libs/ui/src/lib/top-holdings/top-holdings.component.html - 116 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 - - Show all - Tümünü göster + + App + App - libs/ui/src/lib/holdings-table/holdings-table.component.html - 197 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 - - Account - Hesap + + Budgeting + Bütçeleme - libs/ui/src/lib/i18n.ts - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 - - Asia-Pacific - Asya Pasifik + + Community + Topluluk - libs/ui/src/lib/i18n.ts - 5 + apps/client/src/app/app.component.html + 130 - - - Asset Class - Varlık Sınıfı - libs/ui/src/lib/i18n.ts - 6 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 - - - Asset Sub Class - Asset Sub Class - libs/ui/src/lib/i18n.ts - 7 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 - - - Core - Core - libs/ui/src/lib/i18n.ts - 10 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 - - - Switch to Ghostfolio Premium or Ghostfolio Open Source easily - Switch to Ghostfolio Premium or Ghostfolio Open Source easily - libs/ui/src/lib/i18n.ts - 12 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 - - - Switch to Ghostfolio Premium easily - Switch to Ghostfolio Premium easily - libs/ui/src/lib/i18n.ts - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 - - - Switch to Ghostfolio Open Source or Ghostfolio Basic easily - Switch to Ghostfolio Open Source or Ghostfolio Basic easily - libs/ui/src/lib/i18n.ts - 14 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 - - - Emergency Fund - Emergency Fund - libs/ui/src/lib/i18n.ts - 15 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 - - - Grant - Grant - libs/ui/src/lib/i18n.ts - 17 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 - - - Higher Risk - Higher Risk - libs/ui/src/lib/i18n.ts - 18 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 - - - This activity already exists. - This activity already exists. - libs/ui/src/lib/i18n.ts - 19 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 - - - Japan - Japan - libs/ui/src/lib/i18n.ts - 84 + apps/client/src/app/pages/features/features-page.html + 276 - - - Lower Risk - Lower Risk - libs/ui/src/lib/i18n.ts - 20 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 - - Month - Month + + Family Office + Aile Ofisi - libs/ui/src/lib/i18n.ts - 21 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 - - Months - Months + + Investor + Yatırımcı - libs/ui/src/lib/i18n.ts - 22 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 - - Other - Other + + Open Source + Açık Kaynak - libs/ui/src/lib/i18n.ts - 23 + apps/client/src/app/pages/landing/landing-page.html + 261 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 - - Preset - Preset + + Personal Finance + Kişisel Finans - libs/ui/src/lib/i18n.ts - 25 + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 - - Retirement Provision - Retirement Provision + + Privacy + Gizlilik - libs/ui/src/lib/i18n.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 - - Satellite - Satellite + + Software + Yazılım - libs/ui/src/lib/i18n.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 - - Symbol - Sembol + + Tool + Araç - libs/ui/src/lib/i18n.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 - - Tag - Etiket + + User Experience + Kullanıcı Deneyimi - libs/ui/src/lib/i18n.ts - 29 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 - - Year - Yıl + + Wealth + Zenginlik - libs/ui/src/lib/i18n.ts - 30 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 - - Years - Yıl + + Wealth Management + Zenginlik Yönetimi - libs/ui/src/lib/i18n.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 - - Buy - Al + + Australia + Avustralya libs/ui/src/lib/i18n.ts - 35 + 76 - - Valuable - Kıymet + + Austria + Avusturya libs/ui/src/lib/i18n.ts - 39 + 77 - - Liability - Yükümlülük + + Belgium + Belçika libs/ui/src/lib/i18n.ts - 40 + 78 - - Sell - Sat + + Bulgaria + Bulgaristan libs/ui/src/lib/i18n.ts - 41 + 80 - - Cash - Nakit + + Canada + Kanada libs/ui/src/lib/i18n.ts - 44 + 81 - - Commodity - Emtia + + Czech Republic + Çek Cumhuriyeti libs/ui/src/lib/i18n.ts - 45 + 82 - - Equity - Menkul Kıymet + + Finland + Finlandiya libs/ui/src/lib/i18n.ts - 46 + 83 - - Fixed Income - Sabit Gelir + + France + Fransa libs/ui/src/lib/i18n.ts - 47 + 84 - - Real Estate - Gayrimenkul + + Germany + Almanya libs/ui/src/lib/i18n.ts - 49 + 85 - - Bond - Bono + + India + Hindistan libs/ui/src/lib/i18n.ts - 52 + 86 - - Cryptocurrency - Kriptopara + + Italy + İtalya libs/ui/src/lib/i18n.ts - 53 + 88 - - ETF - Borsada İşlem Gören Fonlar (ETF) + + Netherlands + Hollanda libs/ui/src/lib/i18n.ts - 54 + 90 - - Mutual Fund - Borsada İşlem Görmeyen Fonlar (Mutual Fund) + + New Zealand + Yeni Zelanda libs/ui/src/lib/i18n.ts - 55 + 91 - - Precious Metal - Kıymetli Metaller + + Poland + Polonya libs/ui/src/lib/i18n.ts - 56 + 92 - - Private Equity - Özel Menkul Kıymetler + + Romania + Romanya libs/ui/src/lib/i18n.ts - 57 + 93 - - Stock - Hisse Senetleri + + South Africa + Güney Afrika libs/ui/src/lib/i18n.ts - 58 + 95 - - Africa - Afrika + + Thailand + Tayland libs/ui/src/lib/i18n.ts - 65 + 97 - - Asia - Asya + + United States + Amerika Birleşik Devletleri libs/ui/src/lib/i18n.ts - 66 + 100 - - Europe - Avrupa + + Error + Hata - libs/ui/src/lib/i18n.ts - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 - - North America - Kuzey Amerika + + Deactivate + Devre Dışı Bırak - libs/ui/src/lib/i18n.ts - 68 + apps/client/src/app/components/rule/rule.component.html + 72 - - Oceania - Okyanusya + + Activate + Aktif Et - libs/ui/src/lib/i18n.ts - 69 + apps/client/src/app/components/rule/rule.component.html + 74 - - South America - Güney Amerika + + Inactive + Pasif - libs/ui/src/lib/i18n.ts - 70 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 - - Time to add your first activity. - İlk işleminizi girmanin tam zamanı. + + Cancel + İptal Et - libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html - 12 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - No data available - Veri mevcut değil - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - You are using the Live Demo. - Canlı demoyu kullanmaktasınız. - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 - - Interest - Faiz + + Close + Kapat - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 - - (Last 24 hours) - (Son 24 saat) + + Yes + Evet - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/i18n.ts + 32 - - (Last 30 days) - (Son 30 gün) + + Copy link to clipboard + Bağlantıyı panoya kopyala - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + Portfolio Snapshot + Portföy Anlık Görüntüsü - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - (Last 90 days) - (Son 90 gün) + + Change with currency effect Change + Kur farkı etkisiyle değişim Değişim - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - One-time fee, annual account fees - Tek seferlik ücret, yıllık hesap ücreti + + Performance with currency effect Performance + Kur farkı etkisiyle performans Performans - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Distribution of corporate earnings - Şirket gelirinin dağıtımı + + Threshold Min + Eşik Min - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Revenue for lending out money - Borç verme getirisi + + Threshold Max + Eşik Max - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Oops! Could not get the historical exchange rate from - Hay Allah! Tarihsel kur verisi elde edilemedi + + Customize + Özelleştir - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/components/rule/rule.component.html + 67 - - Choose or drop a file here - Dosya seçin ya da sürükleyin + + No auto-renewal. + Otomatik yenileme yok. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Fee - Ücret + + This year + Bu yıl - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/public/public-page.html + 42 - - Add Tag - Etiket Ekleyiniz + + From the beginning + Başlangıçtan beri - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/public/public-page.html + 60 - - Do you really want to delete this tag? - Bu etiketi silmeyi gerçekten istiyor musunuz? + + Oops! Invalid currency. + Hay Allah! Geçersiz para birimi. - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Update tag - Etiketi güncelle + + This page has been archived. + Bu sayfa arşivlendi. - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Add tag - Etiket ekle + + is Open Source Software + , Açık Kaynak Kodlu Yazılımdır - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - - - Currency Cluster Risks - Kur Kümelenme Riskleri (Currency Cluster Risks) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Account Cluster Risks - Hesap Kümelenme Riski (Account Cluster Risks) + + is not Open Source Software + , Açık Kaynak Kodlu Yazılımdır - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Transfer Cash Balance - Nakit Bakiyesini Transfer Et + + can be self-hosted + kendi sunucunuzda barındırılabilir - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Benchmark - Kıyaslama + + cannot be self-hosted + kendi sunucunuzda barındırılmaz - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Version - Versiyon - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Settings - Ayarlar + + can be used anonymously + gizli kullanımda kullanılabilir - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - From - Başlangıç - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - To - Bitiş + + cannot be used anonymously + gizli kullanımda kullanılmaz - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - Transfer - Transfer - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Membership - Üyelik + + offers a free plan + ücretsiz plan sunar - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Access - Erişim + + does not offer a free plan + ücretsiz plan sunmaz - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Find holding... - Sahip olunan varlıkları bul... + + Oops! Could not find any assets. + Oops! Herhangi bir varlık bulunamadı. - libs/ui/src/lib/assistant/assistant.component.ts - 144 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - No entries... - Girdi yok... + + Data Providers + Veri Sağlayıcıları - libs/ui/src/lib/assistant/assistant.html - 63 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 + + + Set API key + API anahtarını ayarla - libs/ui/src/lib/assistant/assistant.html - 84 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Asset Profile - Varlık Profili + + Get access to 80’000+ tickers from over 50 exchanges + 80’000+ sembolden 50’den fazla borsada erişim alın - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + libs/ui/src/lib/i18n.ts + 24 - - Do you really want to delete this asset profile? - Bu varlık profilini silmeyi gerçekten istiyor musunuz? + + Ukraine + Ukraine - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + libs/ui/src/lib/i18n.ts + 98 - - Search - Arama + + Join now + Şimdi katıl - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Add Manually - Elle Giriş + + Glossary + Sözlük - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 + + + apps/client/src/app/pages/resources/resources-page.component.ts + 45 + + + libs/common/src/lib/routes/routes.ts + 293 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio, hisse senetleri, ETF’ler veya kriptopara birimleri gibi varlıklarınızı birden fazla platformda takip etmenizi sağlayan bir kişisel finans kontrol panelidir. + + Guides + Kılavuzlar - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/resources/guides/resources-guides.component.html 4 - - - Last All Time High - Son, ATH - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - User - Kullanıcı - apps/client/src/app/components/admin-users/admin-users.html - 29 + libs/common/src/lib/routes/routes.ts + 301 - - Ghostfolio vs comparison table - Ghostfolio ve karşılatırma tablosu + + guides + kilavuzlar + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + libs/common/src/lib/routes/routes.ts + 296 - - - Open Source Wealth Management Software - Açık Kaynak Varlık Yönetim Yazılımı - apps/client/src/app/pages/i18n/i18n-page.html - 14 + libs/common/src/lib/routes/routes.ts + 299 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - app, varlık, kriptopara, kontrol paneli, etf, finans, yönetim, performans, portföy, yazılım, hisse, alım satım, varlık, web3 + + glossary + sozluk + kebab-case - apps/client/src/app/pages/i18n/i18n-page.html - 9 + libs/common/src/lib/routes/routes.ts + 288 + + + libs/common/src/lib/routes/routes.ts + 291 - - Oops, cash balance transfer has failed. - Hay Allah, Nakit bakiyesi tranferi başarısız oldu. + + Threshold range + Eşik aralığı - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - Extreme Fear - Aşırı Korku + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray statik analiz kullanarak portföyünüzdeki potansiyel sorunları ve riskleri keşfetmek için kullanılır. Aşağıdaki kuralları ayarlayın ve özel eşikleri ayarlayarak kişisel yatırım stratejinize uyun. - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Extreme Greed - Aşırı Açgözlülük + + Economic Market Cluster Risks + Ekonomik Piyasa Küme Riskleri - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - Neutral - Nötr + + of + ın - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Oops! Could not parse historical data. - Hay Allah! Geçmiş veriler ayrıştırılamadı. + + daily requests + günlük istekler - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Do you really want to delete this system message? - Bu sistem mesajını silmeyi gerçekten istiyor musunuz? + + Remove API key + API anahtarını kaldır - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - 50-Day Trend - 50 Günlük Trend + + Do you really want to delete the API key? + API anahtarını silmek istediğinize emin misiniz? - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - 200-Day Trend - 200 Günlük Trend + + Please enter your Ghostfolio API key: + Ghostfolio API anahtarınızı girin: - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Cash Balances - Nakit Bakiyeleri + + API Requests Today + API Günü İstekleri - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Starting from - Başlangıç + + Could not generate an API key + API anahtarı oluşturulamadı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 + + + Set this API key in your self-hosted environment: + Bu API anahtarını kendi barındırılan ortamınıza ayarlayın: - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - year - Yıl + + Ghostfolio Premium Data Provider API Key + Ghostfolio Premium Veri Sağlayıcı API Anahtarı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 + + + Do you really want to generate a new API key? + Yeni bir API anahtarı oluşturmak istediğinize emin misiniz? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Do you really want to delete this account balance? - Bu nakit bakiyesini silmeyi gerçekten istiyor musunuz? + + API Key + API Anahtarı - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - is an invalid currency! - is an invalid currency! + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Kendi barındırılan ortamlar için Ghostfolio Premium Veri Sağlayıcı API anahtarı oluştur... - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - If a translation is missing, kindly support us in extending it here. - If a translation is missing, kindly support us in extending it here. + + out of + dışında - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - The current market price is - The current market price is + + rules align with your portfolio. + kurallar portföyünüze uyuyor. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Test - Test + + Save + Kaydet apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 559 - - - Date Range - Date Range - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Permission - Permission - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Restricted view - Restricted view - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - - - Oops! Could not grant access. - Oops! Could not grant access. - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Private - Private apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + 65 - - - Job Queue - Job Queue - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Market data is delayed for - Market data is delayed for - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Investment - Investment + + Asset Class Cluster Risks + Varlık Sınıfı Küme Riskleri - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + Me + Ben - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Absolute Asset Performance - Absolute Asset Performance + + Received Access + Alınan Erişim - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Asset Performance - Asset Performance + + Please enter your Ghostfolio API key. + Lütfen Ghostfolio API anahtarınızı girin. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Absolute Currency Performance - Absolute Currency Performance + + AI prompt has been copied to the clipboard + Yapay zeka istemi panoya kopyalandı - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Currency Performance - Currency Performance + + Link has been copied to the clipboard + Bağlantı panoya kopyalandı - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Absolute Net Performance - Absolute Net Performance + + Regional Market Cluster Risks + Bölgesel Piyasa Küme Riskleri - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Net Performance - Net Performance + + Lazy + Tembel - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Week to date - Week to date + + Instant + Anında - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - WTD - WTD + + Default Market Price + Varsayılan Piyasa Fiyatı - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Month to date - Month to date + + Mode + Mod - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - MTD - MTD + + Selector + Seçici - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Year to date - Year to date + + HTTP Request Headers + HTTP İstek Başlıkları - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - View - View + + end of day + gün sonu - apps/client/src/app/components/access-table/access-table.component.html - 23 - - - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - Oops! A data provider is experiencing the hiccups. - Oops! A data provider is experiencing the hiccups. + + real-time + gerçek zamanlı - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + + Open Duck.ai + Duck.ai’yi aç - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - Reset Filters - Reset Filters + + Create + Oluştur - libs/ui/src/lib/assistant/assistant.html - 185 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - year - year + + Change + Değişim - libs/ui/src/lib/assistant/assistant.component.ts - 235 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - years - years - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - Apply Filters - Apply Filters + + Performance + Performans - libs/ui/src/lib/assistant/assistant.html - 195 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - Data Gathering - Data Gathering - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - General - General - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Cloud - Cloud - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Self-Hosting - Self-Hosting + + Copy portfolio data to clipboard for AI prompt + Yapay zeka istemi için portföy verilerini panoya kopyalayın - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 + + + Copy AI prompt to clipboard for analysis + Yapay zeka istemini analiz için panoya kopyala - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - self-hosting - self-hosting + + Armenia + Ermenistan - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/ui/src/lib/i18n.ts + 75 - - FAQ - FAQ + + British Virgin Islands + Britanya Virjin Adaları - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + Singapur - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - Oops! It looks like you’re making too many requests. Please slow down a bit. + + Terms and Conditions + Hükümler ve Koşullar - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - My Account - My Account + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Lütfen güvenlik tokenınızı güvende tutun. Kaybetmeniz halinde hesabınızı kurtarmanız mümkün olmayacaktır. - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Active - Active + + I understand that if I lose my security token, I cannot recover my account + Güvenlik belirtecimi kaybedersem hesabımı kurtaramayacağımı anlıyorum. - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Closed - Closed + + Continue + Devam et - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Activity - Activity + + Here is your security token. It is only visible once, please store and keep it in a safe place. + İşte güvenlik belirteciniz. Yalnızca bir kez görülebilir, lütfen saklayın ve güvenli bir yerde muhafaza edin. - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Dividend Yield - Dividend Yield + + Security token + Güvenlik belirteci - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Execute Job - Execute Job - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Priority - Priority + + Do you really want to generate a new security token for this user? + Bu kullanıcı için yeni bir güvenlik belirteci oluşturmak istediğinize emin misiniz? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - This action is not allowed. - This action is not allowed. + + Generate Security Token + Güvenlik belirteci oluştur - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Liquidity - Liquidity + + United Kingdom + Birleşik Krallık libs/ui/src/lib/i18n.ts - 48 + 99 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + Terms of Service + Hükümler ve Koşullar - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Buy and sell - Buy and sell + + terms-of-service + hizmet-kosullari + kebab-case - libs/ui/src/lib/i18n.ts - 8 + libs/common/src/lib/routes/routes.ts + 212 + + + libs/common/src/lib/routes/routes.ts + 215 - - Delete Activities - Delete Activities + + Terms of Service + Hizmet Koşulları - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + apps/client/src/app/app.component.html + 112 + + + libs/common/src/lib/routes/routes.ts + 217 - - Internationalization - Internationalization + + and I agree to the Terms of Service. + ve kabul ediyorum Hizmet Koşulları. - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Do you really want to close your Ghostfolio account? - Do you really want to close your Ghostfolio account? + + () is already in use. + () is already in use. - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - Danger Zone - Danger Zone + + An error occurred while updating to (). + Güncelleştirilirken bir hata oluştu (). - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Close Account - Close Account + + Apply + Uygula - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - By ETF Holding - By ETF Holding + + with API access for + API erişimi için - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Gather Recent Historical Market Data + Yakın Geçmiş Piyasa Verilerini Topla - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Join now or check out the example account - Join now or check out the example account + + Gather All Historical Market Data + Tüm Geçmiş Piyasa Verilerini Topla - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + Gather Historical Market Data + Geçmiş Piyasa Verilerini Topla - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Show more - Show more + + Data Gathering is off + Veri Toplama Kapalı - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Benchmarks - Benchmarks + + Performance Calculation + Performans Hesaplaması - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Delete Profiles - Delete Profiles + + someone + birisi - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Do you really want to delete these profiles? - Do you really want to delete these profiles? + + Add asset to watchlist + Varlığı izleme listesine ekle - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Oops! Could not delete profiles. - Oops! Could not delete profiles. + + Watchlist + İzleme Listesi - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 + + + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 - - Table - Table + + Do you really want to delete this item? + Bu öğeyi silmek istediğinize emin misiniz? - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Chart - Chart + + Log out + Oturumu kapat - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/header/header.component.html + 329 - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? + + Calculations are based on delayed market data and may not be displayed in real-time. + Hesaplamalar gecikmeli piyasa verilerine dayanmaktadır ve gerçek zamanlı olarak görüntülenemeyebilir. - apps/client/src/app/pages/public/public-page.html - 211 + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 - - Alternative - Alternative + + changelog + degisiklik-gunlugu + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - App - App + + Demo user account has been synced. + Demo kullanıcı hesabı senkronize edildi. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Budgeting - Budgeting + + Sync Demo User Account + Demo Kullanıcı Hesabını Senkronize Et - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Community - Community + + Set up + Acil Durum Fonu: Kurulum - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Family Office - Family Office + + No emergency fund has been set up + Acil durum fonu oluşturulmadı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Investor - Investor + + An emergency fund has been set up + Acil durum fonu kuruldu - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Open Source - Open Source + + Fee Ratio + Ücret Oranı - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Personal Finance - Personal Finance + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Ücretler, ilk yatırımınızın %${thresholdMax} kadarını aşıyor (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Privacy - Privacy + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + Ücretler, ilk yatırımınızın %${thresholdMax}’ını (${feeRatio}%) aşmaz - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - Software - Software + + Name + İsim - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Tool - Tool + + Find holding or page... + Holding veya sayfayı bulun... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - User Experience - User Experience + + Quick Links + Hızlı Bağlantılar - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/assistant/assistant.html + 56 - - Wealth - Wealth + + Asset Profiles + Varlık Profilleri - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.html + 112 - - Wealth Management - Wealth Management + + Live Demo + Canlı Demo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Australia - Australia - libs/ui/src/lib/i18n.ts - 73 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Austria - Austria - libs/ui/src/lib/i18n.ts - 74 + libs/common/src/lib/routes/routes.ts + 231 - - Belgium - Belgium + + Open Source Alternative to + Açık Kaynak Alternatifi - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 326 - - Bulgaria - Bulgaria + + Single Account + Tek Hesap - libs/ui/src/lib/i18n.ts - 76 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Canada - Canada + + Your net worth is managed by a single account + Net değeriniz tek bir hesap tarafından yönetiliyor - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Czech Republic - Czech Republic + + Your net worth is managed by ${accountsLength} accounts + Net değeriniz ${accountsLength} hesaplar tarafından yönetiliyor - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - Finland - Finland + + personal-finance-tools + kisisel-finans-araclari + kebab-case - libs/ui/src/lib/i18n.ts - 79 + libs/common/src/lib/routes/routes.ts + 312 - - - France - France - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 315 - - - Germany - Germany - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 323 - - India - India + + markets + pazarlar + kebab-case - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 304 - - - Italy - Italy - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 307 - - Netherlands - Netherlands + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - libs/ui/src/lib/i18n.ts - 85 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - New Zealand - New Zealand + + Get Access + Erişim Alın - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Poland - Poland + + Learn more + Daha fazla bilgi edin - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - Romania - Romania + + Limited Offer! + Sınırlı Teklif! - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - South Africa - South Africa + + Get extra + Get extra - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Thailand - Thailand + + Available + Mevcut - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - United States - United States + + Unavailable + Mevcut değil - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Error - Error + + new + yeni - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Deactivate - Deactivate - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Activate - Activate + + Investment + Yatırım - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Inactive - Inactive + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Cancel - Cancel + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Close - Close + + Equity + özsermaye - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Yes - Yes + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Change with currency effect Change - Change with currency effect Change + + Fixed Income + Sabit Gelir - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Performance with currency effect Performance - Performance with currency effect Performance + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Close - Close + + Investment: Base Currency + Yatırım: Baz Para Birimi - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - Customize - Customize + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - Today - Today + + Investment + Yatırım - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - This year - This year + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - From the beginning - From the beginning + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - Oops! Invalid currency. - Oops! Invalid currency. + + start + baslangic + kebab-case - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + libs/common/src/lib/routes/routes.ts + 336 - - - This page has been archived. - This page has been archived. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 337 - - is Open Source Software - is Open Source Software + + Do you really want to generate a new security token? + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is not Open Source Software - is not Open Source Software + + Generate + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is Open Source Software - is Open Source Software + + Stocks + Stocks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - is not Open Source Software - is not Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/pages/features/features-page.html + 15 - - can be self-hosted - can be self-hosted + + Cryptocurrencies + Cryptocurrencies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - cannot be self-hosted - cannot be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/pages/features/features-page.html + 51 - - can be self-hosted - can be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - cannot be self-hosted - cannot be self-hosted + + Manage Asset Profile + Manage Asset Profile - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - can be used anonymously - can be used anonymously + + Alternative Investment + Alternative Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously - cannot be used anonymously + + Collectible + Collectible - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 54 - - can be used anonymously - can be used anonymously + + Average Unit Price + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - cannot be used anonymously - cannot be used anonymously - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + Asset Class Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + Currency Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + Economic Market Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + Emergency Fund - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + Regional Market Cluster Risks - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + No results found... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + Developed Markets - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + Emerging Markets - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + Net değeriniz 0 hesap tarafından yönetiliyor - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + Asya-Pasifik - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + Gelişmekte Olan Piyasalar - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + Avrupa - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + Japonya - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + Kuzey Amerika - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + GitHub’da Ghostfolio’yu bulun - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + Ghostfolio Slack topluluğuna katılın - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + Ghostfolio’yu X’te takip edin (eski adıyla Twitter) - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + Bir e-posta gönder - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + Ghostfolio’yu LinkedIn’de takip edin - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + Ghostfolio’yu destekleyin - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf new file mode 100644 index 000000000..49dd5e2d1 --- /dev/null +++ b/apps/client/src/locales/messages.uk.xlf @@ -0,0 +1,8136 @@ + + + + + Features + Функції + + apps/client/src/app/app.component.html + 79 + + + apps/client/src/app/components/header/header.component.html + 361 + + + apps/client/src/app/pages/features/features-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 256 + + + + Internationalization + Інтернаціоналізація + + libs/common/src/lib/routes/routes.ts + 119 + + + + Sign in + Увійти + + apps/client/src/app/components/header/header.component.html + 422 + + + apps/client/src/app/components/header/header.component.ts + 259 + + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 + + + libs/common/src/lib/routes/routes.ts + 81 + + + libs/common/src/lib/routes/routes.ts + 157 + + + + You are using the Live Demo. + Ви використовуєте демо-версію. + + apps/client/src/app/app.component.html + 12 + + + + Create Account + Створити обліковий запис + + apps/client/src/app/app.component.html + 13 + + + apps/client/src/app/pages/register/register-page.html + 27 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 2 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + + + + Frequently Asked Questions (FAQ) + Часті запитання (FAQ) + + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 + + + apps/client/src/app/pages/faq/saas/saas-page.html + 5 + + + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + Ризик втрат у торгівлі може бути суттєвим. Не рекомендується інвестувати гроші, які можуть знадобитися в короткостроковій перспективі. + + apps/client/src/app/app.component.html + 221 + + + + about + about + kebab-case + + libs/common/src/lib/routes/routes.ts + 176 + + + libs/common/src/lib/routes/routes.ts + 177 + + + libs/common/src/lib/routes/routes.ts + 182 + + + libs/common/src/lib/routes/routes.ts + 190 + + + libs/common/src/lib/routes/routes.ts + 198 + + + libs/common/src/lib/routes/routes.ts + 206 + + + libs/common/src/lib/routes/routes.ts + 214 + + + + license + license + kebab-case + + libs/common/src/lib/routes/routes.ts + 188 + + + libs/common/src/lib/routes/routes.ts + 191 + + + + privacy-policy + privacy-policy + kebab-case + + libs/common/src/lib/routes/routes.ts + 204 + + + libs/common/src/lib/routes/routes.ts + 207 + + + + faq + faq + kebab-case + + libs/common/src/lib/routes/routes.ts + 234 + + + libs/common/src/lib/routes/routes.ts + 235 + + + libs/common/src/lib/routes/routes.ts + 239 + + + libs/common/src/lib/routes/routes.ts + 245 + + + + features + features + kebab-case + + libs/common/src/lib/routes/routes.ts + 254 + + + libs/common/src/lib/routes/routes.ts + 255 + + + + markets + markets + kebab-case + + libs/common/src/lib/routes/routes.ts + 259 + + + libs/common/src/lib/routes/routes.ts + 260 + + + + pricing + pricing + kebab-case + + libs/common/src/lib/routes/routes.ts + 269 + + + libs/common/src/lib/routes/routes.ts + 270 + + + + register + register + kebab-case + + libs/common/src/lib/routes/routes.ts + 279 + + + libs/common/src/lib/routes/routes.ts + 280 + + + + resources + resources + kebab-case + + libs/common/src/lib/routes/routes.ts + 284 + + + libs/common/src/lib/routes/routes.ts + 285 + + + libs/common/src/lib/routes/routes.ts + 290 + + + libs/common/src/lib/routes/routes.ts + 298 + + + libs/common/src/lib/routes/routes.ts + 306 + + + libs/common/src/lib/routes/routes.ts + 314 + + + libs/common/src/lib/routes/routes.ts + 322 + + + + Alias + Псевдонім + + apps/client/src/app/components/access-table/access-table.component.html + 4 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 + + + + Grantee + Одержувач + + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + + Permission + Дозвіл + + apps/client/src/app/components/access-table/access-table.component.html + 18 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 + + + + View + Перегляд + + apps/client/src/app/components/access-table/access-table.component.html + 23 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 + + + + Restricted view + Обмежений перегляд + + apps/client/src/app/components/access-table/access-table.component.html + 26 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 + + + + Details + Деталі + + apps/client/src/app/components/access-table/access-table.component.html + 33 + + + + Copy link to clipboard + Скопіювати посилання в буфер обміну + + apps/client/src/app/components/access-table/access-table.component.html + 70 + + + + Revoke + Відкликати + + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + + Link has been copied to the clipboard + Посилання скопійовано в буфер обміну + + apps/client/src/app/components/access-table/access-table.component.ts + 94 + + + + Do you really want to revoke this granted access? + Ви дійсно хочете відкликати цей наданий доступ? + + apps/client/src/app/components/access-table/access-table.component.ts + 108 + + + + Cash Balance + Баланс готівки + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 + + + + Platform + Платформа + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 + + + + Holdings + Активи + + libs/ui/src/lib/assistant/assistant.html + 82 + + + + Cash Balances + Баланс готівки + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 + + + + Transfer Cash Balance + Перевести баланс готівки + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + + Name + Назва + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 89 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 + + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 + + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 138 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 16 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + + Total + Загалом + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 55 + + + + Currency + Валюта + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + + Value + Вартість + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 34 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 257 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 293 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 + + + + Edit + Редагувати + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 + + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 430 + + + + Delete + Видалити + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 131 + + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 80 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 457 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + + + + Do you really want to delete this account? + Ви дійсно хочете видалити цей обліковий запис? + + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 + + + + Type + Тип + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 15 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 161 + + + + Asset Profile + Профіль активу + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + + Historical Market Data + Історичні ринкові дані + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + + + + Portfolio Snapshot + Знімок портфеля + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 + + + + Data Source + Джерело даних + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 + + + + Priority + Пріоритет + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 + + + + Attempts + Спроби + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 + + + + Created + Створено + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 + + + + Finished + Завершено + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 + + + + Status + Статус + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 + + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + + + + Delete Jobs + Видалити завдання + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + + View Data + Переглянути дані + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + + View Stacktrace + Переглянути трасування + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + + Execute Job + Виконати завдання + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 + + + + Delete Job + Видалити завдання + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + + Benchmarks + Порівняльні показники + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + + Currencies + Валюти + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 + + + apps/client/src/app/pages/public/public-page.html + 88 + + + + ETFs without Countries + ETF без країн + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + + ETFs without Sectors + ETF без секторів + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + + Filter by... + Фільтрувати за... + + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + + Market Price + Ринкова ціна + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + + First Activity + Перша активність + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 + + + + Activities Count + Кількість активностей + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + + Historical Data + Історичні дані + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 + + + + Sectors Count + Кількість секторів + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + + Countries Count + Кількість країн + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 + + + + Gather Profile Data + Зібрати дані профілю + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 + + + + Delete Profiles + Видалити профілі + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + + Do you really want to delete this asset profile? + Ви дійсно хочете видалити цей профіль активу? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + + Oops! Could not delete profiles. + Упс! Не вдалося видалити профілі. + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + + Do you really want to delete these profiles? + Ви дійсно хочете видалити ці профілі? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + + Error + Помилка + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 + + + + The current market price is + Поточна ринкова ціна + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 + + + + Refresh + Оновити + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 + + + + Sector + Сектор + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 + + + + Country + Країна + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 + + + apps/client/src/app/components/admin-users/admin-users.html + 78 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 + + + + Sectors + Сектори + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 + + + apps/client/src/app/pages/public/public-page.html + 106 + + + + Countries + Країни + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 + + + + Symbol Mapping + Зіставлення символів + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 + + + + Scraper Configuration + Конфігурація скребка + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 + + + + Test + Тест + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 + + + + Url + URL + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 515 + + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 38 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 25 + + + + Note + Примітка + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 + + + + Add Asset Profile + Додати профіль активу + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 + + + + Search + Пошук + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 + + + + Add Manually + Додати вручну + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + + Add Currency + Додати валюту + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 + + + + Name, symbol or ISIN + Назва, символ або ISIN + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 + + + + Oops! Invalid currency. + Упс! Невірна валюта. + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 + + + + Do you really want to delete this coupon? + Ви дійсно хочете видалити цей купон? + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + + Do you really want to delete this system message? + Ви дійсно хочете видалити це системне повідомлення? + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + + Do you really want to flush the cache? + Ви дійсно хочете очистити кеш? + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 + + + + Please set your system message: + Будь ласка, встановіть ваше системне повідомлення: + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 + + + + Version + Версія + + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + + User Count + Кількість користувачів + + apps/client/src/app/components/admin-overview/admin-overview.html + 13 + + + + Activity Count + Кількість активностей + + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + + per User + на користувача + + apps/client/src/app/components/admin-overview/admin-overview.html + 28 + + + + User Signup + Реєстрація користувача + + apps/client/src/app/components/admin-overview/admin-overview.html + 34 + + + + Read-only Mode + Режим лише для читання + + apps/client/src/app/components/admin-overview/admin-overview.html + 48 + + + + Data Gathering + Збір даних + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 + + + apps/client/src/app/components/admin-overview/admin-overview.html + 60 + + + + System Message + Системне повідомлення + + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + + Set Message + Встановити повідомлення + + apps/client/src/app/components/admin-overview/admin-overview.html + 94 + + + + Coupons + Купони + + apps/client/src/app/components/admin-overview/admin-overview.html + 102 + + + + Add + Додати + + apps/client/src/app/components/admin-overview/admin-overview.html + 176 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + + + + Housekeeping + Прибирання + + apps/client/src/app/components/admin-overview/admin-overview.html + 184 + + + + Flush Cache + Очистити кеш + + apps/client/src/app/components/admin-overview/admin-overview.html + 200 + + + + Add Platform + Додати платформу + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + + Do you really want to delete this platform? + Ви дійсно хочете видалити цю платформу? + + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + + Update platform + Оновити платформу + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + + Add platform + Додати платформу + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + + Data Providers + Постачальники даних + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 + + + + Valid until + Дійсне до + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 + + + libs/ui/src/lib/membership-card/membership-card.component.html + 42 + + + + of + з + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 + + + + daily requests + щоденних запитів + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 + + + + Remove API key + Вилучити ключ API + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 + + + + Set API key + Встановити ключ API + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 + + + + Platforms + Платформи + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + + Tags + Теги + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 + + + + Do you really want to delete the API key? + Ви дійсно хочете видалити ключ API? + + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 + + + + Please enter your Ghostfolio API key. + Будь ласка, введіть ваш ключ API Ghostfolio. + + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 + + + + or + або + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 + + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 + + + apps/client/src/app/pages/landing/landing-page.html + 48 + + + apps/client/src/app/pages/landing/landing-page.html + 451 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 + + + apps/client/src/app/pages/register/register-page.html + 31 + + + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 + + + + Add Tag + Додати тег + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 + + + + User + Користувач + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 31 + + + apps/client/src/app/components/header/header.component.html + 231 + + + + Do you really want to delete this tag? + Ви дійсно хочете видалити цей тег? + + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + + Update tag + Оновити тег + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + + Add tag + Додати тег + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + + Do you really want to delete this user? + Ви дійсно хочете видалити цього користувача? + + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + + User + Користувач + + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + + Engagement per Day + Взаємодія за день + + apps/client/src/app/components/admin-users/admin-users.html + 158 + + + + API Requests Today + Запити API сьогодні + + apps/client/src/app/components/admin-users/admin-users.html + 179 + + + + Last Request + Останній запит + + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + + Impersonate User + Видавати себе за користувача + + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + + Delete User + Видалити користувача + + apps/client/src/app/components/admin-users/admin-users.html + 261 + + + + Compare with... + Порівняти з... + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + + Manage Benchmarks + Управляти порівняльними показниками + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 + + + + Portfolio + Портфель + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 + + + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 + + + libs/common/src/lib/routes/routes.ts + 151 + + + + Benchmark + Порівняльний показник + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + + Current Market Mood + Поточний ринковий настрій + + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 + + + + Upgrade Plan + Оновити план + + apps/client/src/app/components/header/header.component.html + 193 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 70 + + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 + + + apps/client/src/app/pages/pricing/pricing-page.html + 299 + + + + Renew Plan + Поновити план + + apps/client/src/app/components/header/header.component.html + 191 + + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 18 + + + apps/client/src/app/pages/pricing/pricing-page.html + 297 + + + + About Ghostfolio + Про Ghostfolio + + apps/client/src/app/components/header/header.component.html + 326 + + + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 + + + + Get started + Почати + + apps/client/src/app/components/header/header.component.html + 432 + + + + Oops! Incorrect Security Token. + Упс! Неправильний Секретний Токен. + + apps/client/src/app/components/header/header.component.ts + 274 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 + + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 + + + + Change with currency effect Change + Зміна з урахуванням валютного ефекту Зміна + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 + + + + Performance with currency effect Performance + Прибутковість з урахуванням валютного ефекту валюти Прибутковість + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 + + + + Minimum Price + Мінімальна ціна + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 + + + + Maximum Price + Максимальна ціна + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + + Quantity + Кількість + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 153 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 189 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 186 + + + + Dividend Yield + Дохідність дивіденду + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 + + + + Fees + Комісії + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 + + + + Indonesia + Indonesia + + libs/ui/src/lib/i18n.ts + 87 + + + + Activity + Активність + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 + + + + Report Data Glitch + Повідомити про збій даних + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 446 + + + + Active + Активний + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + + Closed + Закритий + + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 + + + + Table + Таблиця + + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + + Chart + Графік + + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + + Manage Activities + Керування діяльністю + + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + + Fear + Страх + + apps/client/src/app/components/home-market/home-market.component.ts + 42 + + + apps/client/src/app/components/markets/markets.component.ts + 47 + + + libs/ui/src/lib/i18n.ts + 105 + + + + Greed + Жадібність + + apps/client/src/app/components/home-market/home-market.component.ts + 43 + + + apps/client/src/app/components/markets/markets.component.ts + 48 + + + libs/ui/src/lib/i18n.ts + 106 + + + + Last Days + Останні днів + + apps/client/src/app/components/home-market/home-market.html + 7 + + + apps/client/src/app/components/markets/markets.html + 17 + + + + Welcome to Ghostfolio + Ласкаво просимо в Ghostfolio + + apps/client/src/app/components/home-overview/home-overview.html + 11 + + + + Ready to take control of your personal finances? + Готові взяти під контроль ваші особисті фінанси? + + apps/client/src/app/components/home-overview/home-overview.html + 12 + + + + Setup your accounts + Налаштуйте ваші рахунки + + apps/client/src/app/components/home-overview/home-overview.html + 19 + + + + Get a comprehensive financial overview by adding your bank and brokerage accounts. + Отримайте комплексний фінансовий огляд, додавши ваші банківські та брокерські рахунки. + + apps/client/src/app/components/home-overview/home-overview.html + 21 + + + + Capture your activities + Фіксуйте свою діяльність + + apps/client/src/app/components/home-overview/home-overview.html + 28 + + + + Record your investment activities to keep your portfolio up to date. + Записуйте ваші інвестиційні дії, щоб підтримувати актуальність вашого портфеля. + + apps/client/src/app/components/home-overview/home-overview.html + 30 + + + + Monitor and analyze your portfolio + Відстежуйте та аналізуйте свій портфель + + apps/client/src/app/components/home-overview/home-overview.html + 37 + + + + Track your progress in real-time with comprehensive analysis and insights. + Відстежуйте свій прогрес в режимі реального часу за допомогою всебічного аналізу та інсайтів + + apps/client/src/app/components/home-overview/home-overview.html + 39 + + + + Setup accounts + Налаштувати рахунки + + apps/client/src/app/components/home-overview/home-overview.html + 52 + + + + Add activity + Додати активність + + apps/client/src/app/components/home-overview/home-overview.html + 60 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 8 + + + + Total Amount + Загальна сума + + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 + + + + Savings Rate + Ставка заощаджень + + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 + + + + Security Token + Секретний Токен + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 + + + apps/client/src/app/components/user-account-access/user-account-access.html + 3 + + + apps/client/src/app/components/user-account-access/user-account-access.html + 15 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 + + + + Sign in with Internet Identity + Увійти з Інтернет-Ідентичністю + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + + Sign in with Google + Увійти з Google + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 + + + + Stay signed in + Залишатися в системі + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 + + + + Oops! A data provider is experiencing the hiccups. + Упс! У постачальника даних виникають проблеми. + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 + + + + Market data is delayed for + Ринкові дані затримуються для + + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Time in Market + Час на ринку + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {дія} other {дій}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Absolute Gross Performance + Абсолютний валовий дохід + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + + Absolute Net Performance + Абсолютний чистий прибуток + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 + + + + Net Performance + Чистий прибуток + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 + + + + Total Assets + Загальні активи + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + + Assets + Активи + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 + + + + Buying Power + Купівельна спроможність + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 + + + + Excluded from Analysis + Виключено з аналізу + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 + + + + Liabilities + Зобов’язання + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 + + + apps/client/src/app/pages/features/features-page.html + 102 + + + + Net Worth + Чиста вартість + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 + + + + Annualized Performance + Річна доходність + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 + + + + Save + Зберегти + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 32 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 + + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 + + + + Please set the amount of your emergency fund. + Будь ласка, встановіть суму вашого резервного фонду. + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 + + + + Threshold range + Діапазон порогу + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 + + + + Threshold Min + Мінімальний поріг + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 + + + + Threshold Max + Максимальний поріг + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 + + + + Customize + Налаштувати + + apps/client/src/app/components/rule/rule.component.html + 67 + + + + Deactivate + Деактивувати + + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + Активувати + + apps/client/src/app/components/rule/rule.component.html + 74 + + + + Are you an ambitious investor who needs the full picture? + Ви амбітний інвестор, якому потрібна повна картина? + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 + + + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + Оновіть до Ghostfolio Premium сьогодні та отримайте доступ до ексклюзивних функцій, щоб покращити ваш інвестиційний досвід: + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 + + + + Portfolio Summary + Резюме портфеля + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 + + + apps/client/src/app/pages/pricing/pricing-page.html + 44 + + + apps/client/src/app/pages/pricing/pricing-page.html + 205 + + + + Portfolio Allocations + Розподіли портфеля + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 + + + apps/client/src/app/pages/features/features-page.html + 161 + + + apps/client/src/app/pages/pricing/pricing-page.html + 48 + + + apps/client/src/app/pages/pricing/pricing-page.html + 209 + + + + Performance Benchmarks + Порівняльні показники продуктивності + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 + + + apps/client/src/app/pages/pricing/pricing-page.html + 52 + + + apps/client/src/app/pages/pricing/pricing-page.html + 213 + + + + FIRE Calculator + Калькулятор FIRE + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 + + + apps/client/src/app/pages/pricing/pricing-page.html + 56 + + + apps/client/src/app/pages/pricing/pricing-page.html + 217 + + + + Professional Data Provider + Професійний постачальник даних + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 + + + apps/client/src/app/pages/pricing/pricing-page.html + 237 + + + + and more Features... + і більше функцій... + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 + + + apps/client/src/app/pages/pricing/pricing-page.html + 72 + + + apps/client/src/app/pages/pricing/pricing-page.html + 261 + + + + Get the tools to effectively manage your finances and refine your personal investment strategy. + Отримайте інструменти для ефективного управління фінансами та вдосконалення вашої особистої інвестиційної стратегії. + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 + + + + Skip + Пропустити + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 + + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + + Join now + Приєднуйтесь + + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 + + + + Today + Сьогодні + + apps/client/src/app/pages/public/public-page.html + 24 + + + libs/ui/src/lib/assistant/assistant.component.ts + 348 + + + + YTD + З початку року + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + 1Y + 1 рік + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + 5Y + 5 років + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Max + Максимум + + libs/ui/src/lib/assistant/assistant.component.ts + 401 + + + + Oops! Could not grant access. + Упс! Не вдалося надати доступ. + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + + Grant access + Надати доступ + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 7 + + + + Private + Приватний + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 + + + + Public + Публічний + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 25 + + + + User ID + ID користувача + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 + + + + Me + Я + + apps/client/src/app/components/header/header.component.html + 213 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 + + + + Received Access + Отриманий доступ + + apps/client/src/app/components/user-account-access/user-account-access.html + 53 + + + + Granted Access + Наданий доступ + + apps/client/src/app/components/user-account-access/user-account-access.html + 57 + + + + Could not generate an API key + Не вдалося згенерувати ключ API + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 + + + + Okay + ОК + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 + + + apps/client/src/app/core/http-response.interceptor.ts + 89 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 + + + + Set this API key in your self-hosted environment: + Встановіть цей ключ API у вашому self-hosted середовищі: + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 + + + + Ghostfolio Premium Data Provider API Key + Ключ API Ghostfolio Premium Data Provider + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 + + + + Do you really want to generate a new API key? + Ви дійсно хочете згенерувати новий ключ API? + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 + + + + Could not redeem coupon code + Не вдалося обміняти код купона + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 + + + + Coupon code has been redeemed + Код купона був обміняний + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 + + + + Reload + Перезавантажити + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 + + + + Please enter your coupon code. + Будь ласка, введіть ваш код купона. + + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 + + + + per year + на рік + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 + + + apps/client/src/app/pages/pricing/pricing-page.html + 283 + + + + Try Premium + Спробуйте Premium + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 + + + + Redeem Coupon + Обміняти купон + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 + + + + No auto-renewal. + Без автоматичного поновлення. + + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 + + + + Auto + Автоматичний + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 + + + + Do you really want to close your Ghostfolio account? + Ви дійсно хочете закрити ваш обліковий запис Ghostfolio? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + + Do you really want to remove this sign in method? + Ви дійсно хочете вилучити цей спосіб входу? + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 + + + + Oops! There was an error setting up biometric authentication. + Упс! Виникла помилка під час налаштування біометричної автентифікації. + + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + + Presenter View + Режим доповідача + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 + + + + Protection for sensitive information like absolute performances and quantity values + Захист конфіденційної інформації, такої як абсолютні показники та кількісні значення + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 + + + + Base Currency + Базова валюта + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 + + + + Language + Мова + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 + + + + If a translation is missing, kindly support us in extending it here. + Якщо переклад відсутній, будь ласка, підтримайте нас у його розширенні тут. + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 + + + + Locale + Локалізація + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 + + + + Date and number format + Формат дати та чисел + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 + + + + Appearance + Зовнішній вигляд + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 + + + + Light + Світлий + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 + + + + Dark + Темний + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 + + + + Zen Mode + Режим дзен + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 + + + apps/client/src/app/pages/features/features-page.html + 246 + + + + Distraction-free experience for turbulent times + Досвід без відволікань для неспокійних часів + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 + + + + Biometric Authentication + Біометрична аутентифікація + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 + + + + Sign in with fingerprint + Увійти з відбитком пальця + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 + + + + Experimental Features + Експериментальні функції + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 + + + + Sneak peek at upcoming functionality + Попередній перегляд майбутніх функцій + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 + + + + Export Data + Експортувати дані + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 + + + + Danger Zone + Зона небезпеки + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + + Close Account + Закрити обліковий запис + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + + This feature is currently unavailable. + Ця функція наразі недоступна. + + apps/client/src/app/core/http-response.interceptor.ts + 55 + + + + Please try again later. + Спробуйте ще раз пізніше. + + apps/client/src/app/core/http-response.interceptor.ts + 57 + + + apps/client/src/app/core/http-response.interceptor.ts + 88 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 + + + + This action is not allowed. + Ця дія заборонена. + + apps/client/src/app/core/http-response.interceptor.ts + 67 + + + + Oops! Something went wrong. + Упс! Щось пішло не так. + + apps/client/src/app/core/http-response.interceptor.ts + 86 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 + + + + Oops! It looks like you’re making too many requests. Please slow down a bit. + Упс! Здається, ви робите занадто багато запитів. Будь ласка, пригальмуй трохи. + + apps/client/src/app/core/http-response.interceptor.ts + 106 + + + + About + Про нас + + apps/client/src/app/app.component.html + 70 + + + apps/client/src/app/components/header/header.component.html + 124 + + + apps/client/src/app/components/header/header.component.html + 375 + + + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 220 + + + + Changelog + Журнал змін + + apps/client/src/app/app.component.html + 77 + + + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 185 + + + + License + Ліцензія + + apps/client/src/app/app.component.html + 89 + + + apps/client/src/app/pages/about/license/license-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 193 + + + + Privacy Policy + Політика конфіденційності + + apps/client/src/app/app.component.html + 105 + + + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 209 + + + + Our + Наші + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 + + + + Discover other exciting Open Source Software projects + Відкрийте для себе інші захоплюючі проекти з відкритим кодом + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 + + + + Visit + Відвідати + + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 + + + + Accounts + Рахунки + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 + + + apps/client/src/app/components/admin-users/admin-users.html + 115 + + + apps/client/src/app/components/header/header.component.html + 58 + + + apps/client/src/app/components/header/header.component.html + 268 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 + + + apps/client/src/app/pages/accounts/accounts-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 69 + + + + Oops, cash balance transfer has failed. + Упс, перенесення балансу готівки не вдалося. + + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + + Update account + Оновити рахунок + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 + + + + Add account + Додати рахунок + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 + + + + Account ID + Ідентифікатор облікового запису + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 + + + + From + Від + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 + + + + To + До + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 + + + + Transfer + Переказати + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 + + + + Admin Control + Управління адміністратором + + apps/client/src/app/components/header/header.component.html + 74 + + + apps/client/src/app/components/header/header.component.html + 289 + + + libs/common/src/lib/routes/routes.ts + 64 + + + + Job Queue + Черга завдань + + libs/common/src/lib/routes/routes.ts + 46 + + + + Market Data + Ринкові дані + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 + + + libs/common/src/lib/routes/routes.ts + 51 + + + + Settings + Налаштування + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 + + + libs/common/src/lib/routes/routes.ts + 34 + + + libs/common/src/lib/routes/routes.ts + 56 + + + + Users + Користувачі + + libs/common/src/lib/routes/routes.ts + 61 + + + + Overview + Огляд + + apps/client/src/app/components/header/header.component.html + 30 + + + apps/client/src/app/components/header/header.component.html + 248 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 48 + + + apps/client/src/app/pages/resources/resources-page.component.ts + 30 + + + libs/common/src/lib/routes/routes.ts + 113 + + + libs/common/src/lib/routes/routes.ts + 170 + + + + Please enter your Ghostfolio API key: + Будь ласка, введіть ваш ключ API Ghostfolio: + + apps/client/src/app/pages/api/api-page.component.ts + 41 + + + + Blog + Блог + + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 + + + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 + + + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 + + + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 + + + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 + + + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 + + + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 + + + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 + + + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 + + + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 + + + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 + + + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 + + + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 + + + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 + + + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 + + + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 + + + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 + + + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 + + + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 + + + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 + + + apps/client/src/app/pages/blog/blog-page.html + 5 + + + libs/common/src/lib/routes/routes.ts + 225 + + + + Discover the latest Ghostfolio updates and insights on personal finance + Відкрийте для себе останні оновлення Ghostfolio та виявлення особистих фінансів + + apps/client/src/app/pages/blog/blog-page.html + 7 + + + + As you are already logged in, you cannot access the demo account. + Оскільки ви вже ввійшли, ви не можете отримати доступ до демонстраційного обліковий запис. + + apps/client/src/app/pages/demo/demo-page.component.ts + 35 + + + + Frequently Asked Questions (FAQ) + Часто задавані питання (FAQ) + + apps/client/src/app/app.component.html + 83 + + + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 + + + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 251 + + + + General + Загальні + + apps/client/src/app/pages/faq/faq-page.component.ts + 49 + + + + Cloud + Хмара + + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 + + + + Self-Hosting + Самохостинг + + apps/client/src/app/pages/faq/faq-page.component.ts + 60 + + + libs/common/src/lib/routes/routes.ts + 248 + + + + self-hosting + samohosting + kebab-case + + libs/common/src/lib/routes/routes.ts + 243 + + + libs/common/src/lib/routes/routes.ts + 246 + + + + Check out the numerous features of Ghostfolio to manage your wealth + Огляньте численні функції Ghostfolio для управління вашим багатством + + apps/client/src/app/pages/features/features-page.html + 7 + + + + ETFs + ETF + + apps/client/src/app/pages/features/features-page.html + 25 + + + + Bonds + Облігації + + apps/client/src/app/pages/features/features-page.html + 38 + + + + Wealth Items + Предмети багатства + + apps/client/src/app/pages/features/features-page.html + 76 + + + + Import and Export + Імпорт та експорт + + apps/client/src/app/pages/features/features-page.html + 116 + + + + Multi-Accounts + Багатокористувацькі акаунти + + apps/client/src/app/pages/features/features-page.html + 127 + + + + Portfolio Calculations + Розрахунки портфеля + + apps/client/src/app/pages/features/features-page.html + 141 + + + + Dark Mode + Темний режим + + apps/client/src/app/pages/features/features-page.html + 233 + + + + Market Mood + Ринковий настрій + + apps/client/src/app/pages/features/features-page.html + 215 + + + + Static Analysis + Статичний аналіз + + apps/client/src/app/pages/features/features-page.html + 179 + + + + Multi-Language + Багатомовність + + apps/client/src/app/pages/features/features-page.html + 259 + + + + Open Source Software + Програмне забезпечення з відкритим кодом + + apps/client/src/app/pages/features/features-page.html + 295 + + + + Get Started + Почати + + apps/client/src/app/pages/features/features-page.html + 320 + + + apps/client/src/app/pages/public/public-page.html + 220 + + + + Holdings + Активи + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 + + + apps/client/src/app/components/home-holdings/home-holdings.html + 4 + + + apps/client/src/app/pages/public/public-page.html + 70 + + + libs/common/src/lib/routes/routes.ts + 90 + + + libs/common/src/lib/routes/routes.ts + 167 + + + + Summary + Зведення + + apps/client/src/app/components/home-summary/home-summary.html + 2 + + + libs/common/src/lib/routes/routes.ts + 105 + + + + Markets + Ринки + + apps/client/src/app/app.component.html + 61 + + + apps/client/src/app/components/header/header.component.html + 408 + + + apps/client/src/app/components/home-market/home-market.html + 2 + + + apps/client/src/app/components/markets/markets.html + 2 + + + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 + + + apps/client/src/app/pages/resources/resources-page.component.ts + 40 + + + libs/common/src/lib/routes/routes.ts + 95 + + + libs/common/src/lib/routes/routes.ts + 100 + + + libs/common/src/lib/routes/routes.ts + 261 + + + libs/common/src/lib/routes/routes.ts + 309 + + + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio - це панель особистих фінансів для відстеження вашого чистого капіталу, включаючи готівку, акції, ETF та криптовалюти на різних платформах. + + apps/client/src/app/pages/i18n/i18n-page.html + 5 + + + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + додаток, актив, криптовалюта, панель, etf, фінанси, управління, продуктивність, портфель, програмне забезпечення, акція, торгівля, багатство, web3 + + apps/client/src/app/pages/i18n/i18n-page.html + 10 + + + + My Account + Мій рахунок + + apps/client/src/app/pages/i18n/i18n-page.html + 13 + + + + Open Source Wealth Management Software + Програмне забезпечення управління багатством з відкритим кодом + + apps/client/src/app/pages/i18n/i18n-page.html + 224 + + + + Manage your wealth like a boss + Керуйте своїми фінансами як професіонал + + apps/client/src/app/pages/landing/landing-page.html + 6 + + + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio - це інформаційна панель з відкритим кодом для управління вашими особистими фінансами, орієнтована насамперед на конфіденційність. Розподіліть свої активи, визначте чисту вартість свого майна та приймайте зважені інвестиційні рішення на основі даних. + + apps/client/src/app/pages/landing/landing-page.html + 10 + + + + Get Started + Почати + + apps/client/src/app/pages/landing/landing-page.html + 42 + + + apps/client/src/app/pages/landing/landing-page.html + 447 + + + apps/client/src/app/pages/pricing/pricing-page.html + 351 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 + + + + Monthly Active Users + Щомісячні активні користувачі + + apps/client/src/app/pages/landing/landing-page.html + 70 + + + + Stars on GitHub + Зірки на GitHub + + apps/client/src/app/pages/landing/landing-page.html + 88 + + + apps/client/src/app/pages/open/open-page.html + 103 + + + + Pulls on Docker Hub + Завантаження на Docker Hub + + apps/client/src/app/pages/landing/landing-page.html + 106 + + + apps/client/src/app/pages/open/open-page.html + 117 + + + + As seen in + Як видно в + + apps/client/src/app/pages/landing/landing-page.html + 115 + + + + Protect your assets. Refine your personal investment strategy. + Захищайте свої активи. Вдосконалюйте власну інвестиційну стратегію. + + apps/client/src/app/pages/landing/landing-page.html + 226 + + + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio допомагає зайнятим людям відстежувати акції, ETF або криптовалюти без ризику бути відстеженими. + + apps/client/src/app/pages/landing/landing-page.html + 230 + + + + 360° View + 360° огляд + + apps/client/src/app/pages/landing/landing-page.html + 240 + + + + Get the full picture of your personal finances across multiple platforms. + Отримайте повну картину ваших особистих фінансів на різних платформах. + + apps/client/src/app/pages/landing/landing-page.html + 243 + + + + Web3 Ready + Готовий до Web3 + + apps/client/src/app/pages/landing/landing-page.html + 251 + + + + Use Ghostfolio anonymously and own your financial data. + Використовуйте Ghostfolio анонімно та володійте своїми фінансовими даними. + + apps/client/src/app/pages/landing/landing-page.html + 254 + + + + Benefit from continuous improvements through a strong community. + Отримуйте користь від постійних покращень завдяки сильній спільноті. + + apps/client/src/app/pages/landing/landing-page.html + 264 + + + + Why Ghostfolio? + Чому Ghostfolio? + + apps/client/src/app/pages/landing/landing-page.html + 272 + + + + Ghostfolio is for you if you are... + Ghostfolio для вас, якщо ви... + + apps/client/src/app/pages/landing/landing-page.html + 274 + + + + trading stocks, ETFs or cryptocurrencies on multiple platforms + торгуєте акціями, ETF або криптовалютами на різних платформах + + apps/client/src/app/pages/landing/landing-page.html + 280 + + + + pursuing a buy & hold strategy + дотримуєтеся стратегії купівлі та утримання + + apps/client/src/app/pages/landing/landing-page.html + 286 + + + + interested in getting insights of your portfolio composition + вас цікавлять інсайти вашого складу портфеля + + apps/client/src/app/pages/landing/landing-page.html + 291 + + + + valuing privacy and data ownership + цінуєте конфіденційність і володіння даними + + apps/client/src/app/pages/landing/landing-page.html + 296 + + + + into minimalism + займаєтесь мінімалізмом + + apps/client/src/app/pages/landing/landing-page.html + 299 + + + + caring about diversifying your financial resources + піклуєтесь про диверсифікацію ваших фінансових ресурсів + + apps/client/src/app/pages/landing/landing-page.html + 303 + + + + interested in financial independence + цікавитесь фінансовою незалежністю + + apps/client/src/app/pages/landing/landing-page.html + 307 + + + + saying no to spreadsheets in + кажете ні таблицям у + + apps/client/src/app/pages/landing/landing-page.html + 311 + + + + still reading this list + все ще читаєте цей список + + apps/client/src/app/pages/landing/landing-page.html + 314 + + + + Learn more about Ghostfolio + Дізнайтеся більше про Ghostfolio + + apps/client/src/app/pages/landing/landing-page.html + 319 + + + + What our users are saying + Що говорять користувачі + + apps/client/src/app/pages/landing/landing-page.html + 328 + + + + Members from around the globe are using Ghostfolio Premium + Члени зі всього світу використовують Ghostfolio Premium + + apps/client/src/app/pages/landing/landing-page.html + 367 + + + + How does Ghostfolio work? + Як працює Ghostfolio? + + apps/client/src/app/pages/landing/landing-page.html + 384 + + + + Get started in only 3 steps + Почніть всього за 3 кроки + + apps/client/src/app/pages/landing/landing-page.html + 386 + + + + Sign up anonymously* + Зареєструйтеся анонімно* + + apps/client/src/app/pages/landing/landing-page.html + 392 + + + + * no e-mail address nor credit card required + * не потрібні електронна адреса та кредитна картка + + apps/client/src/app/pages/landing/landing-page.html + 394 + + + + Add any of your historical transactions + Додайте будь-які з ваших історичних транзакцій + + apps/client/src/app/pages/landing/landing-page.html + 406 + + + + Get valuable insights of your portfolio composition + Отримуйте цінні інсайти вашого складу портфеля + + apps/client/src/app/pages/landing/landing-page.html + 418 + + + + Are you ready? + Ви готові? + + apps/client/src/app/pages/landing/landing-page.html + 432 + + + + Join now or check out the example account + Приєднуйтесь зараз або перегляньте демонстраційний рахунок + + apps/client/src/app/pages/landing/landing-page.html + 435 + + + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + У Ghostfolio прозорість є основою наших цінностей. Ми публікуємо вихідний код як відкрите програмне забезпечення (OSS) під AGPL-3.0 ліцензією та відкрито ділимося агрегованими ключовими метриками операційного стану платформи. + + apps/client/src/app/pages/open/open-page.html + 7 + + + + (Last 24 hours) + (Останні 24 години) + + apps/client/src/app/pages/open/open-page.html + 37 + + + + Active Users + Активні користувачі + + apps/client/src/app/pages/open/open-page.html + 40 + + + apps/client/src/app/pages/open/open-page.html + 62 + + + + (Last 30 days) + (Останні 30 днів) + + apps/client/src/app/pages/open/open-page.html + 48 + + + apps/client/src/app/pages/open/open-page.html + 59 + + + + New Users + Нові користувачі + + apps/client/src/app/pages/open/open-page.html + 51 + + + + Users in Slack community + Користувачі в спільноті Slack + + apps/client/src/app/pages/open/open-page.html + 75 + + + + Contributors on GitHub + Учасники на GitHub + + apps/client/src/app/pages/open/open-page.html + 89 + + + + (Last 90 days) + (Останні 90 днів) + + apps/client/src/app/pages/open/open-page.html + 127 + + + + Uptime + Час безвідмовної роботи + + apps/client/src/app/pages/open/open-page.html + 132 + + + + Activities + Активності + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 + + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 + + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 + + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 + + + apps/client/src/app/components/admin-users/admin-users.html + 136 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 + + + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 + + + libs/common/src/lib/routes/routes.ts + 128 + + + + Update activity + Оновити активність + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 + + + + Stocks, ETFs, bonds, cryptocurrencies, commodities + Акції, ETF, облігації, криптовалюти, товари + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 65 + + + + One-time fee, annual account fees + Одноразова комісія, щорічна комісія за обслуговування рахунку + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 + + + + Distribution of corporate earnings + Розподіл корпоративних доходів + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + + Revenue for lending out money + Доходи за кредитування грошей + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + + Mortgages, personal loans, credit cards + Іпотека, особисті кредити, кредитні картки + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 + + + + Luxury items, real estate, private companies + Предмети розкоші, нерухомість, приватні компанії + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 + + + + Update Cash Balance + Оновити баланс готівки + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 + + + + Date + Дата + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 12 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 170 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + + Unit Price + Ціна за одиницю + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 210 + + + + Import Activities + Імпортувати активності + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 9 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 371 + + + + Import Dividends + Імпорт дивідендів + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 129 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 29 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 383 + + + + Importing data... + Імпортуються дані... + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 167 + + + + Import has been completed + Імпорт завершено + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 176 + + + + Validating data... + Перевірка даних... + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 + + + + Select Holding + Вибрати актив + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 + + + + Select File + Вибрати файл + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 22 + + + + Holding + Актив + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 + + + libs/ui/src/lib/assistant/assistant.html + 179 + + + + Load Dividends + Завантажити дивіденди + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 + + + + Choose or drop a file here + Виберіть або перетягніть файл сюди + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + + The following file formats are supported: + Підтримуються наступні формати файлів: + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 + + + + Select Dividends + Вибрати дивіденди + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 + + + + Select Activities + Виберіть активності + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 + + + + Back + Назад + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 + + + + Import + Імпорт + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 + + + + Allocations + Розподіли + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 + + + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 + + + libs/common/src/lib/routes/routes.ts + 133 + + + + Proportion of Net Worth + Частка чистої вартості + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 + + + + By Platform + За платформою + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 44 + + + + By Currency + За валютою + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 + + + + By Asset Class + За класом активів + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 + + + + By Holding + За активом + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 + + + + By Sector + За сектором + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 + + + + By Continent + За континентом + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 + + + + By Market + За ринком + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 175 + + + + Regions + Регіони + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 + + + apps/client/src/app/pages/public/public-page.html + 143 + + + + Developed Markets + Розвиті ринки + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 + + + apps/client/src/app/pages/public/public-page.html + 160 + + + + Emerging Markets + Ринки, що розвиваються + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 + + + apps/client/src/app/pages/public/public-page.html + 169 + + + + Other Markets + Інші ринки + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 + + + apps/client/src/app/pages/public/public-page.html + 178 + + + + By Country + За країною + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 + + + + By Account + За рахунком + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 + + + + By ETF Provider + За постачальником ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 + + + + By ETF Holding + За активами ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + + Approximation based on the top holdings of each ETF + Наближення на основі провідних активів кожного ETF + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 + + + + Analysis + Аналіз + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 + + + libs/common/src/lib/routes/routes.ts + 138 + + + + Dividend + Дивіденди + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 + + + apps/client/src/app/pages/features/features-page.html + 63 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 + + + libs/ui/src/lib/i18n.ts + 36 + + + + Investment + Інвестиції + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 + + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + + Monthly + Щомісячно + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 + + + + Yearly + Щорічно + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 + + + + Absolute Asset Performance + Абсолютна прибутковість активів + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + + Asset Performance + Прибутковість активів + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 + + + + Absolute Currency Performance + Абсолютна прибутковість валюти + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + + Currency Performance + Прибутковість валюти + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + + Absolute Net Performance + Абсолютна чиста прибутковість + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + + Net Performance + Чиста прибутковість + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + + Top + Топ + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 + + + + Bottom + Низ + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + + + Portfolio Evolution + Еволюція портфеля + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 + + + + Investment Timeline + Інвестиційний графік + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 + + + + Current Streak + Поточна серія + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 + + + + Longest Streak + Найдовша серія + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 + + + + Dividend Timeline + Графік дивідендів + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 + + + + FIRE + Фінансова незалежність, достроковий вихід на пенсію (FIRE) + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 4 + + + + Calculator + Калькулятор + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 + + + + 4% Rule + Правило 4% + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + Якщо ви вийдете на пенсію сьогодні, ви зможете знімати на рік або на місяць, виходячи з вашого загального капіталу в та ставкою виведення у 4%. + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 + + + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray використовує статичний аналіз для виявлення потенційних проблем та ризиків у вашому портфелі. Налаштуйте правила нижче та встановіть індивідуальні пороги, щоб узгодити їх з вашою особистою інвестиційною стратегією. + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 + + + + out of + з + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 + + + + rules align with your portfolio. + правила узгоджуються з вашим портфелем. + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 + + + + Currency Cluster Risks + Ризики зосередження валюти + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 + + + + Asset Class Cluster Risks + Ризики зосередження класу активів + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + + Account Cluster Risks + Ризики зосередження рахунків + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + + Economic Market Cluster Risks + Ризики зосередження економічного ринку + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 + + + + Inactive + Неактивний + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + + Pricing + Ціни + + apps/client/src/app/app.component.html + 99 + + + apps/client/src/app/components/header/header.component.html + 105 + + + apps/client/src/app/components/header/header.component.html + 313 + + + apps/client/src/app/components/header/header.component.html + 389 + + + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts + 13 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 + + + libs/common/src/lib/routes/routes.ts + 271 + + + + Pricing Plans + Плани цін + + apps/client/src/app/pages/pricing/pricing-page.html + 4 + + + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + Наша офіційна хмарна пропозиція Ghostfolio Premium - це найпростіший спосіб почати роботу. Завдяки економії часу, це буде найкращим варіантом для більшості людей. Доходи використовуються для покриття витрат на хостинг-інфраструктуру та фінансування постійної розробки. + + apps/client/src/app/pages/pricing/pricing-page.html + 7 + + + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + Якщо ви віддаєте перевагу запускати Ghostfolio на власній інфраструктурі, перейдіть на GitHub для отримання вихідного коду та подальших інструкцій. + + apps/client/src/app/pages/pricing/pricing-page.html + 14 + + + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + Для технікознавих інвесторів, які віддають перевагу запуску Ghostfolio на власній інфраструктурі. + + apps/client/src/app/pages/pricing/pricing-page.html + 26 + + + + Unlimited Transactions + Необмежені транзакції + + apps/client/src/app/pages/pricing/pricing-page.html + 32 + + + apps/client/src/app/pages/pricing/pricing-page.html + 121 + + + apps/client/src/app/pages/pricing/pricing-page.html + 193 + + + + Unlimited Accounts + Необмежена кількість рахунків + + apps/client/src/app/pages/pricing/pricing-page.html + 36 + + + apps/client/src/app/pages/pricing/pricing-page.html + 125 + + + apps/client/src/app/pages/pricing/pricing-page.html + 197 + + + + Portfolio Performance + Прибутковість портфеля + + apps/client/src/app/pages/pricing/pricing-page.html + 40 + + + apps/client/src/app/pages/pricing/pricing-page.html + 129 + + + apps/client/src/app/pages/pricing/pricing-page.html + 201 + + + + Data Import and Export + Імпорт та експорт даних + + apps/client/src/app/pages/pricing/pricing-page.html + 60 + + + apps/client/src/app/pages/pricing/pricing-page.html + 133 + + + apps/client/src/app/pages/pricing/pricing-page.html + 221 + + + + Community Support + Підтримка спільноти + + apps/client/src/app/pages/pricing/pricing-page.html + 77 + + + + Self-hosted, update manually. + Самохостинг, оновлення вручну. + + apps/client/src/app/pages/pricing/pricing-page.html + 81 + + + + Free + Безкоштовно + + apps/client/src/app/pages/pricing/pricing-page.html + 83 + + + apps/client/src/app/pages/pricing/pricing-page.html + 146 + + + + For new investors who are just getting started with trading. + Для нових інвесторів, які тільки починають з торгівлі. + + apps/client/src/app/pages/pricing/pricing-page.html + 116 + + + + Fully managed Ghostfolio cloud offering. + Повністю керована хмарна пропозиція Ghostfolio. + + apps/client/src/app/pages/pricing/pricing-page.html + 144 + + + apps/client/src/app/pages/pricing/pricing-page.html + 270 + + + + For ambitious investors who need the full picture of their financial assets. + Для амбітних інвесторів, яким потрібна повна картина їхніх фінансових активів. + + apps/client/src/app/pages/pricing/pricing-page.html + 187 + + + + Email and Chat Support + Підтримка електронної пошти та чату + + apps/client/src/app/pages/pricing/pricing-page.html + 266 + + + + One-time payment, no auto-renewal. + Разова оплата, без автоматичного поновлення. + + apps/client/src/app/pages/pricing/pricing-page.html + 303 + + + + It’s free. + Це безкоштовно. + + apps/client/src/app/pages/pricing/pricing-page.html + 353 + + + + Hello, has shared a Portfolio with you! + Привіт, поділився з вами Портфелем! + + apps/client/src/app/pages/public/public-page.html + 5 + + + + This year + Цього року + + apps/client/src/app/pages/public/public-page.html + 42 + + + + From the beginning + З початку + + apps/client/src/app/pages/public/public-page.html + 60 + + + + Continents + Континенти + + apps/client/src/app/pages/public/public-page.html + 124 + + + + Would you like to refine your personal investment strategy? + Чи хотіли б ви удосконалити вашу особисту інвестиційну стратегію? + + apps/client/src/app/pages/public/public-page.html + 212 + + + + Ghostfolio empowers you to keep track of your wealth. + Ghostfolio надає можливість вам стежити за вашим багатством. + + apps/client/src/app/pages/public/public-page.html + 216 + + + + Registration + Реєстрація + + apps/client/src/app/components/admin-users/admin-users.html + 98 + + + libs/common/src/lib/routes/routes.ts + 281 + + + + Continue with Internet Identity + Продовжити з Інтернет-Ідентичністю + + apps/client/src/app/pages/register/register-page.html + 42 + + + + Continue with Google + Продовжити з Google + + apps/client/src/app/pages/register/register-page.html + 53 + + + + Copy to clipboard + Копіювати в буфер обміну + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 + + + + Glossary + Глосарій + + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 + + + apps/client/src/app/pages/resources/resources-page.component.ts + 45 + + + libs/common/src/lib/routes/routes.ts + 293 + + + + Guides + Посібники + + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 + + + apps/client/src/app/pages/resources/resources-page.component.ts + 34 + + + libs/common/src/lib/routes/routes.ts + 301 + + + + guides + guides + kebab-case + + libs/common/src/lib/routes/routes.ts + 296 + + + libs/common/src/lib/routes/routes.ts + 299 + + + + glossary + glossary + kebab-case + + libs/common/src/lib/routes/routes.ts + 288 + + + libs/common/src/lib/routes/routes.ts + 291 + + + + Personal Finance Tools + Інструменти особистих фінансів + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 + + + libs/common/src/lib/routes/routes.ts + 329 + + + + open-source-alternative-to + vidkrytyi-alternatyvnyi-dlia + kebab-case + + libs/common/src/lib/routes/routes.ts + 320 + + + libs/common/src/lib/routes/routes.ts + 324 + + + + Discover Open Source Alternatives for Personal Finance Tools + Відкрийте для себе альтернативи з відкритим кодом для інструментів особистих фінансів + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 + + + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + Ця сторінка огляду містить добірку інструментів особистих фінансів, порівняних з відкритою альтернативою Ghostfolio. Якщо ви цінуєте прозорість, конфіденційність даних та співпрацю в спільноті, Ghostfolio надає чудову можливість взяти під контроль ваше фінансове управління. + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 + + + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + Ознайомтеся з посиланнями нижче, щоб порівняти різні інструменти особистих фінансів з Ghostfolio. + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 + + + + Open Source Alternative to + Відкрита альтернатива для + + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 + + + + Switzerland + Швейцарія + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 + + + libs/ui/src/lib/i18n.ts + 96 + + + + Global + Глобальний + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 + + + libs/ui/src/lib/i18n.ts + 16 + + + + Alternative + Альтернатива + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 + + + + App + Додаток + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + + Budgeting + Бюджетування + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + + Community + Спільнота + + apps/client/src/app/app.component.html + 130 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 + + + apps/client/src/app/pages/features/features-page.html + 276 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 + + + + Family Office + Сімейний офіс + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 + + + + Investor + Інвестор + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 + + + + Open Source + Відкритий код + + apps/client/src/app/pages/landing/landing-page.html + 261 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 + + + + Personal Finance + Особисті фінанси + + apps/client/src/app/app.component.html + 57 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 + + + + Privacy + Конфіденційність + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 + + + + Software + Програмне забезпечення + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + + Tool + Інструмент + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 + + + + User Experience + Користувацький досвід + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 + + + + Wealth + Багатство + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + + Wealth Management + Управління багатством + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + + The Open Source Alternative to + Відкрита альтернатива до + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 + + + + This page has been archived. + Цю сторінку було архівовано. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 + + + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + Ви шукаєте відкриту альтернативу для ? Ghostfolio є потужним інструментом управління портфелем, який надає індивідуумам комплексну платформу для відстеження, аналізу та оптимізації їхніх інвестицій. Незалежно від того, чи ви досвідчений інвестор, чи тільки починаєте, Ghostfolio пропонує зручний інтерфейс користувача та широкий спектр функціональностей для допомоги вам у прийнятті обґрунтованих рішень та взятті під контроль вашого фінансового майбутнього. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 + + + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio є відкритим програмним забезпеченням (OSS), що надає економічно ефективну альтернативу для , роблячи його особливо підходящим для тих, хто обмежений у бюджеті, таких як прагнення до фінансової незалежності, раннього виходу на пенсію (FIRE). Використовуючи колективні зусилля спільноти розробників та ентузіастів особистих фінансів, Ghostfolio постійно покращує свої можливості, безпеку та користувацький досвід. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + Давайте заглибимося у детальну порівняльну таблицю Ghostfolio проти нижче, щоб отримати повне розуміння того, як Ghostfolio позиціонує себе відносно . Ми дослідимо різні аспекти, такі як функції, конфіденційність даних, ціни тощо, що дозволить вам зробити добре обдуманий вибір для ваших особистих потреб. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 + + + + Ghostfolio vs comparison table + Порівняльна таблиця Ghostfolio проти + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 + + + + Founded + Засновано + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 + + + + Origin + Походження + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 + + + + Region + Регіон + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 + + + + Available in + Доступно в + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 + + + + is Open Source Software + є відкритим програмним забезпеченням + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 + + + + ✅ Yes + ✅ Так + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 + + + + is not Open Source Software + не є відкритим програмним забезпеченням + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 + + + + ❌ No + ❌ Ні + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 + + + + Self-Hosting + Самохостинг + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 + + + + can be self-hosted + може бути self-hosted + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 + + + + cannot be self-hosted + не може бути self-hosted + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 + + + + Use anonymously + Використовувати анонімно + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 210 + + + + can be used anonymously + може використовуватися анонімно + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 + + + + cannot be used anonymously + не може використовуватися анонімно + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 + + + + Free Plan + Безкоштовний план + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 + + + + offers a free plan + пропонує безкоштовний план + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 + + + + does not offer a free plan + не пропонує безкоштовний план + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 + + + + Starting from + Починаючи з + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 + + + + Notes + Примітки + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 + + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + Зазначаємо, що інформація, надана в порівняльній таблиці Ghostfolio проти базується на нашому незалежному дослідженні та аналізі. Цей веб-сайт не пов’язаний з або будь-яким іншим продуктом, згаданим у порівнянні. Оскільки ландшафт інструментів особистих фінансів еволюціонує, важливо перевіряти будь-які конкретні деталі або зміни безпосередньо на сторінці відповідного продукту. Потрібно оновити дані? Допоможіть нам підтримувати точні дані на GitHub. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 + + + + Ready to take your investments to the next level? + Готові підняти ваші інвестиції на наступний рівень? + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + Легко відстежуйте, аналізуйте та візуалізуйте ваше багатство з Ghostfolio. + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 + + + + Resources + Ресурси + + apps/client/src/app/app.component.html + 64 + + + apps/client/src/app/components/header/header.component.html + 88 + + + apps/client/src/app/components/header/header.component.html + 301 + + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 + + + libs/common/src/lib/routes/routes.ts + 332 + + + + Membership + Членство + + libs/common/src/lib/routes/routes.ts + 31 + + + libs/ui/src/lib/membership-card/membership-card.component.html + 37 + + + + Access + Доступ + + libs/common/src/lib/routes/routes.ts + 26 + + + + My Ghostfolio + Мій Ghostfolio + + apps/client/src/app/components/header/header.component.html + 277 + + + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 + + + + Oops, authentication has failed. + Упс, аутентифікація не вдалася. + + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 + + + + Try again + Спробуйте ще раз + + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 + + + + Go back to Home Page + Повернутися на головну сторінку + + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 + + + + Do you really want to delete this account balance? + Ви дійсно хочете видалити цей рахунок? + + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 + + + + Export Activities + Експорт активності + + libs/ui/src/lib/activities-table/activities-table.component.html + 41 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 396 + + + + Export Drafts as ICS + Експортувати чернетки як ICS + + libs/ui/src/lib/activities-table/activities-table.component.html + 54 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 409 + + + + Delete Activities + Видалити активності + + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + + Draft + Чернетка + + libs/ui/src/lib/activities-table/activities-table.component.html + 145 + + + + Clone + Клонувати + + libs/ui/src/lib/activities-table/activities-table.component.html + 436 + + + + Export Draft as ICS + Експортувати чернетку як ICS + + libs/ui/src/lib/activities-table/activities-table.component.html + 446 + + + + Do you really want to delete these activities? + Ви дійсно хочете видалити ці дії? + + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 + + + + Do you really want to delete this activity? + Ви дійсно хочете видалити цю активність? + + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 + + + + Week to date + Тиждень до дати + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + WTD + WTD + + libs/ui/src/lib/assistant/assistant.component.ts + 352 + + + + Month to date + Місяць до дати + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + MTD + MTD + + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + + Year to date + Рік до дати + + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + + year + рік + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 + + + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + + years + роки + + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + + Asset Profiles + Профілі активів + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 + + + + Date Range + Діапазон дат + + libs/ui/src/lib/assistant/assistant.html + 143 + + + + Reset Filters + Скинути фільтри + + libs/ui/src/lib/assistant/assistant.html + 238 + + + + Apply Filters + Застосувати фільтри + + libs/ui/src/lib/assistant/assistant.html + 248 + + + + 50-Day Trend + Тренд на 50 днів + + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + + 200-Day Trend + Тренд на 200 днів + + libs/ui/src/lib/benchmark/benchmark.component.html + 54 + + + + Last All Time High + Останній рекордний максимум + + libs/ui/src/lib/benchmark/benchmark.component.html + 83 + + + + Change from All Time High + Зміна від Історичного Максимуму + + libs/ui/src/lib/benchmark/benchmark.component.html + 110 + + + + from ATH + від ІМ + + libs/ui/src/lib/benchmark/benchmark.component.html + 112 + + + + Market data provided by + Ринкові дані надані + + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 + + + + Savings Rate per Month + Ставка заощаджень на місяць + + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 + + + + Annual Interest Rate + Річна процентна ставка + + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 + + + + Retirement Date + Дата виходу на пенсію + + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 + + + + Projected Total Amount + Прогнозована загальна сума + + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 + + + + Deposit + Депозит + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 + + + + Interest + Відсотки + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 + + + libs/ui/src/lib/i18n.ts + 38 + + + + Savings + Заощадження + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 + + + + Details for + Деталі для + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + + Oops! Could not parse historical data. + Упс! Не вдалося отримати історичні дані. + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + + Allocation + Розподіл + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 40 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 + + + + Show all + Показати все + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 + + + + Account + Рахунок + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + + + libs/ui/src/lib/i18n.ts + 4 + + + + Asia-Pacific + Азія-Тихоокеанський регіон + + libs/ui/src/lib/i18n.ts + 5 + + + + Asset Class + Клас активів + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + + + libs/ui/src/lib/i18n.ts + 6 + + + + Asset Sub Class + Підклас активів + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + + + libs/ui/src/lib/i18n.ts + 7 + + + + Buy and sell + Купівля та продаж + + libs/ui/src/lib/i18n.ts + 8 + + + + Cancel + Скасувати + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 + + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 + + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 + + + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 + + + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 + + + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 + + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 + + + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 + + + libs/ui/src/lib/i18n.ts + 9 + + + + Core + Ядро + + libs/ui/src/lib/i18n.ts + 10 + + + + Close + Закрити + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + + + libs/ui/src/lib/i18n.ts + 11 + + + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily + Переключитися на Ghostfolio Premium або Ghostfolio з відкритим вихідним кодом легко + + libs/ui/src/lib/i18n.ts + 12 + + + + Switch to Ghostfolio Premium easily + Переключитися на Ghostfolio Premium легко + + libs/ui/src/lib/i18n.ts + 13 + + + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily + Переключитися на Ghostfolio Open Source або Ghostfolio Basic легко + + libs/ui/src/lib/i18n.ts + 14 + + + + Emergency Fund + Резервний фонд + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + + + libs/ui/src/lib/i18n.ts + 15 + + + + Grant + Грант + + libs/ui/src/lib/i18n.ts + 17 + + + + Higher Risk + Вищий ризик + + libs/ui/src/lib/i18n.ts + 18 + + + + This activity already exists. + Така активність вже існує. + + libs/ui/src/lib/i18n.ts + 19 + + + + Lower Risk + Нижчий ризик + + libs/ui/src/lib/i18n.ts + 20 + + + + Month + Місяць + + libs/ui/src/lib/i18n.ts + 21 + + + + Months + Місяців + + libs/ui/src/lib/i18n.ts + 22 + + + + Other + Інші + + libs/ui/src/lib/i18n.ts + 23 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 + + + + Get access to 80’000+ tickers from over 50 exchanges + Отримайте доступ до 80 000+ тікерів з понад 50 бірж + + libs/ui/src/lib/i18n.ts + 24 + + + + Preset + Пресет + + libs/ui/src/lib/i18n.ts + 25 + + + + Retirement Provision + Пенсійне накопичення + + libs/ui/src/lib/i18n.ts + 26 + + + + Satellite + Супутник + + libs/ui/src/lib/i18n.ts + 27 + + + + Symbol + Символ + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + + + libs/ui/src/lib/i18n.ts + 28 + + + + Tag + Тег + + libs/ui/src/lib/assistant/assistant.html + 207 + + + libs/ui/src/lib/i18n.ts + 29 + + + + Year + Рік + + libs/ui/src/lib/i18n.ts + 30 + + + + Years + Роки + + libs/ui/src/lib/i18n.ts + 31 + + + + Yes + Так + + libs/ui/src/lib/i18n.ts + 32 + + + + Buy + Купити + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + + + libs/ui/src/lib/i18n.ts + 35 + + + + Fee + Комісія + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 234 + + + libs/ui/src/lib/i18n.ts + 37 + + + + Valuable + Цінний + + libs/ui/src/lib/i18n.ts + 39 + + + + Liability + Зобов’язання + + libs/ui/src/lib/i18n.ts + 40 + + + + Sell + Продати + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + + + libs/ui/src/lib/i18n.ts + 41 + + + + Cash + Готівка + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + + + libs/ui/src/lib/i18n.ts + 53 + + + + Commodity + Товар + + libs/ui/src/lib/i18n.ts + 45 + + + + Equity + Капітал + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + + + libs/ui/src/lib/i18n.ts + 46 + + + + Fixed Income + Фіксований дохід + + libs/ui/src/lib/i18n.ts + 47 + + + + Liquidity + Ліквідність + + libs/ui/src/lib/i18n.ts + 48 + + + + Real Estate + Нерухомість + + libs/ui/src/lib/i18n.ts + 49 + + + + Bond + Облігація + + libs/ui/src/lib/i18n.ts + 52 + + + + Cryptocurrency + Криптовалюта + + libs/ui/src/lib/i18n.ts + 55 + + + + ETF + ETF + + libs/ui/src/lib/i18n.ts + 56 + + + + Mutual Fund + Взаємний фонд + + libs/ui/src/lib/i18n.ts + 57 + + + + Precious Metal + Дорогоцінний метал + + libs/ui/src/lib/i18n.ts + 58 + + + + Private Equity + Приватний капітал + + libs/ui/src/lib/i18n.ts + 59 + + + + Stock + Акція + + libs/ui/src/lib/i18n.ts + 60 + + + + Africa + Африка + + libs/ui/src/lib/i18n.ts + 67 + + + + Asia + Азія + + libs/ui/src/lib/i18n.ts + 68 + + + + Europe + Європа + + libs/ui/src/lib/i18n.ts + 69 + + + + North America + Північна Америка + + libs/ui/src/lib/i18n.ts + 70 + + + + Oceania + Океанія + + libs/ui/src/lib/i18n.ts + 71 + + + + South America + Південна Америка + + libs/ui/src/lib/i18n.ts + 72 + + + + Australia + Австралія + + libs/ui/src/lib/i18n.ts + 76 + + + + Austria + Австрія + + libs/ui/src/lib/i18n.ts + 77 + + + + Belgium + Бельгія + + libs/ui/src/lib/i18n.ts + 78 + + + + Bulgaria + Болгарія + + libs/ui/src/lib/i18n.ts + 80 + + + + Canada + Канада + + libs/ui/src/lib/i18n.ts + 81 + + + + Czech Republic + Чеська Республіка + + libs/ui/src/lib/i18n.ts + 82 + + + + Finland + Фінляндія + + libs/ui/src/lib/i18n.ts + 83 + + + + France + Франція + + libs/ui/src/lib/i18n.ts + 84 + + + + Germany + Німеччина + + libs/ui/src/lib/i18n.ts + 85 + + + + India + Індія + + libs/ui/src/lib/i18n.ts + 86 + + + + Italy + Італія + + libs/ui/src/lib/i18n.ts + 88 + + + + Japan + Японія + + libs/ui/src/lib/i18n.ts + 89 + + + + Netherlands + Нідерланди + + libs/ui/src/lib/i18n.ts + 90 + + + + New Zealand + Нова Зеландія + + libs/ui/src/lib/i18n.ts + 91 + + + + Poland + Польща + + libs/ui/src/lib/i18n.ts + 92 + + + + Romania + Румунія + + libs/ui/src/lib/i18n.ts + 93 + + + + South Africa + Південна Африка + + libs/ui/src/lib/i18n.ts + 95 + + + + Thailand + Таїланд + + libs/ui/src/lib/i18n.ts + 97 + + + + Ukraine + Україна + + libs/ui/src/lib/i18n.ts + 98 + + + + United States + Сполучені Штати + + libs/ui/src/lib/i18n.ts + 100 + + + + Extreme Fear + Екстремальний страх + + libs/ui/src/lib/i18n.ts + 103 + + + + Extreme Greed + Екстремальна жадібність + + libs/ui/src/lib/i18n.ts + 104 + + + + Neutral + Нейтрально + + libs/ui/src/lib/i18n.ts + 107 + + + + API Key + Ключ API + + libs/ui/src/lib/membership-card/membership-card.component.html + 18 + + + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + Згенерувати ключ API для постачальника даних Ghostfolio Premium для self-hosted середовищ... + + libs/ui/src/lib/membership-card/membership-card.component.html + 26 + + + + Time to add your first activity. + Час додати першу активність. + + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 + + + + No data available + Дані недоступні + + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 + + + apps/client/src/app/pages/public/public-page.html + 188 + + + libs/ui/src/lib/benchmark/benchmark.component.html + 202 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 + + + + Oops! Could not find any assets. + Упс! Не вдалося знайти жодного активу. + + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 + + + + Show more + Показати більше + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + + AI prompt has been copied to the clipboard + Запит AI скопійовано в буфер обміну + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 + + + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + + + Change + Change + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 + + + + Performance + Performance + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 + + + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 + + + + Copy portfolio data to clipboard for AI prompt + Copy portfolio data to clipboard for AI prompt + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 + + + + Copy AI prompt to clipboard for analysis + Copy AI prompt to clipboard for analysis + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 + + + + Armenia + Armenia + + libs/ui/src/lib/i18n.ts + 75 + + + + British Virgin Islands + British Virgin Islands + + libs/ui/src/lib/i18n.ts + 79 + + + + Singapore + Singapore + + libs/ui/src/lib/i18n.ts + 94 + + + + Terms and Conditions + Terms and Conditions + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 + + + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + Please keep your security token safe. If you lose it, you will not be able to recover your account. + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 + + + + I understand that if I lose my security token, I cannot recover my account + I understand that if I lose my security token, I cannot recover my account + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 + + + + Continue + Continue + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 + + + + Here is your security token. It is only visible once, please store and keep it in a safe place. + Here is your security token. It is only visible once, please store and keep it in a safe place. + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 + + + + Security token + Security token + + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 + + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 + + + + Do you really want to generate a new security token for this user? + Do you really want to generate a new security token for this user? + + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 + + + + Generate Security Token + Generate Security Token + + apps/client/src/app/components/admin-users/admin-users.html + 250 + + + + United Kingdom + United Kingdom + + libs/ui/src/lib/i18n.ts + 99 + + + + Terms of Service + Terms of Service + + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 + + + + terms-of-service + terms-of-service + kebab-case + + libs/common/src/lib/routes/routes.ts + 212 + + + libs/common/src/lib/routes/routes.ts + 215 + + + + Terms of Service + Terms of Service + + apps/client/src/app/app.component.html + 112 + + + libs/common/src/lib/routes/routes.ts + 217 + + + + and I agree to the Terms of Service. + and I agree to the Terms of Service. + + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 + + + + () is already in use. + () is already in use. + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 + + + + An error occurred while updating to (). + An error occurred while updating to (). + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 + + + + Apply + Apply + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 + + + + with API access for + with API access for + + apps/client/src/app/pages/pricing/pricing-page.html + 253 + + + + Gather Recent Historical Market Data + Gather Recent Historical Market Data + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 + + + + Gather All Historical Market Data + Gather All Historical Market Data + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 + + + + Gather Historical Market Data + Gather Historical Market Data + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 + + + + Data Gathering is off + Data Gathering is off + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 + + + + Performance Calculation + Performance Calculation + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 + + + + someone + someone + + apps/client/src/app/pages/public/public-page.component.ts + 33 + + + + Add asset to watchlist + Add asset to watchlist + + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 + + + + Watchlist + Watchlist + + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 + + + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 + + + + Do you really want to delete this item? + Do you really want to delete this item? + + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 + + + + Log out + Log out + + apps/client/src/app/components/header/header.component.html + 329 + + + + Calculations are based on delayed market data and may not be displayed in real-time. + Calculations are based on delayed market data and may not be displayed in real-time. + + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 + + + + changelog + changelog + kebab-case + + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 + + + + Demo user account has been synced. + Demo user account has been synced. + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 + + + + Sync Demo User Account + Sync Demo User Account + + apps/client/src/app/components/admin-overview/admin-overview.html + 195 + + + + Set up + Set up + + apps/client/src/app/pages/i18n/i18n-page.html + 132 + + + + No emergency fund has been set up + No emergency fund has been set up + + apps/client/src/app/pages/i18n/i18n-page.html + 134 + + + + An emergency fund has been set up + An emergency fund has been set up + + apps/client/src/app/pages/i18n/i18n-page.html + 137 + + + + Fee Ratio + Fee Ratio + + apps/client/src/app/pages/i18n/i18n-page.html + 139 + + + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + + apps/client/src/app/pages/i18n/i18n-page.html + 141 + + + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + + apps/client/src/app/pages/i18n/i18n-page.html + 145 + + + + Name + Name + + libs/ui/src/lib/benchmark/benchmark.component.html + 12 + + + + Find holding or page... + Find holding or page... + + libs/ui/src/lib/assistant/assistant.component.ts + 161 + + + + Quick Links + Quick Links + + libs/ui/src/lib/assistant/assistant.html + 56 + + + + Asset Profiles + Asset Profiles + + libs/ui/src/lib/assistant/assistant.html + 112 + + + + Live Demo + Live Demo + + apps/client/src/app/pages/landing/landing-page.html + 49 + + + apps/client/src/app/pages/landing/landing-page.html + 452 + + + libs/common/src/lib/routes/routes.ts + 231 + + + + Open Source Alternative to + Альтернатива з відкритим кодом для + + libs/common/src/lib/routes/routes.ts + 326 + + + + Single Account + Single Account + + apps/client/src/app/pages/i18n/i18n-page.html + 28 + + + + Your net worth is managed by a single account + Your net worth is managed by a single account + + apps/client/src/app/pages/i18n/i18n-page.html + 30 + + + + Your net worth is managed by ${accountsLength} accounts + Your net worth is managed by ${accountsLength} accounts + + apps/client/src/app/pages/i18n/i18n-page.html + 36 + + + + personal-finance-tools + personal-finance-tools + kebab-case + + libs/common/src/lib/routes/routes.ts + 312 + + + libs/common/src/lib/routes/routes.ts + 315 + + + libs/common/src/lib/routes/routes.ts + 323 + + + + markets + markets + kebab-case + + libs/common/src/lib/routes/routes.ts + 304 + + + libs/common/src/lib/routes/routes.ts + 307 + + + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 + + + + Get Access + Get Access + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 + + + + Learn more + Learn more + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 + + + + Limited Offer! + Limited Offer! + + apps/client/src/app/pages/pricing/pricing-page.html + 312 + + + + Get extra + Get extra + + apps/client/src/app/pages/pricing/pricing-page.html + 314 + + + + Available + Available + + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 + + + + Unavailable + Unavailable + + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 + + + + new + new + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 + + + apps/client/src/app/pages/admin/admin-page.component.ts + 56 + + + + Investment + Investment + + apps/client/src/app/pages/i18n/i18n-page.html + 15 + + + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + + apps/client/src/app/pages/i18n/i18n-page.html + 17 + + + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 24 + + + + Equity + Equity + + apps/client/src/app/pages/i18n/i18n-page.html + 41 + + + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 43 + + + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 47 + + + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 51 + + + + Fixed Income + Fixed Income + + apps/client/src/app/pages/i18n/i18n-page.html + 55 + + + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 57 + + + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 61 + + + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 66 + + + + Investment: Base Currency + Investment: Base Currency + + apps/client/src/app/pages/i18n/i18n-page.html + 72 + + + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + + apps/client/src/app/pages/i18n/i18n-page.html + 75 + + + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + + apps/client/src/app/pages/i18n/i18n-page.html + 79 + + + + Investment + Investment + + apps/client/src/app/pages/i18n/i18n-page.html + 82 + + + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + + apps/client/src/app/pages/i18n/i18n-page.html + 84 + + + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 88 + + + + start + start + kebab-case + + libs/common/src/lib/routes/routes.ts + 336 + + + libs/common/src/lib/routes/routes.ts + 337 + + + + Do you really want to generate a new security token? + Do you really want to generate a new security token? + + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 + + + + Generate + Generate + + apps/client/src/app/components/user-account-access/user-account-access.html + 43 + + + + Stocks + Stocks + + apps/client/src/app/components/markets/markets.component.ts + 52 + + + apps/client/src/app/pages/features/features-page.html + 15 + + + + Cryptocurrencies + Cryptocurrencies + + apps/client/src/app/components/markets/markets.component.ts + 53 + + + apps/client/src/app/pages/features/features-page.html + 51 + + + + + + + apps/client/src/app/components/admin-users/admin-users.html + 57 + + + + Manage Asset Profile + Manage Asset Profile + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 + + + + Alternative Investment + Alternative Investment + + libs/ui/src/lib/i18n.ts + 44 + + + + Collectible + Collectible + + libs/ui/src/lib/i18n.ts + 54 + + + + Average Unit Price + Average Unit Price + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 + + + + Account Cluster Risks + Account Cluster Risks + + apps/client/src/app/pages/i18n/i18n-page.html + 14 + + + + Asset Class Cluster Risks + Asset Class Cluster Risks + + apps/client/src/app/pages/i18n/i18n-page.html + 39 + + + + Currency Cluster Risks + Currency Cluster Risks + + apps/client/src/app/pages/i18n/i18n-page.html + 70 + + + + Economic Market Cluster Risks + Economic Market Cluster Risks + + apps/client/src/app/pages/i18n/i18n-page.html + 93 + + + + Emergency Fund + Emergency Fund + + apps/client/src/app/pages/i18n/i18n-page.html + 131 + + + + Fees + Fees + + apps/client/src/app/pages/i18n/i18n-page.html + 148 + + + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/i18n/i18n-page.html + 150 + + + + No results found... + No results found... + + libs/ui/src/lib/assistant/assistant.html + 49 + + + + Developed Markets + Developed Markets + + apps/client/src/app/pages/i18n/i18n-page.html + 96 + + + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 99 + + + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 104 + + + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 109 + + + + Emerging Markets + Emerging Markets + + apps/client/src/app/pages/i18n/i18n-page.html + 114 + + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 122 + + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + + No accounts have been set up + No accounts have been set up + + apps/client/src/app/pages/i18n/i18n-page.html + 21 + + + + Your net worth is managed by 0 accounts + Your net worth is managed by 0 accounts + + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + + Asia-Pacific + Asia-Pacific + + apps/client/src/app/pages/i18n/i18n-page.html + 152 + + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 158 + + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 162 + + + + Emerging Markets + Emerging Markets + + apps/client/src/app/pages/i18n/i18n-page.html + 167 + + + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 170 + + + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 174 + + + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 178 + + + + Europe + Europe + + apps/client/src/app/pages/i18n/i18n-page.html + 182 + + + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 184 + + + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 192 + + + + Japan + Japan + + apps/client/src/app/pages/i18n/i18n-page.html + 196 + + + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 198 + + + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 202 + + + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 206 + + + + North America + North America + + apps/client/src/app/pages/i18n/i18n-page.html + 210 + + + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 212 + + + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + + apps/client/src/app/pages/i18n/i18n-page.html + 216 + + + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + + apps/client/src/app/pages/i18n/i18n-page.html + 220 + + + + Find Ghostfolio on GitHub + Find Ghostfolio on GitHub + + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 + + + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 + + + + Join the Ghostfolio Slack community + Join the Ghostfolio Slack community + + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 + + + + Follow Ghostfolio on X (formerly Twitter) + Follow Ghostfolio on X (formerly Twitter) + + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 + + + + Send an e-mail + Send an e-mail + + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 + + + + Follow Ghostfolio on LinkedIn + Follow Ghostfolio on LinkedIn + + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 + + + + Ghostfolio is an independent & bootstrapped business + Ghostfolio is an independent & bootstrapped business + + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 + + + + Support Ghostfolio + Support Ghostfolio + + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 + + + + + diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index d94fa1090..f19e30758 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -2,6907 +2,7349 @@ - + about - snake-case + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 214 + + + faq + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 245 + + + features + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 255 + + + license + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + kebab-case - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 260 + + + pricing + kebab-case - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 270 + + + privacy-policy + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + libs/common/src/lib/routes/routes.ts + 207 - - faq - snake-case + + register + kebab-case - apps/client/src/app/app.component.ts - 77 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/core/paths.ts - 3 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + kebab-case - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 306 - - - features - snake-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 322 + + + You are using the Live Demo. - apps/client/src/app/components/header/header.component.ts - 87 + apps/client/src/app/app.component.html + 12 + + + Create Account - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/app.component.html + 13 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/pages/register/register-page.html + 27 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 2 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + + + Frequently Asked Questions (FAQ) - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + apps/client/src/app/app.component.html + 221 + + + Alias - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 4 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 + + + Grantee - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + Type - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 - - - license - snake-case - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 15 - apps/client/src/app/core/paths.ts - 5 + libs/ui/src/lib/activities-table/activities-table.component.html + 161 + + + Details - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/components/access-table/access-table.component.html + 33 - - markets - snake-case + + Revoke - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + Do you really want to revoke this granted access? - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/access-table/access-table.component.ts + 108 + + + Cash Balance - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 + + + Platform - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 + + + Cash Balances - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 - - pricing - snake-case + + Transfer Cash Balance - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Name - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 - apps/client/src/app/components/header/header.component.ts + apps/client/src/app/components/admin-market-data/admin-market-data.html 89 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + libs/ui/src/lib/activities-table/activities-table.component.html + 138 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts + libs/ui/src/lib/top-holdings/top-holdings.component.html 16 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + Total - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 55 + + + Currency - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 - - - privacy-policy - snake-case - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 - - - register - snake-case - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 - apps/client/src/app/components/header/header.component.ts - 90 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 - apps/client/src/app/core/auth.guard.ts - 55 + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + Value - apps/client/src/app/core/paths.ts - 9 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 - - - resources - snake-case - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 - apps/client/src/app/components/header/header.component.ts - 85 + libs/ui/src/lib/account-balances/account-balances.component.html + 34 - apps/client/src/app/components/header/header.component.ts - 91 + libs/ui/src/lib/activities-table/activities-table.component.html + 257 - apps/client/src/app/core/paths.ts - 10 + libs/ui/src/lib/activities-table/activities-table.component.html + 293 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 + + + + Edit + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 - apps/client/src/app/pages/features/features-page.component.ts - 30 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + libs/ui/src/lib/activities-table/activities-table.component.html + 430 + + + Delete - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/components/admin-overview/admin-overview.html + 131 - - - You are using the Live Demo. - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 - - - Create Account - apps/client/src/app/app.component.html - 13 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 - apps/client/src/app/pages/register/register-page.html - 27 + libs/ui/src/lib/account-balances/account-balances.component.html + 80 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 2 + libs/ui/src/lib/activities-table/activities-table.component.html + 457 - - - Personal Finance - apps/client/src/app/app.component.html - 57 + libs/ui/src/lib/benchmark/benchmark.component.html + 169 - - Markets + + Do you really want to delete this account? - apps/client/src/app/app.component.html - 61 + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 + + + Asset Profile - apps/client/src/app/components/header/header.component.html - 398 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 + + + Historical Market Data - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 - - Resources + + Data Source - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 - - About + + Attempts - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 + + + Created - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 + + + Finished - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 - - Blog + + Status - apps/client/src/app/app.component.html - 73 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + + + Delete Jobs - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + View Data - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + View Stacktrace - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + Delete Job - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + Details for - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + Date - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + libs/ui/src/lib/account-balances/account-balances.component.html + 12 - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + libs/ui/src/lib/activities-table/activities-table.component.html + 170 - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + Market Price - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + Currencies - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 - - - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + apps/client/src/app/pages/public/public-page.html + 88 + + + ETFs without Countries - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + ETFs without Sectors - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + Do you really want to delete this asset profile? - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Filter by... - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - - - Changelog - apps/client/src/app/app.component.html - 77 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 - - Features + + Activities Count - apps/client/src/app/app.component.html - 79 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + Historical Data - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/features/features-page.html - 5 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 - - Frequently Asked Questions (FAQ) - - apps/client/src/app/app.component.html - 83 - + + Sectors Count - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 - - License + + Countries Count - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 + + + Gather Recent Historical Market Data - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Pricing + + Gather All Historical Market Data - apps/client/src/app/app.component.html - 97 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 + + + Gather Profile Data - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 + + + Oops! Could not parse historical data. - apps/client/src/app/components/header/header.component.html - 379 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Refresh - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 - - Privacy Policy + + Gather Historical Market Data - apps/client/src/app/app.component.html - 103 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 + + + Import - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 - - - Community - apps/client/src/app/app.component.html - 121 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 + + + Sector - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 + + + Country - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 + apps/client/src/app/components/admin-users/admin-users.html + 78 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 + + + Sectors - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 - apps/client/src/app/pages/features/features-page.html - 259 + apps/client/src/app/pages/public/public-page.html + 106 - - The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + + Countries - apps/client/src/app/app.component.html - 200 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 - - - Alias - apps/client/src/app/components/access-table/access-table.component.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 11 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 - - Grantee + + Symbol Mapping - apps/client/src/app/components/access-table/access-table.component.html - 11 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 - - Type + + Scraper Configuration - apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 + + + Note - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 22 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 15 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 - libs/ui/src/lib/activities-table/activities-table.component.html - 161 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 - - Details + + Add Asset Profile - apps/client/src/app/components/access-table/access-table.component.html - 33 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 - - Revoke + + Search - apps/client/src/app/components/access-table/access-table.component.html - 75 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 - - Do you really want to revoke this granted access? + + Add Manually - apps/client/src/app/components/access-table/access-table.component.ts - 67 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 - - Cash Balance + + Name, symbol or ISIN - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 47 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 136 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 34 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 - - - Equity - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 - - Activities + + Do you really want to delete this coupon? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + Do you really want to delete this system message? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + Do you really want to flush the cache? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 + + + + Please set your system message: + + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 + + + + Version + + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + + User Count + + apps/client/src/app/components/admin-overview/admin-overview.html + 13 + + + + Activity Count + + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + + per User + + apps/client/src/app/components/admin-overview/admin-overview.html + 28 + + + + Add Currency + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 + + + + User Signup + + apps/client/src/app/components/admin-overview/admin-overview.html + 34 + + + + Read-only Mode + + apps/client/src/app/components/admin-overview/admin-overview.html + 48 + + + + System Message + + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + + Set Message + + apps/client/src/app/components/admin-overview/admin-overview.html + 94 + + + + Coupons + + apps/client/src/app/components/admin-overview/admin-overview.html + 102 + + + + Add + + apps/client/src/app/components/admin-overview/admin-overview.html + 176 + + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + + + + Housekeeping + + apps/client/src/app/components/admin-overview/admin-overview.html + 184 + + + + Flush Cache + + apps/client/src/app/components/admin-overview/admin-overview.html + 200 + + + + Add Platform + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + + Url + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 + 515 + + + apps/client/src/app/components/admin-platform/admin-platform.component.html + 38 + + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 25 + + + + Do you really want to delete this platform? + + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + + Update platform + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + + Add platform + + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + + Platforms + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + + Tags + + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 + + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 + + + Add Tag apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 + 9 + + + + Do you really want to delete this tag? + + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + + Update tag + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + + Add tag + + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + + Do you really want to delete this user? + + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + + User + + apps/client/src/app/components/admin-tag/admin-tag.component.html + 31 + + + apps/client/src/app/components/header/header.component.html + 231 + + + Engagement per Day apps/client/src/app/components/admin-users/admin-users.html - 135 + 158 + + + Last Request - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + Impersonate User - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + Delete User - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + apps/client/src/app/components/admin-users/admin-users.html + 261 - - Platform + + Compare with... - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 67 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + + Manage Benchmarks + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 + + + + Portfolio + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 + + + apps/client/src/app/components/header/header.component.html + 44 + + + apps/client/src/app/components/header/header.component.html + 258 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 + + + libs/common/src/lib/routes/routes.ts + 151 + + + + Benchmark + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 + + + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + + Current Market Mood + + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 + + + + User + + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + + About Ghostfolio + + apps/client/src/app/components/header/header.component.html + 326 + + + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 + + + + Get started + + apps/client/src/app/components/header/header.component.html + 432 + + + + Sign in + + apps/client/src/app/components/header/header.component.html + 422 + + + apps/client/src/app/components/header/header.component.ts + 259 + + + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 86 + libs/common/src/lib/routes/routes.ts + 81 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 48 + libs/common/src/lib/routes/routes.ts + 157 - - Cash Balances + + Oops! Incorrect Security Token. - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/header/header.component.ts + 274 - - - Transfer Cash Balance - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 - - Name + + Manage Activities - apps/client/src/app/components/accounts-table/accounts-table.component.html - 43 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Fear - apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + apps/client/src/app/components/home-market/home-market.component.ts + 42 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + apps/client/src/app/components/markets/markets.component.ts + 47 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + libs/ui/src/lib/i18n.ts + 105 + + + Greed - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 15 + apps/client/src/app/components/home-market/home-market.component.ts + 43 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + apps/client/src/app/components/markets/markets.component.ts + 48 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 15 + libs/ui/src/lib/i18n.ts + 106 + + + Last Days - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 15 + apps/client/src/app/components/home-market/home-market.html + 7 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + apps/client/src/app/components/markets/markets.html + 17 + + + Welcome to Ghostfolio - libs/ui/src/lib/activities-table/activities-table.component.html - 138 + apps/client/src/app/components/home-overview/home-overview.html + 11 + + + Ready to take control of your personal finances? - libs/ui/src/lib/holdings-table/holdings-table.component.html - 28 + apps/client/src/app/components/home-overview/home-overview.html + 12 + + + Setup your accounts - libs/ui/src/lib/top-holdings/top-holdings.component.html - 16 + apps/client/src/app/components/home-overview/home-overview.html + 19 + + + Get a comprehensive financial overview by adding your bank and brokerage accounts. - libs/ui/src/lib/top-holdings/top-holdings.component.html - 88 + apps/client/src/app/components/home-overview/home-overview.html + 21 - - Total + + Capture your activities - apps/client/src/app/components/accounts-table/accounts-table.component.html - 55 + apps/client/src/app/components/home-overview/home-overview.html + 28 - - Currency + + Record your investment activities to keep your portfolio up to date. - apps/client/src/app/components/accounts-table/accounts-table.component.html - 65 + apps/client/src/app/components/home-overview/home-overview.html + 30 + + + Monitor and analyze your portfolio - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + apps/client/src/app/components/home-overview/home-overview.html + 37 + + + Track your progress in real-time with comprehensive analysis and insights. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + apps/client/src/app/components/home-overview/home-overview.html + 39 + + + Setup accounts - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 46 + apps/client/src/app/components/home-overview/home-overview.html + 52 + + + Add activity - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 25 + apps/client/src/app/components/home-overview/home-overview.html + 60 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 8 + + + Total Amount - libs/ui/src/lib/activities-table/activities-table.component.html - 276 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 - - Value + + Savings Rate - apps/client/src/app/components/accounts-table/accounts-table.component.html - 171 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 + + + Security Token - apps/client/src/app/components/accounts-table/accounts-table.component.html - 206 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 53 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 + + + or - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + apps/client/src/app/pages/landing/landing-page.html + 48 - libs/ui/src/lib/account-balances/account-balances.component.html - 34 + apps/client/src/app/pages/landing/landing-page.html + 451 - libs/ui/src/lib/activities-table/activities-table.component.html - 257 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - libs/ui/src/lib/activities-table/activities-table.component.html - 293 + apps/client/src/app/pages/register/register-page.html + 31 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 74 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 + + + Sign in with Internet Identity - libs/ui/src/lib/top-holdings/top-holdings.component.html - 25 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google - libs/ui/src/lib/top-holdings/top-holdings.component.html - 102 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 - - Edit + + Stay signed in - apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 + + + Time in Market - apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Fees - apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 - libs/ui/src/lib/activities-table/activities-table.component.html - 430 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 - - Delete + + Absolute Net Performance - apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 + + + Net Performance - apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 + + + Total Assets - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + Assets - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 + + + Buying Power - apps/client/src/app/components/admin-overview/admin-overview.html - 206 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 + + + Excluded from Analysis - apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 + + + Liabilities - apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 - libs/ui/src/lib/account-balances/account-balances.component.html - 80 + apps/client/src/app/pages/features/features-page.html + 102 + + + Net Worth - libs/ui/src/lib/activities-table/activities-table.component.html - 457 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 - - Do you really want to delete this account? + + Annualized Performance - apps/client/src/app/components/accounts-table/accounts-table.component.ts - 106 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 - - Asset Profile + + Please set the amount of your emergency fund. - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 - - Historical Market Data + + Minimum Price - apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 - - Symbol + + Maximum Price - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + Quantity - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 153 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 189 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 + libs/ui/src/lib/activities-table/activities-table.component.html + 186 + + + Report Data Glitch apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + 446 - - Data Source + + Are you an ambitious investor who needs the full picture? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 + + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 + + + Portfolio Summary - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + apps/client/src/app/pages/pricing/pricing-page.html + 44 - - - Attempts - apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + apps/client/src/app/pages/pricing/pricing-page.html + 205 - - Created + + Portfolio Allocations - apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 - - - Finished - apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + apps/client/src/app/pages/features/features-page.html + 161 - - - Status - apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + apps/client/src/app/pages/pricing/pricing-page.html + 48 - - - Delete Jobs - apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + apps/client/src/app/pages/pricing/pricing-page.html + 209 - - View Data + + Performance Benchmarks - apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 - - - View Stacktrace - apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + apps/client/src/app/pages/pricing/pricing-page.html + 52 - - - Delete Job - apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + apps/client/src/app/pages/pricing/pricing-page.html + 213 - - Details for + + FIRE Calculator - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 2 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 - - - Date - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + apps/client/src/app/pages/pricing/pricing-page.html + 56 - libs/ui/src/lib/account-balances/account-balances.component.html - 12 + apps/client/src/app/pages/pricing/pricing-page.html + 217 + + + Professional Data Provider - libs/ui/src/lib/activities-table/activities-table.component.html - 170 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 6 + apps/client/src/app/pages/pricing/pricing-page.html + 237 - - Market Price + + and more Features... - apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + apps/client/src/app/pages/pricing/pricing-page.html + 72 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 26 + apps/client/src/app/pages/pricing/pricing-page.html + 261 - - Cancel - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 - + + Get the tools to effectively manage your finances and refine your personal investment strategy. - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 + + + Skip - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + Upgrade Plan - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + apps/client/src/app/components/header/header.component.html + 193 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 70 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + apps/client/src/app/pages/pricing/pricing-page.html + 299 + + + Today - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/pages/public/public-page.html + 24 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + libs/ui/src/lib/assistant/assistant.component.ts + 348 - - Save + + YTD - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + libs/ui/src/lib/assistant/assistant.component.ts + 360 + + + 1Y - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + 5Y - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + Max - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + libs/ui/src/lib/assistant/assistant.component.ts + 401 + + + Grant access - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 7 + + + Public apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 + 25 + + + Granted Access - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 + apps/client/src/app/components/user-account-access/user-account-access.html + 57 + + + Please enter your coupon code. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 + + + Could not redeem coupon code - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 - - Currencies + + Coupon code has been redeemed - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 - - ETFs without Countries + + Reload - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 - - ETFs without Sectors + + per year - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 + + + apps/client/src/app/pages/pricing/pricing-page.html + 283 - - Do you really want to delete this asset profile? + + Try Premium - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 - - Filter by... + + Redeem Coupon - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 - - Asset Class + + Auto - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 + + + Do you really want to remove this sign in method? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 + + + Presenter View - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 + + + Protection for sensitive information like absolute performances and quantity values - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 + + + Base Currency - libs/ui/src/lib/assistant/assistant.html - 166 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 - - Asset Sub Class + + Language - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 + + + Locale apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 + 422 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 + + + + Date and number format + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 + + + Appearance - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 + + + Light - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 - - First Activity + + Dark - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 + + + Zen Mode - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + apps/client/src/app/pages/features/features-page.html + 246 + + + Distraction-free experience for turbulent times - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 - - Activities Count + + Biometric Authentication - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 - - Historical Data + + Sign in with fingerprint - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 + + + Experimental Features - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 - - Sectors Count + + Sneak peek at upcoming functionality - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 - - Countries Count + + User ID - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 + + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 - - Gather Recent Data + + Export Data - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 - - Gather All Data + + This feature is currently unavailable. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + apps/client/src/app/core/http-response.interceptor.ts + 55 - - Gather Profile Data + + Please try again later. - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + apps/client/src/app/core/http-response.interceptor.ts + 57 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 + apps/client/src/app/core/http-response.interceptor.ts + 88 - - - Oops! Could not parse historical data. - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 - - Refresh + + Oops! Something went wrong. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + apps/client/src/app/core/http-response.interceptor.ts + 86 - - - Gather Historical Data - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 - - Import + + Okay - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 153 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 186 + apps/client/src/app/core/http-response.interceptor.ts + 89 + + + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 + + + About - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + apps/client/src/app/app.component.html 70 - - - Sector - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + apps/client/src/app/components/header/header.component.html + 124 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + apps/client/src/app/components/header/header.component.html + 375 - - - Country - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/components/admin-users/admin-users.html + libs/common/src/lib/routes/routes.ts + 220 + + + + Changelog + + apps/client/src/app/app.component.html 77 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 - - - Sectors - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + libs/common/src/lib/routes/routes.ts + 185 + + + License - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + apps/client/src/app/app.component.html + 89 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + apps/client/src/app/pages/about/license/license-page.html + 4 - apps/client/src/app/pages/public/public-page.html - 106 + libs/common/src/lib/routes/routes.ts + 193 - - Countries + + Privacy Policy - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + apps/client/src/app/app.component.html + 105 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + libs/common/src/lib/routes/routes.ts + 209 - - Benchmark + + Our - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 - - Symbol Mapping + + Discover other exciting Open Source Software projects - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 - - Scraper Configuration + + Visit - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 - - Note + + Accounts - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 78 + apps/client/src/app/components/admin-users/admin-users.html + 115 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + apps/client/src/app/components/header/header.component.html + 58 - - - Add Asset Profile - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 7 + apps/client/src/app/components/header/header.component.html + 268 - - - Search - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 - - - Add Manually - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/pages/accounts/accounts-page.html + 4 - - - Name, symbol or ISIN - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 29 + libs/common/src/lib/routes/routes.ts + 69 + + + Oops, cash balance transfer has failed. - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 - - Please add a currency: + + Update account - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 - - is an invalid currency! + + Add account - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - - Do you really want to delete this coupon? + + Account ID - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 - - Do you really want to delete this currency? + + From - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - Do you really want to delete this system message? + + To - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 - - Do you really want to flush the cache? + + Transfer - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Please set your system message: + + Admin Control - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/components/header/header.component.html + 74 - - - Version - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/components/header/header.component.html + 289 - - - User Count - apps/client/src/app/components/admin-overview/admin-overview.html - 13 + libs/common/src/lib/routes/routes.ts + 64 - - Activity Count + + Market Data - apps/client/src/app/components/admin-overview/admin-overview.html - 19 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - - - per User - apps/client/src/app/components/admin-overview/admin-overview.html - 28 + libs/common/src/lib/routes/routes.ts + 51 - - Exchange Rates + + Settings - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - - - Add Currency - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 22 + libs/common/src/lib/routes/routes.ts + 34 - apps/client/src/app/components/admin-overview/admin-overview.html - 105 + libs/common/src/lib/routes/routes.ts + 56 - - User Signup + + Users - apps/client/src/app/components/admin-overview/admin-overview.html - 111 + libs/common/src/lib/routes/routes.ts + 61 - - Read-only Mode + + Overview - apps/client/src/app/components/admin-overview/admin-overview.html - 125 + apps/client/src/app/components/header/header.component.html + 30 - - - System Message - apps/client/src/app/components/admin-overview/admin-overview.html - 149 + apps/client/src/app/components/header/header.component.html + 248 - - - Set Message - apps/client/src/app/components/admin-overview/admin-overview.html - 171 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 - - - Coupons - apps/client/src/app/components/admin-overview/admin-overview.html - 179 + apps/client/src/app/pages/admin/admin-page.component.ts + 48 - - - Add - apps/client/src/app/components/admin-overview/admin-overview.html - 239 + apps/client/src/app/pages/resources/resources-page.component.ts + 30 - libs/ui/src/lib/account-balances/account-balances.component.html - 93 + libs/common/src/lib/routes/routes.ts + 113 + + + libs/common/src/lib/routes/routes.ts + 170 - - Housekeeping + + Blog - apps/client/src/app/components/admin-overview/admin-overview.html - 247 + apps/client/src/app/app.component.html + 74 + + + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 - - - Flush Cache - apps/client/src/app/components/admin-overview/admin-overview.html - 251 + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 - - - Add Platform - apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 - - - Url - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 25 + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 - - - Accounts - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 - apps/client/src/app/components/header/header.component.html - 54 + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 - apps/client/src/app/components/header/header.component.html - 263 + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 - apps/client/src/app/pages/accounts/accounts-page.html - 4 + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 - - - Do you really want to delete this platform? - apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 - - - Update platform - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 8 + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 - - - Add platform - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 10 + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 - - - Platforms - apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 - - - Tags - apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 - - - Add Tag - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 - - - Do you really want to delete this tag? - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/blog/blog-page.html + 5 - - - Update tag - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + libs/common/src/lib/routes/routes.ts + 225 - - Add tag + + Discover the latest Ghostfolio updates and insights on personal finance - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/blog/blog-page.html + 7 - - Do you really want to delete this user? + + As you are already logged in, you cannot access the demo account. - apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + apps/client/src/app/pages/demo/demo-page.component.ts + 35 - - User + + Frequently Asked Questions (FAQ) - apps/client/src/app/components/admin-users/admin-users.html - 29 + apps/client/src/app/app.component.html + 83 - - - Registration - apps/client/src/app/components/admin-users/admin-users.html - 97 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 - - - Engagement per Day - apps/client/src/app/components/admin-users/admin-users.html - 157 + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 - - - Last Request - apps/client/src/app/components/admin-users/admin-users.html - 202 + libs/common/src/lib/routes/routes.ts + 251 - - Impersonate User + + Features - apps/client/src/app/components/admin-users/admin-users.html - 239 + apps/client/src/app/app.component.html + 79 - - - Delete User - apps/client/src/app/components/admin-users/admin-users.html - 251 + apps/client/src/app/components/header/header.component.html + 361 - - - Performance - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 + apps/client/src/app/pages/features/features-page.html + 5 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + libs/common/src/lib/routes/routes.ts + 256 - - Compare with... + + Check out the numerous features of Ghostfolio to manage your wealth - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 18 + apps/client/src/app/pages/features/features-page.html + 7 - - Manage Benchmarks + + ETFs - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 35 + apps/client/src/app/pages/features/features-page.html + 25 - - Portfolio + + Bonds - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 + apps/client/src/app/pages/features/features-page.html + 38 + + + Wealth Items - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 + apps/client/src/app/pages/features/features-page.html + 76 + + + Import and Export - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + apps/client/src/app/pages/features/features-page.html + 116 - - Benchmark + + Multi-Accounts - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + apps/client/src/app/pages/features/features-page.html + 127 - - Current Market Mood + + Portfolio Calculations - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 + apps/client/src/app/pages/features/features-page.html + 141 - - Overview + + Dark Mode - apps/client/src/app/components/header/header.component.html - 28 + apps/client/src/app/pages/features/features-page.html + 233 + + + Market Mood - apps/client/src/app/components/header/header.component.html - 245 + apps/client/src/app/pages/features/features-page.html + 215 - - Portfolio + + Static Analysis - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/pages/features/features-page.html + 179 + + + Multi-Language - apps/client/src/app/components/header/header.component.html - 255 + apps/client/src/app/pages/features/features-page.html + 259 - - Admin Control + + Open Source Software - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/pages/features/features-page.html + 295 + + + Get Started - apps/client/src/app/components/header/header.component.html - 279 + apps/client/src/app/pages/features/features-page.html + 320 - - - Me - apps/client/src/app/components/header/header.component.html - 211 + apps/client/src/app/pages/public/public-page.html + 220 - - User + + Holdings - apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - apps/client/src/app/components/header/header.component.html - 229 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - - - My Ghostfolio - apps/client/src/app/components/header/header.component.html - 270 + apps/client/src/app/pages/public/public-page.html + 70 - - - About Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + libs/common/src/lib/routes/routes.ts + 90 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + libs/common/src/lib/routes/routes.ts + 167 - - Sign in + + Summary - apps/client/src/app/components/header/header.component.html - 412 + apps/client/src/app/components/home-summary/home-summary.html + 2 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + libs/common/src/lib/routes/routes.ts + 105 - - Get started + + Markets - apps/client/src/app/components/header/header.component.html - 422 + apps/client/src/app/app.component.html + 61 - - - Sign in - apps/client/src/app/app-routing.module.ts - 150 + apps/client/src/app/components/header/header.component.html + 408 - apps/client/src/app/components/header/header.component.ts - 230 + apps/client/src/app/components/home-market/home-market.html + 2 - - - Oops! Incorrect Security Token. - apps/client/src/app/components/header/header.component.ts - 245 + apps/client/src/app/components/markets/markets.html + 2 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 - - - Manage Activities - apps/client/src/app/components/home-holdings/home-holdings.html - 63 + apps/client/src/app/pages/resources/resources-page.component.ts + 40 - - - Fear - apps/client/src/app/components/home-market/home-market.component.ts - 27 + libs/common/src/lib/routes/routes.ts + 95 - libs/ui/src/lib/i18n.ts - 98 + libs/common/src/lib/routes/routes.ts + 100 - - - Greed - apps/client/src/app/components/home-market/home-market.component.ts - 28 + libs/common/src/lib/routes/routes.ts + 261 - libs/ui/src/lib/i18n.ts - 99 + libs/common/src/lib/routes/routes.ts + 309 - - Last Days + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - apps/client/src/app/components/home-market/home-market.html - 7 + apps/client/src/app/pages/i18n/i18n-page.html + 5 - - Welcome to Ghostfolio + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - apps/client/src/app/components/home-overview/home-overview.html - 7 + apps/client/src/app/pages/i18n/i18n-page.html + 10 - - Ready to take control of your personal finances? + + Open Source Wealth Management Software - apps/client/src/app/components/home-overview/home-overview.html - 8 + apps/client/src/app/pages/i18n/i18n-page.html + 224 - - Setup your accounts + + Manage your wealth like a boss - apps/client/src/app/components/home-overview/home-overview.html - 15 + apps/client/src/app/pages/landing/landing-page.html + 6 - - Get a comprehensive financial overview by adding your bank and brokerage accounts. + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - apps/client/src/app/components/home-overview/home-overview.html - 17 + apps/client/src/app/pages/landing/landing-page.html + 10 - - Capture your activities + + Get Started - apps/client/src/app/components/home-overview/home-overview.html - 24 + apps/client/src/app/pages/landing/landing-page.html + 42 - - - Record your investment activities to keep your portfolio up to date. - apps/client/src/app/components/home-overview/home-overview.html - 26 + apps/client/src/app/pages/landing/landing-page.html + 447 - - - Monitor and analyze your portfolio - apps/client/src/app/components/home-overview/home-overview.html - 33 + apps/client/src/app/pages/pricing/pricing-page.html + 351 - - - Track your progress in real-time with comprehensive analysis and insights. - apps/client/src/app/components/home-overview/home-overview.html - 35 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - - Setup accounts + + Monthly Active Users - apps/client/src/app/components/home-overview/home-overview.html - 44 + apps/client/src/app/pages/landing/landing-page.html + 70 - - Add activity + + Stars on GitHub - apps/client/src/app/components/home-overview/home-overview.html - 52 + apps/client/src/app/pages/landing/landing-page.html + 88 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 8 + apps/client/src/app/pages/open/open-page.html + 103 - - Summary + + Pulls on Docker Hub - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/pages/landing/landing-page.html + 106 - - - Total Amount - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + apps/client/src/app/pages/open/open-page.html + 117 - - Savings Rate + + As seen in - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + apps/client/src/app/pages/landing/landing-page.html + 115 - - Security Token - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - + + Protect your assets. Refine your personal investment strategy. - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/pages/landing/landing-page.html + 226 - - or + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 35 + apps/client/src/app/pages/landing/landing-page.html + 230 + + + 360° View - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + apps/client/src/app/pages/landing/landing-page.html + 240 + + + Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 47 + 243 + + + Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 450 + 251 + + + Use Ghostfolio anonymously and own your financial data. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 + apps/client/src/app/pages/landing/landing-page.html + 254 + + + Benefit from continuous improvements through a strong community. - apps/client/src/app/pages/register/register-page.html - 30 + apps/client/src/app/pages/landing/landing-page.html + 264 + + + Why Ghostfolio? - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + apps/client/src/app/pages/landing/landing-page.html + 272 - - Sign in with Internet Identity + + Ghostfolio is for you if you are... - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 + apps/client/src/app/pages/landing/landing-page.html + 274 - - Sign in with Google + + trading stocks, ETFs or cryptocurrencies on multiple platforms - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 + apps/client/src/app/pages/landing/landing-page.html + 280 - - Stay signed in + + pursuing a buy & hold strategy - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 286 - - Time in Market + + interested in getting insights of your portfolio composition - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 + apps/client/src/app/pages/landing/landing-page.html + 291 - - Buy + + valuing privacy and data ownership - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + apps/client/src/app/pages/landing/landing-page.html + 296 - - Sell + + into minimalism - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + apps/client/src/app/pages/landing/landing-page.html + 299 - - Investment + + caring about diversifying your financial resources - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 + apps/client/src/app/pages/landing/landing-page.html + 303 + + + interested in financial independence - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 + apps/client/src/app/pages/landing/landing-page.html + 307 - - Absolute Gross Performance + + saying no to spreadsheets in - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 + apps/client/src/app/pages/landing/landing-page.html + 311 - - Fees + + still reading this list - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + apps/client/src/app/pages/landing/landing-page.html + 314 + + + Learn more about Ghostfolio - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 84 + apps/client/src/app/pages/landing/landing-page.html + 319 + + + What our users are saying - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + apps/client/src/app/pages/landing/landing-page.html + 328 - - Absolute Net Performance + + Members from around the globe are using Ghostfolio Premium - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 + apps/client/src/app/pages/landing/landing-page.html + 367 - - Net Performance + + How does Ghostfolio work? - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/pages/landing/landing-page.html + 384 - - Total Assets + + Get started in only 3 steps - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 143 + apps/client/src/app/pages/landing/landing-page.html + 386 - - Valuables + + Sign up anonymously* - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 + apps/client/src/app/pages/landing/landing-page.html + 392 - - Emergency Fund + + * no e-mail address nor credit card required - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 + apps/client/src/app/pages/landing/landing-page.html + 394 + + + Add any of your historical transactions - apps/client/src/app/pages/features/features-page.html - 89 + apps/client/src/app/pages/landing/landing-page.html + 406 + + + Get valuable insights of your portfolio composition - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 + apps/client/src/app/pages/landing/landing-page.html + 418 - - Cash + + Are you ready? - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + apps/client/src/app/pages/landing/landing-page.html + 432 - - Assets + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + apps/client/src/app/pages/open/open-page.html + 7 - - Buying Power + + (Last 24 hours) - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + apps/client/src/app/pages/open/open-page.html + 37 - - Excluded from Analysis + + Active Users - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + apps/client/src/app/pages/open/open-page.html + 40 + + + apps/client/src/app/pages/open/open-page.html + 62 - - Liabilities + + (Last 30 days) - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + apps/client/src/app/pages/open/open-page.html + 48 - apps/client/src/app/pages/features/features-page.html - 102 + apps/client/src/app/pages/open/open-page.html + 59 - - Net Worth + + New Users - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + apps/client/src/app/pages/open/open-page.html + 51 - - Annualized Performance + + Users in Slack community - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 + apps/client/src/app/pages/open/open-page.html + 75 - - Interest + + Contributors on GitHub - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/open/open-page.html + 89 - - Dividend + + (Last 90 days) - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 + apps/client/src/app/pages/open/open-page.html + 127 + + + Uptime - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 + apps/client/src/app/pages/open/open-page.html + 132 + + + Activities - apps/client/src/app/pages/features/features-page.html + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html 63 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 - - - Please set the amount of your emergency fund. - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 - - - Change - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - - - Average Unit Price - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + apps/client/src/app/components/admin-users/admin-users.html + 136 - - - Minimum Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + 226 - - - Maximum Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + 337 - - - Quantity - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + libs/common/src/lib/routes/routes.ts + 128 + + + Do you really want to delete these activities? - libs/ui/src/lib/activities-table/activities-table.component.html - 186 + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 - - Report Data Glitch + + Update activity - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 - - Are you an ambitious investor who needs the full picture? + + Stocks, ETFs, bonds, cryptocurrencies, commodities - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 65 - - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + + One-time fee, annual account fees - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - Portfolio Summary + + Distribution of corporate earnings - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 24 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 + + + Revenue for lending out money - apps/client/src/app/pages/pricing/pricing-page.html - 57 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 + + + Mortgages, personal loans, credit cards - apps/client/src/app/pages/pricing/pricing-page.html - 213 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 - - Portfolio Allocations + + Luxury items, real estate, private companies - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 28 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 + + + Update Cash Balance - apps/client/src/app/pages/features/features-page.html - 161 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 + + + Unit Price - apps/client/src/app/pages/pricing/pricing-page.html - 61 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 - apps/client/src/app/pages/pricing/pricing-page.html - 217 + libs/ui/src/lib/activities-table/activities-table.component.html + 210 - - Performance Benchmarks + + Import Activities - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 32 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 - apps/client/src/app/pages/pricing/pricing-page.html - 65 + libs/ui/src/lib/activities-table/activities-table.component.html + 9 - apps/client/src/app/pages/pricing/pricing-page.html - 221 + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - - FIRE Calculator + + Import Dividends - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 36 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 129 - apps/client/src/app/pages/pricing/pricing-page.html - 69 + libs/ui/src/lib/activities-table/activities-table.component.html + 29 - apps/client/src/app/pages/pricing/pricing-page.html - 225 + libs/ui/src/lib/activities-table/activities-table.component.html + 383 - - Professional Data Provider - - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 40 - + + Importing data... - apps/client/src/app/pages/pricing/pricing-page.html - 240 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 167 - - and more Features... + + Import has been completed - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 44 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 176 + + + Validating data... - apps/client/src/app/pages/pricing/pricing-page.html - 85 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 + + + Select Holding - apps/client/src/app/pages/pricing/pricing-page.html - 252 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 - - Get the tools to effectively manage your finances and refine your personal investment strategy. + + Select File - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 22 - - Skip + + Holding - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 - - - Upgrade Plan - apps/client/src/app/components/header/header.component.html - 185 + libs/ui/src/lib/assistant/assistant.html + 179 + + + Load Dividends - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 + + + Choose or drop a file here - apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 + + + The following file formats are supported: - apps/client/src/app/pages/pricing/pricing-page.html - 288 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 - - Today + + Select Dividends - apps/client/src/app/components/toggle/toggle.component.ts - 21 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 + + + Select Activities - libs/ui/src/lib/assistant/assistant.component.ts - 221 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 - - YTD + + Back - apps/client/src/app/components/toggle/toggle.component.ts - 22 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 - - 1Y + + Allocations - apps/client/src/app/components/toggle/toggle.component.ts - 23 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - - - 5Y - apps/client/src/app/components/toggle/toggle.component.ts - 24 + libs/common/src/lib/routes/routes.ts + 133 + + + Proportion of Net Worth - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 - - Max + + By Platform - apps/client/src/app/components/toggle/toggle.component.ts - 25 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 44 + + + By Currency - libs/ui/src/lib/assistant/assistant.component.ts - 260 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 - - Grant access + + By Asset Class - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 - - Public + + By Holding - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 25 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 - - Granted Access + + By Sector - apps/client/src/app/components/user-account-access/user-account-access.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 - - Please enter your coupon code: + + By Continent - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 - - Could not redeem coupon code + + By Market - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + apps/client/src/app/pages/portfolio/allocations/allocations-page.html 175 - - Coupon code has been redeemed + + Regions - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 + + + apps/client/src/app/pages/public/public-page.html + 143 - - Reload + + Developed Markets - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 + + + apps/client/src/app/pages/public/public-page.html + 160 - - per year + + Emerging Markets - apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 - apps/client/src/app/pages/pricing/pricing-page.html - 274 + apps/client/src/app/pages/public/public-page.html + 169 - - Try Premium + + Other Markets - apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 + + + apps/client/src/app/pages/public/public-page.html + 178 - - Redeem Coupon + + By Account - apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 - - Auto + + By ETF Provider - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 - - Do you really want to remove this sign in method? + + By Country - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 - - Settings + + Analysis - apps/client/src/app/components/user-account-settings/user-account-settings.html + apps/client/src/app/pages/portfolio/analysis/analysis-page.html 2 - - - Presenter View - apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + libs/common/src/lib/routes/routes.ts + 138 - - Protection for sensitive information like absolute performances and quantity values + + Dividend - apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 + + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 - - - Base Currency - apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + apps/client/src/app/pages/features/features-page.html + 63 - - - Language - apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 - - - Locale - apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 - - - Date and number format - apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + libs/ui/src/lib/i18n.ts + 36 - - Appearance + + Deposit - apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 - - Auto + + Monthly - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 - - Light + + Yearly - apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 - - Dark + + Top - apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 - - Zen Mode + + Bottom - apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + + Portfolio Evolution - apps/client/src/app/pages/features/features-page.html - 191 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 - - Distraction-free experience for turbulent times + + Investment Timeline - apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 - - Biometric Authentication + + Current Streak - apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 - - Sign in with fingerprint + + Longest Streak - apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 - - Experimental Features + + Dividend Timeline - apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 - - Sneak peek at upcoming functionality + + FIRE - apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 4 - - User ID + + Calculator - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 45 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 + + + 4% Rule - apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 - - Export Data + + Currency Cluster Risks - apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 - - This feature is currently unavailable. + + Account Cluster Risks - apps/client/src/app/core/http-response.interceptor.ts - 53 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 - - Please try again later. + + Holdings - apps/client/src/app/core/http-response.interceptor.ts - 55 + libs/ui/src/lib/assistant/assistant.html + 82 + + + Pricing - apps/client/src/app/core/http-response.interceptor.ts - 80 + apps/client/src/app/app.component.html + 99 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + apps/client/src/app/components/header/header.component.html + 105 - - - Oops! Something went wrong. - apps/client/src/app/core/http-response.interceptor.ts - 78 + apps/client/src/app/components/header/header.component.html + 313 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + apps/client/src/app/components/header/header.component.html + 389 - - - Okay - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts + 13 - apps/client/src/app/core/http-response.interceptor.ts - 81 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + libs/common/src/lib/routes/routes.ts + 271 - - About + + Pricing Plans - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 + apps/client/src/app/pages/pricing/pricing-page.html + 4 + + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. - apps/client/src/app/pages/about/about-page.component.ts - 44 + apps/client/src/app/pages/pricing/pricing-page.html + 7 + + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 14 - - Changelog + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/pages/pricing/pricing-page.html + 26 + + + Unlimited Transactions - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 32 - - - License - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/pages/pricing/pricing-page.html + 121 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 193 - - Privacy Policy + + Unlimited Accounts - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/pricing/pricing-page.html + 36 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 125 - - - Our - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + apps/client/src/app/pages/pricing/pricing-page.html + 197 - - Discover other exciting Open Source Software projects + + Portfolio Performance - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 40 - - - Visit - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/pricing/pricing-page.html + 129 - - - Accounts - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/pages/pricing/pricing-page.html + 201 - - Oops, cash balance transfer has failed. + + Data Import and Export - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/pages/pricing/pricing-page.html + 60 - - - Update account - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/pages/pricing/pricing-page.html + 133 - - - Add account - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/pages/pricing/pricing-page.html + 221 - - Account ID + + Community Support - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 96 + apps/client/src/app/pages/pricing/pricing-page.html + 77 - - From + + Self-hosted, update manually. - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/pricing/pricing-page.html + 81 - - To + + Free - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/pricing/pricing-page.html + 83 + + + apps/client/src/app/pages/pricing/pricing-page.html + 146 - - Transfer + + For new investors who are just getting started with trading. - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/pricing/pricing-page.html + 116 - - Admin Control + + Fully managed Ghostfolio cloud offering. - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/pages/pricing/pricing-page.html + 144 - - - Market Data - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/pages/pricing/pricing-page.html + 270 + + + For ambitious investors who need the full picture of their financial assets. - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + apps/client/src/app/pages/pricing/pricing-page.html + 187 - - Settings + + Email and Chat Support - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 + apps/client/src/app/pages/pricing/pricing-page.html + 266 + + + Renew Plan - apps/client/src/app/pages/admin/admin-page.component.ts - 32 + apps/client/src/app/components/header/header.component.html + 191 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts + apps/client/src/app/components/user-account-membership/user-account-membership.html 18 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + apps/client/src/app/pages/pricing/pricing-page.html + 297 - - Users + + One-time payment, no auto-renewal. - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/pages/pricing/pricing-page.html + 303 + + + It’s free. - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + apps/client/src/app/pages/pricing/pricing-page.html + 353 - - Overview + + Hello, has shared a Portfolio with you! - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/pages/public/public-page.html + 5 + + + Continents - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/pages/public/public-page.html + 124 + + + Ghostfolio empowers you to keep track of your wealth. - apps/client/src/app/pages/resources/resources-page.component.ts - 16 + apps/client/src/app/pages/public/public-page.html + 216 + + + Registration - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + apps/client/src/app/components/admin-users/admin-users.html + 98 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + libs/common/src/lib/routes/routes.ts + 281 - - Blog + + Continue with Internet Identity - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/pages/register/register-page.html + 42 - - Discover the latest Ghostfolio updates and insights on personal finance + + Continue with Google - apps/client/src/app/pages/blog/blog-page.html - 7 + apps/client/src/app/pages/register/register-page.html + 53 - - As you are already logged in, you cannot access the demo account. + + Copy to clipboard - apps/client/src/app/pages/demo/demo-page.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 - - Frequently Asked Questions (FAQ) + + Personal Finance Tools - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + libs/common/src/lib/routes/routes.ts + 329 - - Frequently Asked Questions (FAQ) - - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 - + + open-source-alternative-to + kebab-case - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + libs/common/src/lib/routes/routes.ts + 320 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 + libs/common/src/lib/routes/routes.ts + 324 - - Features + + Discover Open Source Alternatives for Personal Finance Tools - apps/client/src/app/app-routing.module.ts - 74 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 - - Check out the numerous features of Ghostfolio to manage your wealth + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - apps/client/src/app/pages/features/features-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 - - Stocks + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. - apps/client/src/app/pages/features/features-page.html - 15 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 - - ETFs + + Open Source Alternative to - apps/client/src/app/pages/features/features-page.html - 25 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 - - Bonds + + The Open Source Alternative to - apps/client/src/app/pages/features/features-page.html - 38 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 - - Cryptocurrencies + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - apps/client/src/app/pages/features/features-page.html - 51 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 - - Wealth Items + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - apps/client/src/app/pages/features/features-page.html - 76 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 - - Import and Export + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - apps/client/src/app/pages/features/features-page.html - 115 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - Multi-Accounts + + Ghostfolio vs comparison table - apps/client/src/app/pages/features/features-page.html - 127 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 - - Portfolio Calculations + + Founded - apps/client/src/app/pages/features/features-page.html - 141 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 - - Dark Mode + + Origin - apps/client/src/app/pages/features/features-page.html - 178 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 - - Market Mood + + Region - apps/client/src/app/pages/features/features-page.html - 206 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 - - Static Analysis + + Available in - apps/client/src/app/pages/features/features-page.html - 225 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 - - Multi-Language + + ✅ Yes - apps/client/src/app/pages/features/features-page.html - 242 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 - - - Open Source Software - apps/client/src/app/pages/features/features-page.html - 278 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 - - - Get Started - apps/client/src/app/pages/features/features-page.html - 303 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 - apps/client/src/app/pages/public/public-page.html - 220 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 - - - Holdings - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 - apps/client/src/app/pages/home/home-page.component.ts - 42 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 - apps/client/src/app/pages/zen/zen-page.component.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 - - Summary + + ❌ No - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 - apps/client/src/app/pages/home/home-page.component.ts - 47 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 - - - Markets - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 - apps/client/src/app/pages/markets/markets-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 - apps/client/src/app/pages/resources/resources-page.component.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + + Self-Hosting - apps/client/src/app/pages/i18n/i18n-page.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + + Use anonymously - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 210 - - Open Source Wealth Management Software + + Free Plan - apps/client/src/app/pages/i18n/i18n-page.html - 14 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 - - Manage your wealth like a boss + + Starting from - apps/client/src/app/pages/landing/landing-page.html - 5 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - apps/client/src/app/pages/landing/landing-page.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 - - Get Started + + Notes - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 + + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - apps/client/src/app/pages/pricing/pricing-page.html - 324 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - Live Demo + + Ready to take your investments to the next level? - apps/client/src/app/pages/landing/landing-page.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 + + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 - - Monthly Active Users + + Switzerland - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 + + + libs/ui/src/lib/i18n.ts + 96 - - Stars on GitHub + + Global - apps/client/src/app/pages/landing/landing-page.html - 88 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - apps/client/src/app/pages/open/open-page.html - 103 + libs/ui/src/lib/i18n.ts + 16 - - Pulls on Docker Hub + + Resources - apps/client/src/app/pages/landing/landing-page.html - 106 + apps/client/src/app/app.component.html + 64 - apps/client/src/app/pages/open/open-page.html - 117 + apps/client/src/app/components/header/header.component.html + 88 - - - As seen in - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/components/header/header.component.html + 301 - - - Protect your assets. Refine your personal investment strategy. - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 - - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - apps/client/src/app/pages/landing/landing-page.html - 229 + libs/common/src/lib/routes/routes.ts + 332 - - 360° View + + Membership - apps/client/src/app/pages/landing/landing-page.html - 240 + libs/common/src/lib/routes/routes.ts + 31 - - - Get the full picture of your personal finances across multiple platforms. - apps/client/src/app/pages/landing/landing-page.html - 242 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 - - Web3 Ready + + Access - apps/client/src/app/pages/landing/landing-page.html - 251 + libs/common/src/lib/routes/routes.ts + 26 - - Use Ghostfolio anonymously and own your financial data. + + My Ghostfolio - apps/client/src/app/pages/landing/landing-page.html - 253 + apps/client/src/app/components/header/header.component.html + 277 - - - Open Source - apps/client/src/app/pages/landing/landing-page.html - 261 + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 - - Benefit from continuous improvements through a strong community. + + Oops, authentication has failed. - apps/client/src/app/pages/landing/landing-page.html - 263 + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 - - Why Ghostfolio? + + Try again - apps/client/src/app/pages/landing/landing-page.html - 272 + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 - - Ghostfolio is for you if you are... + + Go back to Home Page - apps/client/src/app/pages/landing/landing-page.html - 273 + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 - - trading stocks, ETFs or cryptocurrencies on multiple platforms + + Do you really want to delete this account balance? - apps/client/src/app/pages/landing/landing-page.html - 280 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - pursuing a buy & hold strategy + + Export Activities - apps/client/src/app/pages/landing/landing-page.html - 286 + libs/ui/src/lib/activities-table/activities-table.component.html + 41 - - - interested in getting insights of your portfolio composition - apps/client/src/app/pages/landing/landing-page.html - 291 + libs/ui/src/lib/activities-table/activities-table.component.html + 396 - - valuing privacy and data ownership + + Export Drafts as ICS - apps/client/src/app/pages/landing/landing-page.html - 296 + libs/ui/src/lib/activities-table/activities-table.component.html + 54 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 409 - - into minimalism + + Draft - apps/client/src/app/pages/landing/landing-page.html - 299 + libs/ui/src/lib/activities-table/activities-table.component.html + 145 - - caring about diversifying your financial resources + + Clone - apps/client/src/app/pages/landing/landing-page.html - 303 + libs/ui/src/lib/activities-table/activities-table.component.html + 436 - - interested in financial independence + + Export Draft as ICS - apps/client/src/app/pages/landing/landing-page.html - 307 + libs/ui/src/lib/activities-table/activities-table.component.html + 446 - - saying no to spreadsheets in + + Do you really want to delete this activity? - apps/client/src/app/pages/landing/landing-page.html - 311 + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 - - still reading this list + + Asset Profiles - apps/client/src/app/pages/landing/landing-page.html - 314 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - - Learn more about Ghostfolio + + 50-Day Trend - apps/client/src/app/pages/landing/landing-page.html - 319 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 - - What our users are saying + + 200-Day Trend - apps/client/src/app/pages/landing/landing-page.html - 327 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 - - Members from around the globe are using Ghostfolio Premium + + Last All Time High - apps/client/src/app/pages/landing/landing-page.html - 366 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 - - How does Ghostfolio work? + + Change from All Time High - apps/client/src/app/pages/landing/landing-page.html - 383 + libs/ui/src/lib/benchmark/benchmark.component.html + 110 - - Get started in only 3 steps + + from ATH - apps/client/src/app/pages/landing/landing-page.html - 386 + libs/ui/src/lib/benchmark/benchmark.component.html + 112 - - Sign up anonymously* + + Market data provided by - apps/client/src/app/pages/landing/landing-page.html - 392 + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 - - * no e-mail address nor credit card required + + Savings Rate per Month - apps/client/src/app/pages/landing/landing-page.html - 394 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 - - Add any of your historical transactions + + Annual Interest Rate - apps/client/src/app/pages/landing/landing-page.html - 405 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 - - Get valuable insights of your portfolio composition + + Retirement Date - apps/client/src/app/pages/landing/landing-page.html - 417 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 - - Are you ready? + + Projected Total Amount - apps/client/src/app/pages/landing/landing-page.html - 431 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 - - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + + Interest - apps/client/src/app/pages/open/open-page.html - 6 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 - - - (Last 24 hours) - apps/client/src/app/pages/open/open-page.html - 37 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 - - - Active Users - apps/client/src/app/pages/open/open-page.html - 40 + libs/ui/src/lib/i18n.ts + 38 + + + Savings - apps/client/src/app/pages/open/open-page.html - 62 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 - - (Last 30 days) + + Allocation - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 - apps/client/src/app/pages/open/open-page.html - 59 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 - - - New Users - apps/client/src/app/pages/open/open-page.html - 51 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 40 - - - Users in Slack community - apps/client/src/app/pages/open/open-page.html - 75 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 - - Contributors on GitHub + + Show all - apps/client/src/app/pages/open/open-page.html - 89 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 - - (Last 90 days) + + Account - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 - - - Uptime - apps/client/src/app/pages/open/open-page.html - 132 + libs/ui/src/lib/activities-table/activities-table.component.html + 308 - - - Activities - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + libs/ui/src/lib/assistant/assistant.html + 157 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + libs/ui/src/lib/i18n.ts + 4 - - Do you really want to delete these activities? + + Asia-Pacific - libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + libs/ui/src/lib/i18n.ts + 5 - - Update activity + + Asset Class - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 10 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 - - - Stocks, ETFs, bonds, cryptocurrencies, commodities - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 25 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 65 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 306 - - - One-time fee, annual account fees - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 - - - Distribution of corporate earnings apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + 290 - - - Revenue for lending out money - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + libs/ui/src/lib/assistant/assistant.html + 218 - - - Mortgages, personal loans, credit cards - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 57 + libs/ui/src/lib/i18n.ts + 6 - - Luxury items, real estate, private companies + + Asset Sub Class - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 73 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 - - - Account - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 - libs/ui/src/lib/activities-table/activities-table.component.html - 308 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 - libs/ui/src/lib/assistant/assistant.html - 107 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 - - - Update Cash Balance apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 112 + 306 + + + libs/ui/src/lib/i18n.ts + 7 - - Unit Price + + Core - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + libs/ui/src/lib/i18n.ts + 10 + + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + libs/ui/src/lib/i18n.ts + 12 + + + Switch to Ghostfolio Premium easily - libs/ui/src/lib/activities-table/activities-table.component.html - 210 + libs/ui/src/lib/i18n.ts + 13 - - Oops! Could not get the historical exchange rate from + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + libs/ui/src/lib/i18n.ts + 14 - - Fee + + Emergency Fund - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + apps/client/src/app/pages/features/features-page.html + 89 - libs/ui/src/lib/activities-table/activities-table.component.html - 234 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 - - - Oops! Could not get the historical exchange rate from - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 + libs/ui/src/lib/i18n.ts + 15 - - Import Activities + + Grant - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + libs/ui/src/lib/i18n.ts + 17 - - Import Dividends + + Higher Risk - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + libs/ui/src/lib/i18n.ts + 18 - - Importing data... + + This activity already exists. - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + libs/ui/src/lib/i18n.ts + 19 - - Import has been completed + + Japan - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + libs/ui/src/lib/i18n.ts + 89 - - Validating data... + + Lower Risk - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + libs/ui/src/lib/i18n.ts + 20 - - Select Holding + + Month - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 20 + libs/ui/src/lib/i18n.ts + 21 - - Select File + + Months - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + libs/ui/src/lib/i18n.ts 22 - - Holding + + Other - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 32 + libs/ui/src/lib/i18n.ts + 23 - libs/ui/src/lib/assistant/assistant.html - 127 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 - - Load Dividends + + Preset - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 68 + libs/ui/src/lib/i18n.ts + 25 - - Choose or drop a file here + + Retirement Provision - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/ui/src/lib/i18n.ts + 26 - - The following file formats are supported: + + Satellite - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 90 + libs/ui/src/lib/i18n.ts + 27 - - Select Dividends + + Symbol - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 113 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 - - - Select Activities - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 115 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 - - - Back - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 144 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 178 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 - - - Allocations - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + libs/ui/src/lib/i18n.ts + 28 - - Allocations + + Tag - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + libs/ui/src/lib/assistant/assistant.html + 207 - - - Proportion of Net Worth - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 12 + libs/ui/src/lib/i18n.ts + 29 - - By Platform + + Year - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 44 + libs/ui/src/lib/i18n.ts + 30 - - By Currency + + Years - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 63 + libs/ui/src/lib/i18n.ts + 31 - - By Asset Class + + Buy - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 85 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 - - - By Holding - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 107 + libs/ui/src/lib/i18n.ts + 35 - - By Sector + + Fee - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 130 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 234 + + + libs/ui/src/lib/i18n.ts + 37 - - By Continent + + Valuable - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 153 + libs/ui/src/lib/i18n.ts + 39 - - By Market + + Liability - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 175 + libs/ui/src/lib/i18n.ts + 40 - - Regions + + Sell - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 198 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 - apps/client/src/app/pages/public/public-page.html - 143 + libs/ui/src/lib/i18n.ts + 41 - - Developed Markets + + Cash - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 222 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 - apps/client/src/app/pages/public/public-page.html - 160 + libs/ui/src/lib/i18n.ts + 53 - - Emerging Markets + + Commodity - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 231 + libs/ui/src/lib/i18n.ts + 45 + + + + Equity + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 - apps/client/src/app/pages/public/public-page.html - 169 + libs/ui/src/lib/i18n.ts + 46 - - Other Markets + + Fixed Income - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 240 + libs/ui/src/lib/i18n.ts + 47 + + + Real Estate - apps/client/src/app/pages/public/public-page.html - 178 + libs/ui/src/lib/i18n.ts + 49 - - No data available + + Bond - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 + libs/ui/src/lib/i18n.ts + 52 + + + Cryptocurrency - apps/client/src/app/pages/public/public-page.html - 188 + libs/ui/src/lib/i18n.ts + 55 + + + ETF - libs/ui/src/lib/benchmark/benchmark.component.html - 137 + libs/ui/src/lib/i18n.ts + 56 + + + Mutual Fund - libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + libs/ui/src/lib/i18n.ts + 57 - - By Account + + Precious Metal - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 286 + libs/ui/src/lib/i18n.ts + 58 - - By ETF Provider + + Private Equity - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 306 + libs/ui/src/lib/i18n.ts + 59 - - By Country + + Stock - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 264 + libs/ui/src/lib/i18n.ts + 60 - - Analysis + + Africa - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 67 + + + + Asia + + libs/ui/src/lib/i18n.ts + 68 + + + Europe - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/ui/src/lib/i18n.ts + 69 - - Dividend + + North America - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + libs/ui/src/lib/i18n.ts + 70 + + + Oceania libs/ui/src/lib/i18n.ts - 36 + 71 - - Deposit + + South America - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + libs/ui/src/lib/i18n.ts + 72 - - Monthly + + Extreme Fear - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + libs/ui/src/lib/i18n.ts + 103 - - Yearly + + Extreme Greed - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + libs/ui/src/lib/i18n.ts + 104 - - Analysis + + Neutral - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + libs/ui/src/lib/i18n.ts + 107 - - Top + + Valid until - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 - - - Bottom - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + libs/ui/src/lib/membership-card/membership-card.component.html + 42 - - Portfolio Evolution + + Time to add your first activity. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 - - Investment Timeline + + No data available - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 - - - Current Streak - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + apps/client/src/app/pages/public/public-page.html + 188 - - - Longest Streak - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + libs/ui/src/lib/benchmark/benchmark.component.html + 202 - - - Dividend Timeline - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 - - - FIRE - apps/client/src/app/pages/portfolio/fire/fire-page.html - 4 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 - - - Calculator - apps/client/src/app/pages/portfolio/fire/fire-page.html - 7 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - - 4% Rule + + If a translation is missing, kindly support us in extending it here. - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Currency Cluster Risks + + Date Range - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + libs/ui/src/lib/assistant/assistant.html + 143 - - Account Cluster Risks + + The current market price is - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - Holdings + + Test - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 + + + Oops! Could not grant access. - apps/client/src/app/components/home-holdings/home-holdings.html - 4 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + Restricted view - apps/client/src/app/pages/public/public-page.html - 70 + apps/client/src/app/components/access-table/access-table.component.html + 26 - libs/ui/src/lib/assistant/assistant.html - 46 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Pricing + + Permission - apps/client/src/app/pages/pricing/pricing-page-routing.module.ts - 13 + apps/client/src/app/components/access-table/access-table.component.html + 18 - - - Pricing Plans - apps/client/src/app/pages/pricing/pricing-page.html - 4 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. + + Private - apps/client/src/app/pages/pricing/pricing-page.html - 6 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + + Job Queue - apps/client/src/app/pages/pricing/pricing-page.html - 26 + libs/common/src/lib/routes/routes.ts + 46 - - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + + Market data is delayed for - apps/client/src/app/pages/pricing/pricing-page.html - 38 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 - - Unlimited Transactions + + Absolute Currency Performance - apps/client/src/app/pages/pricing/pricing-page.html - 45 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + Absolute Net Performance - apps/client/src/app/pages/pricing/pricing-page.html - 134 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 + + + Absolute Asset Performance - apps/client/src/app/pages/pricing/pricing-page.html - 201 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 - - Unlimited Accounts + + Investment - apps/client/src/app/pages/pricing/pricing-page.html - 49 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - apps/client/src/app/pages/pricing/pricing-page.html - 138 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - apps/client/src/app/pages/pricing/pricing-page.html - 205 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - - - Portfolio Performance - apps/client/src/app/pages/pricing/pricing-page.html - 53 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 94 - apps/client/src/app/pages/pricing/pricing-page.html - 142 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 + + + Asset Performance - apps/client/src/app/pages/pricing/pricing-page.html - 209 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Data Import and Export + + Net Performance - apps/client/src/app/pages/pricing/pricing-page.html - 73 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + Currency Performance - apps/client/src/app/pages/pricing/pricing-page.html - 146 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 + + + Year to date - apps/client/src/app/pages/pricing/pricing-page.html - 229 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Community Support + + Week to date - apps/client/src/app/pages/pricing/pricing-page.html - 90 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Self-hosted, update manually. + + Month to date - apps/client/src/app/pages/pricing/pricing-page.html - 94 + libs/ui/src/lib/assistant/assistant.component.ts + 356 - - Free + + MTD - apps/client/src/app/pages/pricing/pricing-page.html - 95 + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + WTD - apps/client/src/app/pages/pricing/pricing-page.html - 158 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - For new investors who are just getting started with trading. + + Oops! A data provider is experiencing the hiccups. - apps/client/src/app/pages/pricing/pricing-page.html - 128 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 - - Fully managed Ghostfolio cloud offering. + + View - apps/client/src/app/pages/pricing/pricing-page.html - 157 + apps/client/src/app/components/access-table/access-table.component.html + 23 - apps/client/src/app/pages/pricing/pricing-page.html - 261 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - For ambitious investors who need the full picture of their financial assets. + + Reset Filters - apps/client/src/app/pages/pricing/pricing-page.html - 194 + libs/ui/src/lib/assistant/assistant.html + 238 - - Email and Chat Support + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - apps/client/src/app/pages/pricing/pricing-page.html - 257 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 - - Renew Plan + + year - apps/client/src/app/components/header/header.component.html - 191 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - apps/client/src/app/pages/pricing/pricing-page.html - 294 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - One-time payment, no auto-renewal. + + years - apps/client/src/app/pages/pricing/pricing-page.html - 298 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Get Started + + Apply Filters - apps/client/src/app/pages/landing/landing-page.html - 446 + libs/ui/src/lib/assistant/assistant.html + 248 - - It’s free. + + self-hosting + kebab-case - apps/client/src/app/pages/pricing/pricing-page.html - 327 + libs/common/src/lib/routes/routes.ts + 243 - - - Hello, has shared a Portfolio with you! - apps/client/src/app/pages/public/public-page.html - 4 + libs/common/src/lib/routes/routes.ts + 246 - - Currencies + + Self-Hosting - apps/client/src/app/pages/public/public-page.html - 88 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - - - Continents - apps/client/src/app/pages/public/public-page.html - 124 + libs/common/src/lib/routes/routes.ts + 248 - - Ghostfolio empowers you to keep track of your wealth. + + Data Gathering - apps/client/src/app/pages/public/public-page.html - 215 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 - - - Registration - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + apps/client/src/app/components/admin-overview/admin-overview.html + 60 - - Continue with Internet Identity + + General - apps/client/src/app/pages/register/register-page.html - 42 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 - - Continue with Google + + Cloud - apps/client/src/app/pages/register/register-page.html - 53 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 - - - Copy to clipboard - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + libs/common/src/lib/routes/routes.ts + 240 - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. + + Oops! It looks like you’re making too many requests. Please slow down a bit. - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + apps/client/src/app/core/http-response.interceptor.ts + 106 - - Agree and continue + + My Account - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 13 - - Personal Finance Tools + + Closed - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 - - open-source-alternative-to + + Active - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 + + + Indonesia - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + libs/ui/src/lib/i18n.ts + 87 - - Open Source Alternative to + + Activity - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 - - Discover Open Source Alternatives for Personal Finance Tools + + Dividend Yield - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + + Execute Job - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. + + This action is not allowed. - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/core/http-response.interceptor.ts + 67 - - Open Source Alternative to + + Priority - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 - - The Open Source Alternative to + + Liquidity - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + libs/ui/src/lib/i18n.ts + 48 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + + Buy and sell - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + libs/ui/src/lib/i18n.ts + 8 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + + {VAR_PLURAL, plural, =1 {activity} other {activities}} - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + + Delete Activities - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + libs/ui/src/lib/activities-table/activities-table.component.html + 67 - - Ghostfolio vs comparison table + + Internationalization - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + libs/common/src/lib/routes/routes.ts + 119 - - Founded + + Close Account - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 77 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 - - Origin + + Do you really want to close your Ghostfolio account? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 82 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 - - Region + + Danger Zone - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 87 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 - - Available in + + Approximation based on the top holdings of each ETF - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 - - ✅ Yes + + By ETF Holding - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 140 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + Join now or check out the example account - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 157 + apps/client/src/app/pages/landing/landing-page.html + 435 + + + Oops! There was an error setting up biometric authentication. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 179 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + Show more - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 196 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + Do you really want to delete these profiles? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 218 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + Delete Profiles - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 235 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + Oops! Could not delete profiles. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 257 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + Benchmarks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 274 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 - - ❌ No + + Chart - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 147 + apps/client/src/app/components/home-holdings/home-holdings.html + 19 + + + Table - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 164 + apps/client/src/app/components/home-holdings/home-holdings.html + 16 + + + Would you like to refine your personal investment strategy? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 186 + apps/client/src/app/pages/public/public-page.html + 212 + + + Wealth - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 203 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 + + + Community - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 225 + apps/client/src/app/app.component.html + 130 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 242 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 264 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 281 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 - - - Self-Hosting - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 - - - Use anonymously - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 - - - Free Plan - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 - - - Starting from - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 - - - year - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 - - - Notes - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 302 + apps/client/src/app/pages/features/features-page.html + 276 - - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 - - Ready to take your investments to the next level? + + Thailand - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + libs/ui/src/lib/i18n.ts + 97 - - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + + India - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 + libs/ui/src/lib/i18n.ts + 86 - - Get Started + + Austria - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + libs/ui/src/lib/i18n.ts + 77 - - Personal Finance Tools + + Poland - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 + libs/ui/src/lib/i18n.ts + 92 - - Switzerland - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 - + + Italy libs/ui/src/lib/i18n.ts - 90 + 88 - - Global + + User Experience apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 - - - libs/ui/src/lib/i18n.ts - 16 + 95 - - Resources + + App - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 - - Guides + + Tool - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 - - Glossary + + Investor - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 - - Membership - - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 - + + Wealth Management - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 - - Access + + Canada - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + libs/ui/src/lib/i18n.ts + 81 + + + New Zealand - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + libs/ui/src/lib/i18n.ts + 91 - - My Ghostfolio + + Netherlands - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 33 + libs/ui/src/lib/i18n.ts + 90 - - Oops, authentication has failed. + + Alternative - apps/client/src/app/pages/webauthn/webauthn-page.html - 19 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 - - Try again + + Family Office - apps/client/src/app/pages/webauthn/webauthn-page.html - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 - - Go back to Home Page + + Personal Finance - apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + apps/client/src/app/app.component.html + 57 - - - Do you really want to delete this account balance? - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 - - Import Activities + + Software - libs/ui/src/lib/activities-table/activities-table.component.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 + + + Romania - libs/ui/src/lib/activities-table/activities-table.component.html - 371 + libs/ui/src/lib/i18n.ts + 93 - - Import Dividends + + Germany - libs/ui/src/lib/activities-table/activities-table.component.html - 29 + libs/ui/src/lib/i18n.ts + 85 + + + United States - libs/ui/src/lib/activities-table/activities-table.component.html - 383 + libs/ui/src/lib/i18n.ts + 100 - - Export Activities + + Budgeting - libs/ui/src/lib/activities-table/activities-table.component.html - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 + + + Belgium - libs/ui/src/lib/activities-table/activities-table.component.html - 396 + libs/ui/src/lib/i18n.ts + 78 - - Export Drafts as ICS + + Open Source - libs/ui/src/lib/activities-table/activities-table.component.html - 54 + apps/client/src/app/pages/landing/landing-page.html + 261 - libs/ui/src/lib/activities-table/activities-table.component.html - 409 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 - - Draft + + Czech Republic - libs/ui/src/lib/activities-table/activities-table.component.html - 145 + libs/ui/src/lib/i18n.ts + 82 - - Clone + + Australia - libs/ui/src/lib/activities-table/activities-table.component.html - 436 + libs/ui/src/lib/i18n.ts + 76 - - Export Draft as ICS + + South Africa - libs/ui/src/lib/activities-table/activities-table.component.html - 446 + libs/ui/src/lib/i18n.ts + 95 - - Do you really want to delete this activity? + + Bulgaria - libs/ui/src/lib/activities-table/activities-table.component.ts - 229 + libs/ui/src/lib/i18n.ts + 80 - - Find holding... + + Privacy - libs/ui/src/lib/assistant/assistant.component.ts - 144 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 - - No entries... + + Finland - libs/ui/src/lib/assistant/assistant.html - 63 + libs/ui/src/lib/i18n.ts + 83 + + + France - libs/ui/src/lib/assistant/assistant.html + libs/ui/src/lib/i18n.ts 84 - - Asset Profiles + + Error - libs/ui/src/lib/assistant/assistant.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 - - Index + + Cancel - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - 50-Day Trend - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - - - 200-Day Trend - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - Last All Time High - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 - - - Change from All Time High - libs/ui/src/lib/benchmark/benchmark.component.html - 81 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 - - - from ATH - libs/ui/src/lib/benchmark/benchmark.component.html - 83 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 - - - Market data provided by - libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html - 2 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 - - - Savings Rate per Month - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 10 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 - - - Annual Interest Rate - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 21 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 - - - Retirement Date - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 32 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 - - - Projected Total Amount - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 - - - Interest - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 libs/ui/src/lib/i18n.ts - 38 + 9 - - Savings + + Yes - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + libs/ui/src/lib/i18n.ts + 32 - - Allocation - - libs/ui/src/lib/holdings-table/holdings-table.component.html - 98 - + + Inactive - libs/ui/src/lib/top-holdings/top-holdings.component.html - 40 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 + + + Close - libs/ui/src/lib/top-holdings/top-holdings.component.html - 116 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 - - - Show all - libs/ui/src/lib/holdings-table/holdings-table.component.html - 197 + libs/ui/src/lib/i18n.ts + 11 - - Account + + Activate - libs/ui/src/lib/i18n.ts - 4 + apps/client/src/app/components/rule/rule.component.html + 74 - - Asia-Pacific + + Deactivate - libs/ui/src/lib/i18n.ts - 5 + apps/client/src/app/components/rule/rule.component.html + 72 - - Asset Class + + Threshold Max - libs/ui/src/lib/i18n.ts - 6 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Asset Sub Class + + Customize - libs/ui/src/lib/i18n.ts - 7 + apps/client/src/app/components/rule/rule.component.html + 67 - - Core + + Portfolio Snapshot - libs/ui/src/lib/i18n.ts - 10 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Switch to Ghostfolio Premium or Ghostfolio Open Source easily + + Threshold Min - libs/ui/src/lib/i18n.ts - 12 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Switch to Ghostfolio Premium easily + + Performance with currency effect Performance - libs/ui/src/lib/i18n.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Switch to Ghostfolio Open Source or Ghostfolio Basic easily + + Copy link to clipboard - libs/ui/src/lib/i18n.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - Emergency Fund + + Change with currency effect Change - libs/ui/src/lib/i18n.ts - 15 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Grant + + No auto-renewal. - libs/ui/src/lib/i18n.ts - 17 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - Higher Risk + + From the beginning - libs/ui/src/lib/i18n.ts - 18 + apps/client/src/app/pages/public/public-page.html + 60 - - This activity already exists. + + This year - libs/ui/src/lib/i18n.ts - 19 + apps/client/src/app/pages/public/public-page.html + 42 - - Japan + + offers a free plan - libs/ui/src/lib/i18n.ts - 84 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Lower Risk - libs/ui/src/lib/i18n.ts - 20 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Month + + does not offer a free plan - libs/ui/src/lib/i18n.ts - 21 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - Months - libs/ui/src/lib/i18n.ts - 22 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Other + + can be self-hosted - libs/ui/src/lib/i18n.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Preset + + cannot be self-hosted - libs/ui/src/lib/i18n.ts - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 - - - Retirement Provision - libs/ui/src/lib/i18n.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Satellite + + can be used anonymously - libs/ui/src/lib/i18n.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Symbol - libs/ui/src/lib/i18n.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Tag + + cannot be used anonymously - libs/ui/src/lib/i18n.ts - 29 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - Year - libs/ui/src/lib/i18n.ts - 30 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Years + + is not Open Source Software - libs/ui/src/lib/i18n.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - - - Buy - libs/ui/src/lib/i18n.ts - 35 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Fee + + is Open Source Software - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 - - - Valuable - libs/ui/src/lib/i18n.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Liability + + This page has been archived. - libs/ui/src/lib/i18n.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Sell + + Oops! Invalid currency. - libs/ui/src/lib/i18n.ts - 41 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Cash + + Oops! Could not find any assets. - libs/ui/src/lib/i18n.ts - 44 + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html + 40 - - Commodity + + Ukraine libs/ui/src/lib/i18n.ts - 45 + 98 - - Equity + + Set API key - libs/ui/src/lib/i18n.ts - 46 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Fixed Income + + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts - 47 + 24 - - Real Estate + + Data Providers - libs/ui/src/lib/i18n.ts - 49 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Bond + + Join now - libs/ui/src/lib/i18n.ts - 52 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Cryptocurrency + + Glossary - libs/ui/src/lib/i18n.ts - 53 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - ETF - libs/ui/src/lib/i18n.ts - 54 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Mutual Fund - libs/ui/src/lib/i18n.ts - 55 + libs/common/src/lib/routes/routes.ts + 293 - - Precious Metal + + glossary + kebab-case - libs/ui/src/lib/i18n.ts - 56 + libs/common/src/lib/routes/routes.ts + 288 - - - Private Equity - libs/ui/src/lib/i18n.ts - 57 + libs/common/src/lib/routes/routes.ts + 291 - - Stock + + Guides - libs/ui/src/lib/i18n.ts - 58 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Africa - libs/ui/src/lib/i18n.ts - 65 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Asia - libs/ui/src/lib/i18n.ts - 66 + libs/common/src/lib/routes/routes.ts + 301 - - Europe + + guides + kebab-case - libs/ui/src/lib/i18n.ts - 67 + libs/common/src/lib/routes/routes.ts + 296 - - - North America - libs/ui/src/lib/i18n.ts - 68 + libs/common/src/lib/routes/routes.ts + 299 - - Oceania + + Threshold range - libs/ui/src/lib/i18n.ts - 69 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - South America + + Economic Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 + + + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - libs/ui/src/lib/i18n.ts - 70 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Extreme Fear + + Please enter your Ghostfolio API key: - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Extreme Greed + + of - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Neutral + + Do you really want to delete the API key? - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Membership + + Remove API key - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Valid until + + daily requests apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 + 137 + + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... libs/ui/src/lib/membership-card/membership-card.component.html - 42 + 26 - - Time to add your first activity. + + API Key - libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html - 12 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - No data available + + API Requests Today - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + apps/client/src/app/components/admin-users/admin-users.html + 179 + + + Could not generate an API key - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - If a translation is missing, kindly support us in extending it here. + + Do you really want to generate a new API key? - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Date Range + + Ghostfolio Premium Data Provider API Key - libs/ui/src/lib/assistant/assistant.html - 93 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - The current market price is + + Set this API key in your self-hosted environment: - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 - - Test + + rules align with your portfolio. - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Oops! Could not grant access. + + out of - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - Restricted view + + Save - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Permission - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Private - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Job Queue - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Market data is delayed for - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 - - - Absolute Currency Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - - - Absolute Net Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Absolute Asset Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Investment + + Asset Class Cluster Risks - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + Received Access - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 + + + Me - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/header/header.component.html + 213 - - - Asset Performance - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Net Performance + + Please enter your Ghostfolio API key. - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Currency Performance + + AI prompt has been copied to the clipboard - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Year to date + + Link has been copied to the clipboard - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Week to date + + Regional Market Cluster Risks - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Month to date + + Mode - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - MTD + + Default Market Price - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - WTD + + Selector - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 - - Oops! A data provider is experiencing the hiccups. + + Instant - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - View + + Lazy - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 + + + HTTP Request Headers - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - Reset Filters + + real-time - libs/ui/src/lib/assistant/assistant.html - 185 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + + end of day - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - year + + Open Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - years + + Create - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - Apply Filters + + Change - libs/ui/src/lib/assistant/assistant.html - 195 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - self-hosting + + Performance - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - - - FAQ - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - - - Self-Hosting - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Data Gathering + + Copy AI prompt to clipboard for analysis - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - General + + Singapore - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/i18n.ts + 94 - - Cloud + + Armenia - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/i18n.ts + 75 + + + British Virgin Islands - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 79 - - Oops! It looks like you’re making too many requests. Please slow down a bit. + + Copy portfolio data to clipboard for AI prompt - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 - - My Account + + I understand that if I lose my security token, I cannot recover my account - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Closed + + Please keep your security token safe. If you lose it, you will not be able to recover your account. - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Active + + Here is your security token. It is only visible once, please store and keep it in a safe place. - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Activity + + Continue - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Dividend Yield + + Terms and Conditions - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - Execute Job + + Do you really want to generate a new security token for this user? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - This action is not allowed. + + Security token - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Priority - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Liquidity + + Generate Security Token - libs/ui/src/lib/i18n.ts - 48 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Buy and sell + + United Kingdom libs/ui/src/lib/i18n.ts - 8 + 99 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + Terms of Service - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/app.component.html + 112 - - - Delete Activities - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + libs/common/src/lib/routes/routes.ts + 217 - - Internationalization + + terms-of-service + kebab-case - apps/client/src/app/app-routing.module.ts - 88 + libs/common/src/lib/routes/routes.ts + 212 - - - Close Account - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + libs/common/src/lib/routes/routes.ts + 215 - - Do you really want to close your Ghostfolio account? + + Terms of Service - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Danger Zone + + and I agree to the Terms of Service. - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Approximation based on the top holdings of each ETF + + () is already in use. - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - By ETF Holding + + An error occurred while updating to (). - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Join now or check out the example account + + Apply - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Oops! There was an error setting up biometric authentication. + + with API access for - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Show more + + Data Gathering is off - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 38 - - Do you really want to delete these profiles? + + Performance Calculation - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Delete Profiles + + someone - apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Oops! Could not delete profiles. + + Add asset to watchlist - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Benchmarks + + Watchlist - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 - - - Chart - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/pages/features/features-page.html + 197 - - - Table - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + libs/common/src/lib/routes/routes.ts + 110 - - Would you like to refine your personal investment strategy? + + Do you really want to delete this item? - apps/client/src/app/pages/public/public-page.html - 211 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Wealth + + Log out - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + apps/client/src/app/components/header/header.component.html + 329 - - Community + + Calculations are based on delayed market data and may not be displayed in real-time. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/home-market/home-market.html + 44 - - - Thailand - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/components/markets/markets.html + 53 - - India + + changelog + kebab-case - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - Austria + + Sync Demo User Account - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Poland + + Demo user account has been synced. - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Italy + + Name - libs/ui/src/lib/i18n.ts - 83 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - User Experience + + Set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - App + + No emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Tool + + An emergency fund has been set up - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Investor + + Fee Ratio - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Wealth Management + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Canada + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - New Zealand + + Find holding or page... - libs/ui/src/lib/i18n.ts - 86 + libs/ui/src/lib/assistant/assistant.component.ts + 161 - - Netherlands + + Quick Links - libs/ui/src/lib/i18n.ts - 85 + libs/ui/src/lib/assistant/assistant.html + 56 - - Alternative + + Asset Profiles - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + libs/ui/src/lib/assistant/assistant.html + 112 - - Family Office + + Live Demo - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Personal Finance - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + libs/common/src/lib/routes/routes.ts + 231 - - Romania + + Open Source Alternative to - libs/ui/src/lib/i18n.ts - 88 + libs/common/src/lib/routes/routes.ts + 326 - - Germany + + Single Account - libs/ui/src/lib/i18n.ts - 81 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - United States + + Your net worth is managed by a single account - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Budgeting + + Your net worth is managed by ${accountsLength} accounts - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - Belgium + + personal-finance-tools + kebab-case - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 312 - - - Open Source - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + libs/common/src/lib/routes/routes.ts + 315 - - - Czech Republic - libs/ui/src/lib/i18n.ts - 78 + libs/common/src/lib/routes/routes.ts + 323 - - Australia + + markets + kebab-case - libs/ui/src/lib/i18n.ts - 73 + libs/common/src/lib/routes/routes.ts + 304 - - - South Africa - libs/ui/src/lib/i18n.ts - 89 + libs/common/src/lib/routes/routes.ts + 307 - - Bulgaria + + Get Access - libs/ui/src/lib/i18n.ts - 76 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Privacy + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Finland + + Learn more - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - France + + Limited Offer! - libs/ui/src/lib/i18n.ts - 80 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Error + + Get extra - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - Cancel + + Unavailable - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Yes + + Available - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Inactive + + new - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Close - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Activate + + Investment - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Deactivate + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Threshold Max + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Customize + + Equity - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Threshold Min + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Performance with currency effect Performance + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Copy link to clipboard + + Fixed Income - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Change with currency effect Change + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - No auto-renewal. + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - From the beginning + + Investment: Base Currency - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - This year + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - offers a free plan + + Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - offers a free plan + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - is not Open Source Software + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - does not offer a free plan + + start + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + libs/common/src/lib/routes/routes.ts + 336 - - - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + libs/common/src/lib/routes/routes.ts + 337 - - cannot be self-hosted + + Generate - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - does not offer a free plan + + Do you really want to generate a new security token? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - can be self-hosted + + Cryptocurrencies - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/components/markets/markets.component.ts + 53 + + + apps/client/src/app/pages/features/features-page.html + 51 - - can be used anonymously + + Stocks + + apps/client/src/app/components/markets/markets.component.ts + 52 + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be used anonymously + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - is Open Source Software + + Manage Asset Profile - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - is not Open Source Software + + Alternative Investment - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + libs/ui/src/lib/i18n.ts + 44 - - cannot be used anonymously + + Collectible - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + libs/ui/src/lib/i18n.ts + 54 - - cannot be self-hosted + + Average Unit Price - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 - - - is Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - can be used anonymously + + No results found... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + libs/ui/src/lib/assistant/assistant.html + 49 - - This page has been archived. + + Account Cluster Risks - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + apps/client/src/app/pages/i18n/i18n-page.html 14 - - Oops! Invalid currency. + + Asset Class Cluster Risks - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - Oops! Could not find any assets. + + Currency Cluster Risks - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - Want to stay updated? Click below to get notified as soon as it’s available. + + Economic Market Cluster Risks - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Ukraine + + Emergency Fund - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Set API key + + Fees - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - Get access to 100’000+ tickers from over 50 exchanges + + Regional Market Cluster Risks - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - NEW + + Developed Markets - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Data Providers + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Join now + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Glossary + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 109 + + + Emerging Markets - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - glossary - snake-case + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - snake-case + + Your net worth is managed by 0 accounts - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - Skip + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 154 - - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Economic Market Cluster Risks + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Please enter your Ghostfolio API key: + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 170 + + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Notify me + + Europe - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - I have an API key + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 188 - - Remove API key + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - daily requests + + Japan - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Key + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Tag + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - API Requests Today + + North America - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Could not generate an API key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - Set this API key in your self-hosted environment: + + Support Ghostfolio - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 - - rules align with your portfolio. + + Find Ghostfolio on GitHub - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 + + + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of + + Ghostfolio is an independent & bootstrapped business - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Save + + Send an e-mail - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks + + Join the Ghostfolio Slack community - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - Received Access + + Follow Ghostfolio on LinkedIn - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me + + Follow Ghostfolio on X (formerly Twitter) - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index e88e77aec..e76f7a4ed 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -2,7635 +2,8134 @@ - + about - 关于 - snake-case + about + kebab-case - apps/client/src/app/app.component.ts - 64 + libs/common/src/lib/routes/routes.ts + 176 - apps/client/src/app/app.component.ts - 66 + libs/common/src/lib/routes/routes.ts + 177 - apps/client/src/app/app.component.ts - 70 + libs/common/src/lib/routes/routes.ts + 182 - apps/client/src/app/app.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 190 - apps/client/src/app/components/header/header.component.ts - 81 + libs/common/src/lib/routes/routes.ts + 198 - apps/client/src/app/components/header/header.component.ts - 86 + libs/common/src/lib/routes/routes.ts + 206 - apps/client/src/app/core/paths.ts - 2 + libs/common/src/lib/routes/routes.ts + 214 + + + faq + faq + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 45 + libs/common/src/lib/routes/routes.ts + 234 - apps/client/src/app/pages/about/about-page.component.ts - 50 + libs/common/src/lib/routes/routes.ts + 235 - apps/client/src/app/pages/about/about-page.component.ts - 55 + libs/common/src/lib/routes/routes.ts + 239 - apps/client/src/app/pages/about/about-page.component.ts - 63 + libs/common/src/lib/routes/routes.ts + 245 + + + features + features + kebab-case - apps/client/src/app/pages/about/about-page.component.ts - 74 + libs/common/src/lib/routes/routes.ts + 254 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 255 + + + license + license + kebab-case - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 188 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 15 + libs/common/src/lib/routes/routes.ts + 191 + + + markets + markets + kebab-case - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 259 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 260 + + + pricing + pricing + kebab-case - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts - 13 + libs/common/src/lib/routes/routes.ts + 269 - apps/client/src/app/pages/landing/landing-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 270 + + + privacy-policy + privacy-policy + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 18 + libs/common/src/lib/routes/routes.ts + 204 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 24 + libs/common/src/lib/routes/routes.ts + 207 - - faq - 常见问题 - snake-case + + register + register + kebab-case - apps/client/src/app/app.component.ts - 77 + libs/common/src/lib/routes/routes.ts + 279 - apps/client/src/app/core/paths.ts - 3 + libs/common/src/lib/routes/routes.ts + 280 + + + resources + resources + kebab-case - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 19 + libs/common/src/lib/routes/routes.ts + 284 - apps/client/src/app/pages/faq/faq-page.component.ts - 37 + libs/common/src/lib/routes/routes.ts + 285 - apps/client/src/app/pages/faq/faq-page.component.ts - 42 + libs/common/src/lib/routes/routes.ts + 290 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/common/src/lib/routes/routes.ts + 298 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 14 + libs/common/src/lib/routes/routes.ts + 306 - - - features - 功能 - snake-case - apps/client/src/app/app.component.ts - 78 + libs/common/src/lib/routes/routes.ts + 314 - apps/client/src/app/components/header/header.component.ts - 82 + libs/common/src/lib/routes/routes.ts + 322 + + + You are using the Live Demo. + 您正在使用现场演示。 - apps/client/src/app/components/header/header.component.ts - 87 + apps/client/src/app/app.component.html + 12 + + + Create Account + 创建账户 - apps/client/src/app/core/paths.ts - 4 + apps/client/src/app/app.component.html + 13 - apps/client/src/app/pages/about/overview/about-overview-page.component.ts - 20 + apps/client/src/app/pages/register/register-page.html + 27 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 15 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 2 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 101 + + + Frequently Asked Questions (FAQ) + 常见问题 (FAQ) - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 13 + apps/client/src/app/pages/faq/overview/faq-overview-page.html + 5 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts - 13 + apps/client/src/app/pages/faq/saas/saas-page.html + 5 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 18 + apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html + 5 + + + The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. + 交易存在巨大亏损风险,因此不应投入您短期内可能急需的资金。 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts - 15 + apps/client/src/app/app.component.html + 221 + + + Alias + 别名 - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 4 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 15 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 11 + + + Grantee + 被授权人 - apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts - 14 + apps/client/src/app/components/access-table/access-table.component.html + 11 + + + Type + 类型 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 41 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 31 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 25 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 22 - - - license - 许可 - snake-case - apps/client/src/app/app.component.ts - 71 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 15 - apps/client/src/app/core/paths.ts - 5 + libs/ui/src/lib/activities-table/activities-table.component.html + 161 + + + Details + 详情 - apps/client/src/app/pages/about/about-page.component.ts - 55 + apps/client/src/app/components/access-table/access-table.component.html + 33 - - markets - 市场 - snake-case + + Revoke + 撤销 - apps/client/src/app/app.component.ts - 79 + apps/client/src/app/components/access-table/access-table.component.html + 75 + + + Do you really want to revoke this granted access? + 您真的要撤销此访问权限吗? - apps/client/src/app/components/header/header.component.ts - 83 + apps/client/src/app/components/access-table/access-table.component.ts + 108 + + + Cash Balance + 现金余额 - apps/client/src/app/components/header/header.component.ts - 88 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 47 - apps/client/src/app/core/paths.ts - 6 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 136 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 34 + + + Platform + 平台 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts - 19 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 67 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 86 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 31 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 48 + + + Cash Balances + 现金余额 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 35 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 124 - - pricing - 价钱 - snake-case + + Transfer Cash Balance + 转移现金余额 - apps/client/src/app/app.component.ts - 80 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 10 - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 73 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 7 + + + Name + 名称 - apps/client/src/app/components/header/header.component.ts - 84 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 43 - apps/client/src/app/components/header/header.component.ts + apps/client/src/app/components/admin-market-data/admin-market-data.html 89 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts - 16 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 289 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 42 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 22 - apps/client/src/app/core/http-response.interceptor.ts - 72 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 15 - apps/client/src/app/core/paths.ts - 7 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 46 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 22 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 13 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 15 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts - 13 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 15 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts - 14 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 139 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts - 16 + libs/ui/src/lib/activities-table/activities-table.component.html + 138 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 28 - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts + libs/ui/src/lib/top-holdings/top-holdings.component.html 16 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts - 16 - - - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 15 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 88 + + + Total + 总计 - libs/ui/src/lib/membership-card/membership-card.component.ts - 31 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 55 - - privacy-policy - 隐私政策 - snake-case + + Currency + 货币 - apps/client/src/app/app.component.ts - 75 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 65 - apps/client/src/app/core/paths.ts - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 187 - apps/client/src/app/pages/about/about-page.component.ts - 63 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 296 - - - register - 注册 - snake-case - apps/client/src/app/app.component.ts - 81 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 46 - apps/client/src/app/components/header/header.component.ts - 90 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 25 - apps/client/src/app/core/auth.guard.ts - 55 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 145 - apps/client/src/app/core/paths.ts - 9 + libs/ui/src/lib/activities-table/activities-table.component.html + 276 + + + Value + 价值 - apps/client/src/app/pages/faq/saas/saas-page.component.ts - 16 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 171 - apps/client/src/app/pages/features/features-page.component.ts - 29 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 206 - apps/client/src/app/pages/landing/landing-page.component.ts - 27 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 53 - apps/client/src/app/pages/pricing/pricing-page.component.ts - 42 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 205 - - - resources - 资源 - snake-case - apps/client/src/app/app.component.ts - 82 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 208 - apps/client/src/app/components/header/header.component.ts - 85 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 211 - apps/client/src/app/components/header/header.component.ts - 91 + libs/ui/src/lib/account-balances/account-balances.component.html + 34 - apps/client/src/app/core/paths.ts - 10 + libs/ui/src/lib/activities-table/activities-table.component.html + 257 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/activities-table/activities-table.component.html + 293 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 74 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts - 13 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 25 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts - 14 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 102 + + + Edit + 编辑 - apps/client/src/app/pages/features/features-page.component.ts - 30 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 307 - apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts - 16 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 268 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 21 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 74 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 30 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 67 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 39 + libs/ui/src/lib/activities-table/activities-table.component.html + 430 + + + Delete + 删除 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 14 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 318 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 27 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 290 - - - You are using the Live Demo. - 您正在使用现场演示。 - apps/client/src/app/app.component.html - 12 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 64 - - - Create Account - 创建账户 - apps/client/src/app/app.component.html - 13 + apps/client/src/app/components/admin-overview/admin-overview.html + 131 - apps/client/src/app/pages/register/register-page.html - 27 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 85 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 2 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 78 - - - Personal Finance - 个人财务 - apps/client/src/app/app.component.html - 57 + libs/ui/src/lib/account-balances/account-balances.component.html + 80 - - - Markets - 市场 - apps/client/src/app/app.component.html - 61 + libs/ui/src/lib/activities-table/activities-table.component.html + 457 - apps/client/src/app/components/header/header.component.html - 398 + libs/ui/src/lib/benchmark/benchmark.component.html + 169 + + + Do you really want to delete this account? + 您确定要删除此账户吗? - apps/client/src/app/components/home-market/home-market.html - 2 + apps/client/src/app/components/accounts-table/accounts-table.component.ts + 148 + + + Asset Profile + 资产概况 - apps/client/src/app/pages/resources/markets/resources-markets.component.html - 2 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 35 - - Resources - 资源 + + Historical Market Data + 历史市场数据 - apps/client/src/app/app.component.html - 64 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 37 - apps/client/src/app/components/header/header.component.html - 82 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 87 + + + Data Source + 数据源 - apps/client/src/app/components/header/header.component.html - 291 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 55 - apps/client/src/app/pages/resources/overview/resources-overview.component.html - 4 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 106 - - - About - 关于 - apps/client/src/app/app.component.html - 70 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 165 - apps/client/src/app/components/header/header.component.html - 117 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 155 + + + Attempts + 尝试次数 - apps/client/src/app/components/header/header.component.html - 364 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 83 - - Blog - 博客 + + Created + 创建 - apps/client/src/app/app.component.html - 73 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 92 + + + Finished + 完成 - apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html - 204 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 101 + + + Status + 状态 - apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 110 - apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html - 184 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 92 + + + Delete Jobs + 删除任务 - apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html - 184 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 151 + + + View Data + 查看数据 - apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html - 209 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 166 + + + View Stacktrace + 查看堆栈跟踪 - apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html - 196 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 173 + + + Delete Job + 删除任务 - apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html - 181 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 180 + + + Details for + 的详细信息 - apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html - 141 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 2 + + + Date + 日期 - apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html - 168 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 161 - apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html - 178 + libs/ui/src/lib/account-balances/account-balances.component.html + 12 - apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html - 202 + libs/ui/src/lib/activities-table/activities-table.component.html + 170 - apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html - 253 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 6 + + + Market Price + 市场价 - apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html - 233 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 133 - apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html - 243 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 111 - apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html - 154 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 26 + + + Currencies + 货币 - apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html - 273 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 125 - apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html - 181 + apps/client/src/app/pages/public/public-page.html + 88 + + + ETFs without Countries + 没有国家的 ETF - apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html - 148 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 130 + + + ETFs without Sectors + 无行业类别的 ETF - apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html - 270 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 135 + + + + Do you really want to delete this asset profile? + 您确实要删除此资产配置文件吗? + + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 37 + + + Filter by... + 过滤... - apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html - 187 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 379 + + + First Activity + 首笔交易 - apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html - 167 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 148 - apps/client/src/app/pages/blog/blog-page.html - 5 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 198 - - - Changelog - 变更日志 - apps/client/src/app/app.component.html - 77 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 214 - apps/client/src/app/pages/about/changelog/changelog-page.html - 4 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 50 - - Features - 功能 + + Activities Count + 活动计数 - apps/client/src/app/app.component.html - 79 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 157 + + + Historical Data + 历史数据 - apps/client/src/app/components/header/header.component.html - 351 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 166 - apps/client/src/app/pages/features/features-page.html - 5 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 44 - - Frequently Asked Questions (FAQ) - 常见问题 (FAQ) + + Sectors Count + 行业数 - apps/client/src/app/app.component.html - 83 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 175 + + + Countries Count + 国家数 - apps/client/src/app/pages/about/overview/about-overview-page.html - 146 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 184 - - License - 许可 + + Gather Profile Data + 收集个人资料数据 - apps/client/src/app/app.component.html - 88 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 235 - apps/client/src/app/pages/about/license/license-page.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 44 - - Pricing - 价钱 + + Oops! Could not parse historical data. + 哎呀!无法解析历史数据。 - apps/client/src/app/app.component.html - 97 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts + 262 + + + Refresh + 刷新 - apps/client/src/app/components/header/header.component.html - 99 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 17 + + + Import + 导入 - apps/client/src/app/components/header/header.component.html - 303 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 153 - apps/client/src/app/components/header/header.component.html - 379 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 186 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 287 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + 71 - - Privacy Policy - 隐私政策 + + Sector + 行业 - apps/client/src/app/app.component.html - 103 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 242 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html - 4 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 263 - - Community - 社区 + + Country + 国家 - apps/client/src/app/app.component.html - 121 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 253 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 77 + apps/client/src/app/components/admin-users/admin-users.html + 78 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 83 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 273 + + + Sectors + 行业 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 88 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 259 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 92 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 492 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 96 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 279 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 100 + apps/client/src/app/pages/public/public-page.html + 106 + + + Countries + 国家 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 105 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 269 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 110 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 503 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 114 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 291 + + + Symbol Mapping + 代码映射 - apps/client/src/app/pages/features/features-page.html - 259 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 360 - - The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term. - 交易损失的风险可能很大。不建议将短期内可能需要的资金进行投资。 + + Scraper Configuration + 刮削配置 - apps/client/src/app/app.component.html - 200 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 385 - - Alias - 别名 + + Note + 笔记 - apps/client/src/app/components/access-table/access-table.component.html - 4 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 528 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 11 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 78 - - - Grantee - 受赠者 - apps/client/src/app/components/access-table/access-table.component.html - 11 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 275 - - Type - 类型 + + Add Asset Profile + 添加资产概况 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 7 + + + Search + 搜索 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 22 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 16 + + + Add Manually + 手动添加 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 15 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 19 + + + Name, symbol or ISIN + 名称、代码或 ISIN - libs/ui/src/lib/activities-table/activities-table.component.html - 161 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 119 - - - Details - 细节 - apps/client/src/app/components/access-table/access-table.component.html - 33 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 29 - - - Revoke - 撤销 - apps/client/src/app/components/access-table/access-table.component.html - 75 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 10 - - - Do you really want to revoke this granted access? - 您真的要撤销此授予的访问权限吗? - apps/client/src/app/components/access-table/access-table.component.ts - 67 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 124 - - Cash Balance - 现金余额 + + Do you really want to delete this coupon? + 您确实要删除此优惠券吗? - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 47 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 194 + + + Do you really want to delete this system message? + 您真的要删除这条系统消息吗? - apps/client/src/app/components/accounts-table/accounts-table.component.html - 136 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 207 + + + Do you really want to flush the cache? + 您真的要刷新缓存吗? - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 34 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 231 - - Equity - 公平 + + Please set your system message: + 请设置您的系统消息: - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 58 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 251 - - Activities - 活动 + + Version + 版本 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 63 + apps/client/src/app/components/admin-overview/admin-overview.html + 7 + + + User Count + 用户数 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 92 + apps/client/src/app/components/admin-overview/admin-overview.html + 13 + + + Activity Count + 活动计数 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 119 + apps/client/src/app/components/admin-overview/admin-overview.html + 19 + + + per User + 每位用户 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 131 + apps/client/src/app/components/admin-overview/admin-overview.html + 28 + + + Add Currency + 添加货币 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 58 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 22 + + + User Signup + 用户注册 - apps/client/src/app/components/admin-users/admin-users.html - 135 + apps/client/src/app/components/admin-overview/admin-overview.html + 34 + + + Read-only Mode + 只读模式 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 209 + apps/client/src/app/components/admin-overview/admin-overview.html + 48 + + + System Message + 系统信息 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 319 + apps/client/src/app/components/admin-overview/admin-overview.html + 72 + + + Set Message + 设置留言 - apps/client/src/app/pages/portfolio/activities/activities-page.html - 4 + apps/client/src/app/components/admin-overview/admin-overview.html + 94 - - Platform - 平台 + + Coupons + 优惠券 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 67 + apps/client/src/app/components/admin-overview/admin-overview.html + 102 + + + Add + 添加 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 86 + apps/client/src/app/components/admin-overview/admin-overview.html + 176 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 48 + libs/ui/src/lib/account-balances/account-balances.component.html + 93 - - Cash Balances - 现金余额 + + Housekeeping + 维护 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 124 + apps/client/src/app/components/admin-overview/admin-overview.html + 184 - - Transfer Cash Balance - 转移现金余额 - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 10 - + + Flush Cache + 刷新缓存 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 7 + apps/client/src/app/components/admin-overview/admin-overview.html + 200 - - Name - 名称 + + Add Platform + 添加平台 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 43 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 9 + + + Url + 网址 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 60 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 463 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 207 + 515 apps/client/src/app/components/admin-platform/admin-platform.component.html - 30 + 38 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 15 + 25 + + + Do you really want to delete this platform? + 您真的要删除这个平台吗? - apps/client/src/app/components/admin-tag/admin-tag.component.html - 30 + apps/client/src/app/components/admin-platform/admin-platform.component.ts + 107 + + + Update platform + 更新平台 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 15 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 8 + + + Add platform + 添加平台 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 15 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 10 + + + Platforms + 平台 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 195 + + + Tags + 标签 - libs/ui/src/lib/activities-table/activities-table.component.html - 138 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 201 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 28 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - libs/ui/src/lib/top-holdings/top-holdings.component.html + libs/ui/src/lib/tags-selector/tags-selector.component.html 16 - - libs/ui/src/lib/top-holdings/top-holdings.component.html - 88 - - - Total - 全部的 + + Add Tag + 添加标签 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 55 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 9 - - Currency - 货币 - - apps/client/src/app/components/accounts-table/accounts-table.component.html - 65 + + Do you really want to delete this tag? + 您真的要删除此标签吗? + + apps/client/src/app/components/admin-tag/admin-tag.component.ts + 103 + + + Update tag + 更新标签 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 111 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 8 + + + Add tag + 添加标签 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 214 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 10 + + + Do you really want to delete this user? + 您真的要删除该用户吗? - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 46 + apps/client/src/app/components/admin-users/admin-users.component.ts + 177 + + + User + 用户 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 25 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 31 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + apps/client/src/app/components/header/header.component.html + 231 + + + Engagement per Day + 每天的参与度 - libs/ui/src/lib/activities-table/activities-table.component.html - 276 + apps/client/src/app/components/admin-users/admin-users.html + 158 - - Value - 价值 + + Last Request + 最后请求 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 171 + apps/client/src/app/components/admin-users/admin-users.html + 204 + + + Impersonate User + 模拟用户 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 206 + apps/client/src/app/components/admin-users/admin-users.html + 240 + + + Delete User + 删除用户 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 53 + apps/client/src/app/components/admin-users/admin-users.html + 261 + + + Compare with... + 与之比较... - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 204 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 18 + + + Manage Benchmarks + 管理基准 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 207 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 35 + + + Portfolio + 投资组合 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 210 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 124 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 + apps/client/src/app/components/header/header.component.html + 44 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 + apps/client/src/app/components/header/header.component.html + 258 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 92 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 + libs/common/src/lib/routes/routes.ts + 151 + + + Benchmark + 基准 - libs/ui/src/lib/account-balances/account-balances.component.html - 34 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 354 - libs/ui/src/lib/activities-table/activities-table.component.html - 257 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts + 136 + + + Current Market Mood + 当前市场情绪 - libs/ui/src/lib/activities-table/activities-table.component.html - 293 + apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html + 12 + + + User + 用户 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 74 + apps/client/src/app/components/admin-users/admin-users.html + 30 + + + About Ghostfolio + 关于 Ghostfolio - libs/ui/src/lib/top-holdings/top-holdings.component.html - 25 + apps/client/src/app/components/header/header.component.html + 326 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 102 + apps/client/src/app/pages/about/overview/about-overview-page.html + 5 - - Edit - 编辑 + + Get started + 开始使用 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 278 + apps/client/src/app/components/header/header.component.html + 432 + + + Sign in + 登入 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 231 + apps/client/src/app/components/header/header.component.html + 422 - apps/client/src/app/components/admin-overview/admin-overview.html - 78 + apps/client/src/app/components/header/header.component.ts + 259 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 92 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 71 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 85 + libs/common/src/lib/routes/routes.ts + 81 - libs/ui/src/lib/activities-table/activities-table.component.html - 430 + libs/common/src/lib/routes/routes.ts + 157 - - Delete - 删除 + + Oops! Incorrect Security Token. + 哎呀!安全令牌不正确。 - apps/client/src/app/components/accounts-table/accounts-table.component.html - 289 + apps/client/src/app/components/header/header.component.ts + 274 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 253 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 153 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 65 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 191 + + + Manage Activities + 管理活动 - apps/client/src/app/components/admin-overview/admin-overview.html - 89 + apps/client/src/app/components/home-holdings/home-holdings.html + 66 + + + Fear + 恐惧 - apps/client/src/app/components/admin-overview/admin-overview.html - 206 + apps/client/src/app/components/home-market/home-market.component.ts + 42 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 103 + apps/client/src/app/components/markets/markets.component.ts + 47 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 96 + libs/ui/src/lib/i18n.ts + 105 + + + Greed + 贪婪 - libs/ui/src/lib/account-balances/account-balances.component.html - 80 + apps/client/src/app/components/home-market/home-market.component.ts + 43 - libs/ui/src/lib/activities-table/activities-table.component.html - 457 + apps/client/src/app/components/markets/markets.component.ts + 48 - - - Do you really want to delete this account? - 您真的要删除该帐户吗? - apps/client/src/app/components/accounts-table/accounts-table.component.ts + libs/ui/src/lib/i18n.ts 106 - - Asset Profile - 资产概况 + + Last Days + 最后的 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + apps/client/src/app/components/home-market/home-market.html + 7 - - - Historical Market Data - 历史市场数据 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + apps/client/src/app/components/markets/markets.html + 17 - - Symbol - 符号 + + Welcome to Ghostfolio + 欢迎来到Ghostfolio - apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + apps/client/src/app/components/home-overview/home-overview.html + 11 + + + Ready to take control of your personal finances? + 准备好掌控您的个人财务了吗? - apps/client/src/app/components/admin-market-data/admin-market-data.html - 46 + apps/client/src/app/components/home-overview/home-overview.html + 12 + + + Setup your accounts + 设置您的帐户 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 96 - - - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 39 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 289 + apps/client/src/app/components/home-overview/home-overview.html + 19 - - Data Source - 数据源 - - apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 - - - apps/client/src/app/components/admin-market-data/admin-market-data.html - 77 - - - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 106 - + + Get a comprehensive financial overview by adding your bank and brokerage accounts. + 通过添加您的银行和经纪账户来获取全面的财务概览。 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + apps/client/src/app/components/home-overview/home-overview.html + 21 - - Attempts - 尝试 + + Capture your activities + 记录你的活动 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + apps/client/src/app/components/home-overview/home-overview.html + 28 - - Created - 创建 + + Record your investment activities to keep your portfolio up to date. + 记录您的投资活动以使您的投资组合保持最新状态。 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + apps/client/src/app/components/home-overview/home-overview.html + 30 - - Finished - 完成的 + + Monitor and analyze your portfolio + 监控和分析您的投资组合 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + apps/client/src/app/components/home-overview/home-overview.html + 37 - - Status - 状况 + + Track your progress in real-time with comprehensive analysis and insights. + 通过全面的分析和见解实时跟踪您的进度。 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + apps/client/src/app/components/home-overview/home-overview.html + 39 - - Delete Jobs - 删除作业 + + Setup accounts + 设置帐户 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + apps/client/src/app/components/home-overview/home-overview.html + 52 - - View Data - 查看数据 + + Add activity + 添加活动 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + apps/client/src/app/components/home-overview/home-overview.html + 60 - - - View Stacktrace - 查看堆栈跟踪 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 8 - - Delete Job - 删除作业 + + Total Amount + 总金额 - apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 141 - - Details for - 详细信息 + + Savings Rate + 储蓄率 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 2 + apps/client/src/app/components/investment-chart/investment-chart.component.ts + 200 - - Date - 日期 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 - + + Security Token + 安全令牌 - libs/ui/src/lib/account-balances/account-balances.component.html - 12 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 11 - libs/ui/src/lib/activities-table/activities-table.component.html - 170 + apps/client/src/app/components/user-account-access/user-account-access.html + 3 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 6 + apps/client/src/app/components/user-account-access/user-account-access.html + 15 - - - Market Price - 市场价 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 104 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 279 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 98 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 64 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 26 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 72 - - Cancel - 取消 + + or + - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 30 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 56 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 32 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 42 + apps/client/src/app/pages/landing/landing-page.html + 48 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 25 + apps/client/src/app/pages/landing/landing-page.html + 451 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 58 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 97 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 103 + apps/client/src/app/pages/register/register-page.html + 31 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 65 + apps/client/src/app/pages/webauthn/webauthn-page.html + 30 + + + Sign in with Internet Identity + 使用互联网身份登录 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 42 + + + Sign in with Google + 使用 Google 登录 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 38 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 52 + + + Stay signed in + 保持登录 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 46 + apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html + 61 - - Save - 保存 + + Time in Market + 在市时长 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 3 + + + Absolute Gross Performance + 绝对总业绩 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 63 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 70 + + + Fees + 费用 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 49 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 204 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 32 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 84 - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 135 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 213 + + + Absolute Net Performance + 绝对净绩效 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 65 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 102 + + + Net Performance + 净绩效 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 110 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 117 + + + Total Assets + 总资产 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 143 + + + Assets + 资产 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html - 48 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 203 - - Currencies - 货币 + + Buying Power + 购买力 - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 85 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 216 - - ETFs without Countries - 没有国家的 ETF + + Excluded from Analysis + 从分析中排除 - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 90 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 228 - - ETFs without Sectors - 无行业类别的 ETF + + Liabilities + 负债 - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 95 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 243 + + + apps/client/src/app/pages/features/features-page.html + 102 - - Do you really want to delete this asset profile? - 您确实要删除此资产配置文件吗? + + Net Worth + 净值 - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 36 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 261 - - Filter by... - 过滤... + + Annualized Performance + 年化业绩 - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 328 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 274 - - Asset Class - 资产类别 + + Please set the amount of your emergency fund. + 请输入您的应急基金金额。 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 86 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 71 + + + Minimum Price + 最低价格 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 140 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 127 + + + Maximum Price + 最高价格 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 224 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 143 + + + Quantity + 数量 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 216 + 153 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 189 - libs/ui/src/lib/assistant/assistant.html - 166 + libs/ui/src/lib/activities-table/activities-table.component.html + 186 - - Asset Sub Class - 资产子类别 + + Report Data Glitch + 报告数据故障 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 95 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 446 + + + Are you an ambitious investor who needs the full picture? + 您是一位雄心勃勃、需要全面了解的投资者吗? - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 149 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 15 + + + Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: + 立即升级至 Ghostfolio Premium 并获得独家功能,以增强您的投资体验: - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 237 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 18 + + + Portfolio Summary + 投资组合摘要 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 225 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 24 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + apps/client/src/app/pages/pricing/pricing-page.html + 44 + + + apps/client/src/app/pages/pricing/pricing-page.html + 205 - - First Activity - 第一个活动 + + Portfolio Allocations + 投资组合分配 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 119 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 28 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 122 + apps/client/src/app/pages/features/features-page.html + 161 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 197 + apps/client/src/app/pages/pricing/pricing-page.html + 48 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 50 + apps/client/src/app/pages/pricing/pricing-page.html + 209 - - Activities Count - 活动计数 + + Performance Benchmarks + 性能基准 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 128 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 32 - - - Historical Data - 历史数据 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 137 + apps/client/src/app/pages/pricing/pricing-page.html + 52 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html - 44 + apps/client/src/app/pages/pricing/pricing-page.html + 213 - - Sectors Count - 行业数 + + FIRE Calculator + 财务自由计算器 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 146 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 36 - - - Countries Count - 国家数 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 155 + apps/client/src/app/pages/pricing/pricing-page.html + 56 - - - Gather Recent Data - 收集最近的数据 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 192 + apps/client/src/app/pages/pricing/pricing-page.html + 217 - - Gather All Data - 收集所有数据 + + Professional Data Provider + 专业数据提供商 - apps/client/src/app/components/admin-market-data/admin-market-data.html - 195 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 40 + + + apps/client/src/app/pages/pricing/pricing-page.html + 237 - - Gather Profile Data - 收集个人资料数据 + + and more Features... + 以及更多功能... - apps/client/src/app/components/admin-market-data/admin-market-data.html - 198 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 44 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 45 + apps/client/src/app/pages/pricing/pricing-page.html + 72 - - - Oops! Could not parse historical data. - 哎呀!无法解析历史数据。 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts - 263 + apps/client/src/app/pages/pricing/pricing-page.html + 261 - - Refresh - 刷新 + + Get the tools to effectively manage your finances and refine your personal investment strategy. + 获取有效管理财务和完善个人投资策略的工具。 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 22 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 48 - - Gather Historical Data - 收集历史数据 + + Skip + 跳过 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 32 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 59 - - - Import - 导入 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 153 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 98 + + + Upgrade Plan + 升级计划 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 186 + apps/client/src/app/components/header/header.component.html + 193 - libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html 70 - - - Sector - 行业 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 166 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 20 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 242 + apps/client/src/app/pages/pricing/pricing-page.html + 299 - - Country - 国家 + + Today + 今天 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 177 + apps/client/src/app/pages/public/public-page.html + 24 - apps/client/src/app/components/admin-users/admin-users.html - 77 + libs/ui/src/lib/assistant/assistant.component.ts + 348 + + + YTD + 年初至今 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 252 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Sectors - 行业 + + 1Y + 1年 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 183 + libs/ui/src/lib/assistant/assistant.component.ts + 370 + + + 5Y + 5年 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + libs/ui/src/lib/assistant/assistant.component.ts + 395 + + + Max + 最大限度 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 258 + libs/ui/src/lib/assistant/assistant.component.ts + 401 + + + Grant access + 授予访问权限 - apps/client/src/app/pages/public/public-page.html - 106 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 7 - - Countries - 国家 + + Public + 公开 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 193 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 25 + + + Granted Access + 授予访问权限 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + apps/client/src/app/components/user-account-access/user-account-access.html + 57 + + + Please enter your coupon code. + 请输入您的优惠券代码。 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 270 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 215 - - Benchmark - 基准 + + Could not redeem coupon code + 无法兑换优惠券代码 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 265 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 179 - - Symbol Mapping - 符号映射 + + Coupon code has been redeemed + 优惠券代码已被兑换 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 271 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 192 - - Scraper Configuration - 刮削配置 + + Reload + 重新加载 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 193 - - Note - 笔记 + + per year + 每年 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 32 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 78 + apps/client/src/app/pages/pricing/pricing-page.html + 283 + + + Try Premium + 尝试高级版 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 49 - - Add Asset Profile - 添加资产概况 + + Redeem Coupon + 兑换优惠券 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 7 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 63 - - Search - 搜索 + + Auto + 自动 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 16 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 69 - - - Add Manually - 手动添加 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 19 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 172 - - Name, symbol or ISIN - 名称、符号或 ISIN + + Do you really want to remove this sign in method? + 您确实要删除此登录方法吗? - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 29 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 280 + + + Presenter View + 演示者视图 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 124 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 183 - - Please add a currency: - 请添加货币: + + Protection for sensitive information like absolute performances and quantity values + 保护绝对业绩、金额等敏感信息 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 125 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 185 - - is an invalid currency! - 是无效的货币! + + Base Currency + 基础货币 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 136 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 9 - - Do you really want to delete this coupon? - 您确实要删除此优惠券吗? + + Language + 语言 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 155 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 56 - - Do you really want to delete this currency? - 您真的要删除该货币吗? + + Locale + 语言环境 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 168 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 422 - - - Do you really want to delete this system message? - 您真的要删除这条系统消息吗? - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 181 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 133 - - Do you really want to flush the cache? - 您真的要刷新缓存吗? + + Date and number format + 日期和数字格式 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 205 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 135 - - Please set your system message: - 请设置您的系统消息: + + Appearance + 外观 - apps/client/src/app/components/admin-overview/admin-overview.component.ts - 225 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 158 - - Version - 版本 + + Light + 明亮 - apps/client/src/app/components/admin-overview/admin-overview.html - 7 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 173 - - User Count - 用户数 + + Dark + 黑暗 - apps/client/src/app/components/admin-overview/admin-overview.html - 13 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 174 - - Activity Count - 活动计数 + + Zen Mode + 极简模式 - apps/client/src/app/components/admin-overview/admin-overview.html - 19 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 201 - - - per User - 每位用户 - apps/client/src/app/components/admin-overview/admin-overview.html - 28 + apps/client/src/app/pages/features/features-page.html + 246 - - Exchange Rates - 汇率 + + Distraction-free experience for turbulent times + 动荡时期的无干扰体验 - apps/client/src/app/components/admin-overview/admin-overview.html - 34 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 203 - - Add Currency - 添加货币 + + Biometric Authentication + 生物识别认证 - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 22 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 218 + + + Sign in with fingerprint + 使用指纹登录 - apps/client/src/app/components/admin-overview/admin-overview.html - 105 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 219 - - User Signup - 用户注册 + + Experimental Features + 实验性功能 - apps/client/src/app/components/admin-overview/admin-overview.html - 111 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 235 - - Read-only Mode - 只读模式 + + Sneak peek at upcoming functionality + 预览即将推出的功能 - apps/client/src/app/components/admin-overview/admin-overview.html - 125 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 237 - - System Message - 系统信息 + + User ID + 用户身份 - apps/client/src/app/components/admin-overview/admin-overview.html - 149 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 45 - - - Set Message - 设置留言 - apps/client/src/app/components/admin-overview/admin-overview.html - 171 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 252 - - Coupons - 优惠券 + + Export Data + 导出数据 - apps/client/src/app/components/admin-overview/admin-overview.html - 179 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 260 - - Add - 添加 + + This feature is currently unavailable. + 此功能目前无法使用。 - apps/client/src/app/components/admin-overview/admin-overview.html - 239 + apps/client/src/app/core/http-response.interceptor.ts + 55 + + + Please try again later. + 请稍后再试。 - libs/ui/src/lib/account-balances/account-balances.component.html - 93 + apps/client/src/app/core/http-response.interceptor.ts + 57 - - - Housekeeping - 家政 - apps/client/src/app/components/admin-overview/admin-overview.html - 247 + apps/client/src/app/core/http-response.interceptor.ts + 88 - - - Flush Cache - 刷新缓存 - apps/client/src/app/components/admin-overview/admin-overview.html - 251 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 186 - - Add Platform - 添加平台 + + Oops! Something went wrong. + 哎呀!出了些问题。 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 11 + apps/client/src/app/core/http-response.interceptor.ts + 86 - - - Url - 网址 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 184 + + + Okay + 好的 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 51 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 154 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 25 + apps/client/src/app/core/http-response.interceptor.ts + 89 - - - Accounts - 帐户 - apps/client/src/app/components/admin-platform/admin-platform.component.html - 65 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 187 + + + About + 关于 - apps/client/src/app/components/admin-users/admin-users.html - 114 + apps/client/src/app/app.component.html + 70 apps/client/src/app/components/header/header.component.html - 54 + 124 apps/client/src/app/components/header/header.component.html - 263 + 375 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 352 + apps/client/src/app/pages/about/overview/about-overview-page.routes.ts + 12 - apps/client/src/app/pages/accounts/accounts-page.html - 4 + libs/common/src/lib/routes/routes.ts + 220 - - Do you really want to delete this platform? - 您真的要删除这个平台吗? + + Changelog + 更新日志 - apps/client/src/app/components/admin-platform/admin-platform.component.ts - 86 + apps/client/src/app/app.component.html + 77 - - - Update platform - 更新平台 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 8 + apps/client/src/app/pages/about/changelog/changelog-page.html + 4 - - - Add platform - 添加平台 - apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 10 + libs/common/src/lib/routes/routes.ts + 185 - - Platforms - 平台 + + License + 许可证 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 79 + apps/client/src/app/app.component.html + 89 - - - Tags - 标签 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 85 + apps/client/src/app/pages/about/license/license-page.html + 4 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 + libs/common/src/lib/routes/routes.ts + 193 + + + Privacy Policy + 隐私政策 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + apps/client/src/app/app.component.html + 105 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.html + 4 - - - Add Tag - 添加标签 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 11 + libs/common/src/lib/routes/routes.ts + 209 - - Do you really want to delete this tag? - 您真的要删除此标签吗? + + Our + 我们的 - apps/client/src/app/components/admin-tag/admin-tag.component.ts - 86 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 6 - - Update tag - 更新标签 + + Discover other exciting Open Source Software projects + 发现其他令人兴奋的开源软件项目 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 8 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 9 - - Add tag - 添加标签 + + Visit + 访问 - apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 10 + apps/client/src/app/pages/about/oss-friends/oss-friends-page.html + 28 - - Do you really want to delete this user? - 您真的要删除该用户吗? + + Accounts + 账户 - apps/client/src/app/components/admin-users/admin-users.component.ts - 138 + apps/client/src/app/components/admin-platform/admin-platform.component.html + 52 - - - User - 用户 apps/client/src/app/components/admin-users/admin-users.html - 29 + 115 - - - Registration - 注册 - apps/client/src/app/components/admin-users/admin-users.html - 97 + apps/client/src/app/components/header/header.component.html + 58 - - - Engagement per Day - 每天的参与度 - apps/client/src/app/components/admin-users/admin-users.html - 157 + apps/client/src/app/components/header/header.component.html + 268 - - - Last Request - 最后请求 - apps/client/src/app/components/admin-users/admin-users.html - 202 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 370 - - - Impersonate User - 模拟用户 - apps/client/src/app/components/admin-users/admin-users.html - 239 + apps/client/src/app/pages/accounts/accounts-page.html + 4 - - - Delete User - 删除用户 - apps/client/src/app/components/admin-users/admin-users.html - 251 + libs/common/src/lib/routes/routes.ts + 69 - - Performance - 表现 + + Oops, cash balance transfer has failed. + 糟糕,现金余额转账失败。 - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 6 + apps/client/src/app/pages/accounts/accounts-page.component.ts + 330 + + + Update account + 更新账户 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 142 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 8 - - Compare with... - 与之比较... + + Add account + 新增帐户 - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 18 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 10 - - Manage Benchmarks - 管理基准 + + Account ID + 帐户ID - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html - 35 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 96 - - Portfolio - 文件夹 + + From + - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 116 - - - apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 46 - - - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 95 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 11 - - Benchmark - 基准 + + To + - apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts - 128 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 32 - - Current Market Mood - 当前市场情绪 + + Transfer + 转移 - apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.html - 12 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 72 - - Overview - 概述 + + Admin Control + 管理 apps/client/src/app/components/header/header.component.html - 28 + 74 apps/client/src/app/components/header/header.component.html - 245 + 289 + + + libs/common/src/lib/routes/routes.ts + 64 - - Portfolio - 文件夹 + + Market Data + 市场数据 - apps/client/src/app/components/header/header.component.html - 41 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 393 - apps/client/src/app/components/header/header.component.html - 255 + libs/common/src/lib/routes/routes.ts + 51 - - Admin Control - 管理控制 + + Settings + 设置 - apps/client/src/app/components/header/header.component.html - 68 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 2 - apps/client/src/app/components/header/header.component.html - 279 + libs/common/src/lib/routes/routes.ts + 34 - - - Me - - apps/client/src/app/components/header/header.component.html - 211 + libs/common/src/lib/routes/routes.ts + 56 - - User + + Users 用户 - apps/client/src/app/components/admin-tag/admin-tag.component.html - 44 + libs/common/src/lib/routes/routes.ts + 61 + + + Overview + 概述 apps/client/src/app/components/header/header.component.html - 229 + 30 - - - My Ghostfolio - 我的 Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 248 - - - About Ghostfolio - 关于 Ghostfolio - apps/client/src/app/components/header/header.component.html - 316 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 48 - apps/client/src/app/pages/about/overview/about-overview-page.html - 5 + apps/client/src/app/pages/admin/admin-page.component.ts + 48 - - - Sign in - 登入 - apps/client/src/app/components/header/header.component.html - 412 + apps/client/src/app/pages/resources/resources-page.component.ts + 30 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 71 + libs/common/src/lib/routes/routes.ts + 113 - - - Get started - 开始使用 - apps/client/src/app/components/header/header.component.html - 422 + libs/common/src/lib/routes/routes.ts + 170 - - Sign in - 登入 + + Blog + 博客 - apps/client/src/app/app-routing.module.ts - 150 + apps/client/src/app/app.component.html + 74 - apps/client/src/app/components/header/header.component.ts - 230 + apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.html + 205 - - - Oops! Incorrect Security Token. - 哎呀!安全令牌不正确。 - apps/client/src/app/components/header/header.component.ts - 245 + apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html + 185 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 157 + apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html + 185 - - - Manage Activities - 管理活动 - apps/client/src/app/components/home-holdings/home-holdings.html - 63 + apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html + 185 - - - Fear - 恐惧 - apps/client/src/app/components/home-market/home-market.component.ts - 27 + apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.html + 210 - libs/ui/src/lib/i18n.ts - 98 + apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html + 197 - - - Greed - 贪婪 - apps/client/src/app/components/home-market/home-market.component.ts - 28 + apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html + 182 - libs/ui/src/lib/i18n.ts - 99 + apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.html + 142 - - - Last Days - 最后的 - apps/client/src/app/components/home-market/home-market.html - 7 + apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.html + 169 - - - Welcome to Ghostfolio - 欢迎来到Ghostfolio - apps/client/src/app/components/home-overview/home-overview.html - 7 + apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.html + 179 - - - Ready to take control of your personal finances? - 准备好掌控您的个人财务了吗? - apps/client/src/app/components/home-overview/home-overview.html - 8 + apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.html + 203 - - - Setup your accounts - 设置您的帐户 - apps/client/src/app/components/home-overview/home-overview.html - 15 + apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.html + 254 - - - Get a comprehensive financial overview by adding your bank and brokerage accounts. - 通过添加您的银行和经纪账户来获取全面的财务概览。 - apps/client/src/app/components/home-overview/home-overview.html - 17 + apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.html + 234 - - - Capture your activities - 记录你的活动 - apps/client/src/app/components/home-overview/home-overview.html - 24 + apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html + 244 - - - Record your investment activities to keep your portfolio up to date. - 记录您的投资活动以使您的投资组合保持最新状态。 - apps/client/src/app/components/home-overview/home-overview.html - 26 + apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html + 155 - - - Monitor and analyze your portfolio - 监控和分析您的投资组合 - apps/client/src/app/components/home-overview/home-overview.html - 33 + apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.html + 274 - - - Track your progress in real-time with comprehensive analysis and insights. - 通过全面的分析和见解实时跟踪您的进度。 - apps/client/src/app/components/home-overview/home-overview.html - 35 + apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.html + 184 - - - Setup accounts - 设置帐户 - apps/client/src/app/components/home-overview/home-overview.html - 44 + apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.html + 149 - - - Add activity - 添加活动 - apps/client/src/app/components/home-overview/home-overview.html - 52 + apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.html + 271 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 8 + apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.html + 190 - - - Summary - 概括 - apps/client/src/app/components/home-summary/home-summary.html - 2 + apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html + 168 - - - Total Amount - 总金额 - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 140 + apps/client/src/app/pages/blog/blog-page.html + 5 - - - Savings Rate - 储蓄率 - apps/client/src/app/components/investment-chart/investment-chart.component.ts - 199 + libs/common/src/lib/routes/routes.ts + 225 - - Security Token - 安全令牌 - - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 11 - - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 251 - + + Discover the latest Ghostfolio updates and insights on personal finance + 了解最新的 Ghostfolio 更新和个人理财见解 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 10 + apps/client/src/app/pages/blog/blog-page.html + 7 - - or - + + As you are already logged in, you cannot access the demo account. + 由于您已经登录,因此无法访问模拟帐户。 - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html + apps/client/src/app/pages/demo/demo-page.component.ts 35 + + + Frequently Asked Questions (FAQ) + 常见问题 (FAQ) - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 31 + apps/client/src/app/app.component.html + 83 - apps/client/src/app/pages/landing/landing-page.html - 47 + apps/client/src/app/pages/about/overview/about-overview-page.html + 164 - apps/client/src/app/pages/landing/landing-page.html - 450 + apps/client/src/app/pages/faq/overview/faq-overview-page.routes.ts + 12 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 97 + libs/common/src/lib/routes/routes.ts + 251 + + + Features + 功能 - apps/client/src/app/pages/register/register-page.html - 30 + apps/client/src/app/app.component.html + 79 - apps/client/src/app/pages/webauthn/webauthn-page.html - 29 + apps/client/src/app/components/header/header.component.html + 361 - - - Sign in with Internet Identity - 使用互联网身份登录 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 42 + apps/client/src/app/pages/features/features-page.html + 5 - - - Sign in with Google - 使用 Google 登录 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 52 + libs/common/src/lib/routes/routes.ts + 256 - - Stay signed in - 保持登录 + + Check out the numerous features of Ghostfolio to manage your wealth + 查看 Ghostfolio 的众多功能来管理您的财富 - apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html - 61 + apps/client/src/app/pages/features/features-page.html + 7 - - Time in Market - 上市时间 + + ETFs + ETF - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 3 + apps/client/src/app/pages/features/features-page.html + 25 - - Buy - + + Bonds + 债券 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 31 + apps/client/src/app/pages/features/features-page.html + 38 - - Sell - + + Wealth Items + 财富项目 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 43 + apps/client/src/app/pages/features/features-page.html + 76 - - Investment - 投资 + + Import and Export + 导入和导出 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 152 + apps/client/src/app/pages/features/features-page.html + 116 + + + Multi-Accounts + 多账户 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 58 + apps/client/src/app/pages/features/features-page.html + 127 - - Absolute Gross Performance - 绝对总业绩 + + Portfolio Calculations + 投资组合计算 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 70 + apps/client/src/app/pages/features/features-page.html + 141 - - Fees - 费用 + + Dark Mode + 深色模式 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 187 + apps/client/src/app/pages/features/features-page.html + 233 + + + Market Mood + 市场情绪 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 84 + apps/client/src/app/pages/features/features-page.html + 215 + + + Static Analysis + 静态分析 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + apps/client/src/app/pages/features/features-page.html + 179 - - Absolute Net Performance - 绝对净绩效 + + Multi-Language + 多语言 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 102 + apps/client/src/app/pages/features/features-page.html + 259 - - Net Performance - 净绩效 + + Open Source Software + 开源软件 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 117 + apps/client/src/app/pages/features/features-page.html + 295 - - Total Assets - 总资产 + + Get Started + 立即开始 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 143 + apps/client/src/app/pages/features/features-page.html + 320 - - - Valuables - 贵重物品 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 156 + apps/client/src/app/pages/public/public-page.html + 220 - - Emergency Fund - 应急基金 + + Holdings + 持仓 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 168 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 79 - apps/client/src/app/pages/features/features-page.html - 89 + apps/client/src/app/components/home-holdings/home-holdings.html + 4 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 34 + apps/client/src/app/pages/public/public-page.html + 70 - - - Cash - 现金 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 202 + libs/common/src/lib/routes/routes.ts + 90 - - - Assets - 资产 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 215 + libs/common/src/lib/routes/routes.ts + 167 - - Buying Power - 购买力 + + Summary + 汇总 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 228 + apps/client/src/app/components/home-summary/home-summary.html + 2 - - - Excluded from Analysis - 从分析中排除 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 240 + libs/common/src/lib/routes/routes.ts + 105 - - Liabilities - 负债 + + Markets + 市场 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 255 + apps/client/src/app/app.component.html + 61 - apps/client/src/app/pages/features/features-page.html - 102 + apps/client/src/app/components/header/header.component.html + 408 - - - Net Worth - 净值 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 273 + apps/client/src/app/components/home-market/home-market.html + 2 - - - Annualized Performance - 年化业绩 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 285 + apps/client/src/app/components/markets/markets.html + 2 - - - Interest - 利息 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 307 + apps/client/src/app/pages/resources/markets/resources-markets.component.html + 2 - - - Dividend - 股息 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 165 + apps/client/src/app/pages/resources/resources-page.component.ts + 40 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 319 + libs/common/src/lib/routes/routes.ts + 95 - apps/client/src/app/pages/features/features-page.html - 63 + libs/common/src/lib/routes/routes.ts + 100 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + libs/common/src/lib/routes/routes.ts + 261 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 + libs/common/src/lib/routes/routes.ts + 309 - - Please set the amount of your emergency fund. - 请输入您的应急基金金额: + + Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. + Ghostfolio 是一个个人财务仪表板,用于跨多个平台跟踪您的净资产,包括现金、股票、ETF 和加密货币。 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 63 + apps/client/src/app/pages/i18n/i18n-page.html + 5 - - Change - 修改 + + app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 + 应用程序、资产、加密货币、仪表板、etf、财务、管理、绩效、投资组合、软件、股票、交易、财富、web3 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + apps/client/src/app/pages/i18n/i18n-page.html + 10 - - Average Unit Price - 平均单价 + + Open Source Wealth Management Software + 开源财富管理软件 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 87 + apps/client/src/app/pages/i18n/i18n-page.html + 224 - - Minimum Price - 最低价格 + + Manage your wealth like a boss + 像老板一样管理您的财富 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 114 + apps/client/src/app/pages/landing/landing-page.html + 6 - - Maximum Price - 最高价格 + + Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. + Ghostfolio 是一个隐私优先、开源的个人财务仪表板。分解您的资产配置,了解您的净资产并做出可靠的、数据驱动的投资决策。 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 130 + apps/client/src/app/pages/landing/landing-page.html + 10 - - Quantity - 数量 + + Get Started + 开始使用 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 140 + apps/client/src/app/pages/landing/landing-page.html + 42 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 188 + apps/client/src/app/pages/landing/landing-page.html + 447 - libs/ui/src/lib/activities-table/activities-table.component.html - 186 + apps/client/src/app/pages/pricing/pricing-page.html + 351 - - - Report Data Glitch - 报告数据故障 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 334 - - Are you an ambitious investor who needs the full picture? - 您是一位雄心勃勃、需要全面了解的投资者吗? + + Monthly Active Users + 每月活跃用户数 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 14 + apps/client/src/app/pages/landing/landing-page.html + 70 - - Upgrade to Ghostfolio Premium today and gain access to exclusive features to enhance your investment experience: - 立即升级至 Ghostfolio Premium 并获得独家功能,以增强您的投资体验: + + Stars on GitHub + GitHub 上的星星 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 17 + apps/client/src/app/pages/landing/landing-page.html + 88 - - - Portfolio Summary - 投资组合摘要 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 24 + apps/client/src/app/pages/open/open-page.html + 103 + + + Pulls on Docker Hub + Docker Hub 拉取次数 - apps/client/src/app/pages/pricing/pricing-page.html - 57 + apps/client/src/app/pages/landing/landing-page.html + 106 - apps/client/src/app/pages/pricing/pricing-page.html - 213 + apps/client/src/app/pages/open/open-page.html + 117 - - Portfolio Allocations - 投资组合分配 + + As seen in + 如图所示 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 28 + apps/client/src/app/pages/landing/landing-page.html + 115 + + + Protect your assets. Refine your personal investment strategy. + 保护你的资产。完善你的个人投资策略 - apps/client/src/app/pages/features/features-page.html - 161 + apps/client/src/app/pages/landing/landing-page.html + 226 + + + Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. + Ghostfolio 使忙碌的人们能够在不被追踪的情况下跟踪股票、ETF 或加密货币。 - apps/client/src/app/pages/pricing/pricing-page.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 230 + + + 360° View + 360° 视角 - apps/client/src/app/pages/pricing/pricing-page.html - 217 + apps/client/src/app/pages/landing/landing-page.html + 240 - - Performance Benchmarks - 性能基准 + + Get the full picture of your personal finances across multiple platforms. + 跨多个平台全面了解您的个人财务状况。 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 32 + apps/client/src/app/pages/landing/landing-page.html + 243 + + + Web3 Ready + Web3 就绪 - apps/client/src/app/pages/pricing/pricing-page.html - 65 + apps/client/src/app/pages/landing/landing-page.html + 251 + + + Use Ghostfolio anonymously and own your financial data. + 匿名使用 Ghostfolio 并拥有您的财务数据。 - apps/client/src/app/pages/pricing/pricing-page.html - 221 + apps/client/src/app/pages/landing/landing-page.html + 254 - - FIRE Calculator - 财务自由计算器 + + Benefit from continuous improvements through a strong community. + 通过强大的社区不断改进,从中受益。 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 36 + apps/client/src/app/pages/landing/landing-page.html + 264 + + + Why Ghostfolio? + 为什么使用Ghostfolio - apps/client/src/app/pages/pricing/pricing-page.html - 69 + apps/client/src/app/pages/landing/landing-page.html + 272 + + + Ghostfolio is for you if you are... + 如果您符合以下条件,那么 Ghostfolio 适合您... - apps/client/src/app/pages/pricing/pricing-page.html - 225 + apps/client/src/app/pages/landing/landing-page.html + 274 - - Professional Data Provider - 专业数据提供商 + + trading stocks, ETFs or cryptocurrencies on multiple platforms + 在多个平台上交易股票、ETF 或加密货币 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 40 + apps/client/src/app/pages/landing/landing-page.html + 280 + + + pursuing a buy & hold strategy + 采取买入并持有策略 - apps/client/src/app/pages/pricing/pricing-page.html - 240 + apps/client/src/app/pages/landing/landing-page.html + 286 - - and more Features... - 以及更多功能... + + interested in getting insights of your portfolio composition + 有兴趣深入了解您的投资组合构成 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 44 + apps/client/src/app/pages/landing/landing-page.html + 291 + + + valuing privacy and data ownership + 重视隐私和数据所有权 - apps/client/src/app/pages/pricing/pricing-page.html - 85 + apps/client/src/app/pages/landing/landing-page.html + 296 + + + into minimalism + 进入极简主义 - apps/client/src/app/pages/pricing/pricing-page.html - 252 + apps/client/src/app/pages/landing/landing-page.html + 299 - - Get the tools to effectively manage your finances and refine your personal investment strategy. - 获取有效管理财务和完善个人投资策略的工具。 + + caring about diversifying your financial resources + 关心您的财务资源多元化 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 47 + apps/client/src/app/pages/landing/landing-page.html + 303 - - Skip - 跳过 + + interested in financial independence + 对财务独立感兴趣 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 54 + apps/client/src/app/pages/landing/landing-page.html + 307 - - Upgrade Plan - 升级计划 + + saying no to spreadsheets in + 年对电子表格说不 - apps/client/src/app/components/header/header.component.html - 185 + apps/client/src/app/pages/landing/landing-page.html + 311 + + + still reading this list + 仍在阅读此列表 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 61 + apps/client/src/app/pages/landing/landing-page.html + 314 + + + Learn more about Ghostfolio + 了解有关 Ghostfolio 的更多信息 - apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + apps/client/src/app/pages/landing/landing-page.html + 319 + + + What our users are saying + 听听我们的用户怎么说 - apps/client/src/app/pages/pricing/pricing-page.html - 288 + apps/client/src/app/pages/landing/landing-page.html + 328 - - Today - 今天 - - apps/client/src/app/components/toggle/toggle.component.ts - 21 - + + Members from around the globe are using Ghostfolio Premium + 来自世界各地的会员正在使用Ghostfolio 高级版 - libs/ui/src/lib/assistant/assistant.component.ts - 221 + apps/client/src/app/pages/landing/landing-page.html + 367 - - YTD - 年初至今 - - apps/client/src/app/components/toggle/toggle.component.ts - 22 - + + How does Ghostfolio work? + Ghostfolio 如何工作? - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/pages/landing/landing-page.html + 384 - - 1Y - 1年 + + Get started in only 3 steps + 只需 3 步即可开始 - apps/client/src/app/components/toggle/toggle.component.ts - 23 + apps/client/src/app/pages/landing/landing-page.html + 386 + + + Sign up anonymously* + 匿名注册* - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/landing/landing-page.html + 392 - - 5Y - 5年 + + * no e-mail address nor credit card required + * 无需电子邮件地址或信用卡 - apps/client/src/app/components/toggle/toggle.component.ts - 24 + apps/client/src/app/pages/landing/landing-page.html + 394 + + + Add any of your historical transactions + 添加您的任何历史交易 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + apps/client/src/app/pages/landing/landing-page.html + 406 - - Max - 最大限度 + + Get valuable insights of your portfolio composition + 获取有关您的投资组合构成的宝贵见解 - apps/client/src/app/components/toggle/toggle.component.ts - 25 + apps/client/src/app/pages/landing/landing-page.html + 418 + + + Are you ready? + 准备好了吗? - libs/ui/src/lib/assistant/assistant.component.ts - 260 + apps/client/src/app/pages/landing/landing-page.html + 432 - - Grant access - 授予访问权限 + + At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. + 在 Ghostfolio,透明度是我们价值观的核心。我们将源代码发布为开源软件(OSS)下AGPL-3.0许可证我们公开分享平台运营状态的汇总关键指标。 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/pages/open/open-page.html 7 - - Public - 公开 + + (Last 24 hours) + (最近 24 小时) - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 25 + apps/client/src/app/pages/open/open-page.html + 37 - - Granted Access - 授予访问权限 + + Active Users + 活跃用户 - apps/client/src/app/components/user-account-access/user-account-access.html - 7 + apps/client/src/app/pages/open/open-page.html + 40 - - - Please enter your coupon code: - 请输入您的优惠券代码: - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 166 + apps/client/src/app/pages/open/open-page.html + 62 - - Could not redeem coupon code - 无法兑换优惠券代码 + + (Last 30 days) + (最近 30 天) - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 175 + apps/client/src/app/pages/open/open-page.html + 48 - - - Coupon code has been redeemed - 优惠券代码已兑换 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 188 + apps/client/src/app/pages/open/open-page.html + 59 - - Reload - 重新加载 + + New Users + 新用户 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 189 + apps/client/src/app/pages/open/open-page.html + 51 - - per year - 每年 - - apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 - + + Users in Slack community + Slack 社区的用户 - apps/client/src/app/pages/pricing/pricing-page.html - 274 + apps/client/src/app/pages/open/open-page.html + 75 - - Try Premium - 尝试高级版 + + Contributors on GitHub + GitHub 上的贡献者 - apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + apps/client/src/app/pages/open/open-page.html + 89 - - Redeem Coupon - 兑换优惠券 + + (Last 90 days) + (过去 90 天) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + apps/client/src/app/pages/open/open-page.html + 127 - - Auto - 自动 + + Uptime + 正常运行时间 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 38 + apps/client/src/app/pages/open/open-page.html + 132 - - Do you really want to remove this sign in method? - 您确实要删除此登录方法吗? + + Activities + 活动 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 246 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 63 - - - Settings - 设置 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 2 + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 92 - - - Presenter View - 演示者视图 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 7 + apps/client/src/app/components/accounts-table/accounts-table.component.html + 119 - - - Protection for sensitive information like absolute performances and quantity values - 保护绝对性能和数量值等敏感信息 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 207 - - - Base Currency - 基础货币 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 27 + apps/client/src/app/components/admin-tag/admin-tag.component.html + 45 - - - Language - 语言 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 48 + apps/client/src/app/components/admin-users/admin-users.html + 136 - - - Locale - 语言环境 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 123 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 226 - - - Date and number format - 日期和数字格式 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 125 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 337 - - - Appearance - 外貌 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 148 + apps/client/src/app/pages/portfolio/activities/activities-page.html + 4 - - - Auto - 自动 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 162 + libs/common/src/lib/routes/routes.ts + 128 - - Light - 明亮 + + Do you really want to delete these activities? + 您确定要删除这些活动吗? - apps/client/src/app/components/user-account-settings/user-account-settings.html - 163 + libs/ui/src/lib/activities-table/activities-table.component.ts + 250 - - Dark - 黑暗 + + Update activity + 更新活动 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 164 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 10 - - Zen Mode - 极简模式 + + Stocks, ETFs, bonds, cryptocurrencies, commodities + 股票、ETF、债券、加密货币、大宗商品 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 173 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 25 - apps/client/src/app/pages/features/features-page.html - 191 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 65 - - Distraction-free experience for turbulent times - 动荡时期的无干扰体验 + + One-time fee, annual account fees + 一次性费用、年度账户费用 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 174 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 33 - - Biometric Authentication - 生物识别认证 - - apps/client/src/app/components/user-account-settings/user-account-settings.html - 190 - - - - Sign in with fingerprint - 使用指纹登录 + + Distribution of corporate earnings + 企业盈利分配 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 191 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 41 - - Experimental Features - 实验性功能 + + Revenue for lending out money + 放贷收入 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 207 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 49 - - Sneak peek at upcoming functionality - 预览即将推出的功能 + + Mortgages, personal loans, credit cards + 抵押贷款、个人贷款、信用卡 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 208 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 57 - - User ID - 用户身份 + + Luxury items, real estate, private companies + 奢侈品、房地产、私营公司 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 45 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 73 + + + Update Cash Balance + 更新现金余额 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 224 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 112 - - Export Data - 导出数据 + + Unit Price + 单价 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 232 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 214 - - - This feature is currently unavailable. - 此功能目前无法使用。 - apps/client/src/app/core/http-response.interceptor.ts - 53 + libs/ui/src/lib/activities-table/activities-table.component.html + 210 - - Please try again later. - 请稍后再试。 + + Import Activities + 导入活动记录 - apps/client/src/app/core/http-response.interceptor.ts - 55 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 86 - apps/client/src/app/core/http-response.interceptor.ts - 80 + libs/ui/src/lib/activities-table/activities-table.component.html + 9 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 142 + libs/ui/src/lib/activities-table/activities-table.component.html + 371 - - Oops! Something went wrong. - 哎呀!出了些问题。 - - apps/client/src/app/core/http-response.interceptor.ts - 78 - + + Import Dividends + 导入股息 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 140 + 129 - - - Okay - 好的 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 151 + libs/ui/src/lib/activities-table/activities-table.component.html + 29 - apps/client/src/app/core/http-response.interceptor.ts - 81 + libs/ui/src/lib/activities-table/activities-table.component.html + 383 + + + Importing data... + 正在导入数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 167 - - About - 关于 - - apps/client/src/app/pages/about/about-page-routing.module.ts - 51 - + + Import has been completed + 导入已完成 - apps/client/src/app/pages/about/about-page.component.ts - 44 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 176 + + + Validating data... + 验证数据... - apps/client/src/app/pages/about/overview/about-overview-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts + 284 - - Changelog - 更新日志 + + Select Holding + 选择持仓 - apps/client/src/app/pages/about/about-page.component.ts - 49 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 20 + + + Select File + 选择文件 - apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 22 - - License - 许可 + + Holding + 持仓 - apps/client/src/app/pages/about/about-page.component.ts - 54 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 32 - apps/client/src/app/pages/about/license/license-page-routing.module.ts - 13 + libs/ui/src/lib/assistant/assistant.html + 179 - - Privacy Policy - 隐私政策 + + Load Dividends + 加载股息 - apps/client/src/app/pages/about/about-page.component.ts - 62 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 68 + + + Choose or drop a file here + 在此处选择或放置文件 - apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 84 - - Our - 我们的 + + The following file formats are supported: + 支持以下文件格式: - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 6 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 90 - - Discover other exciting Open Source Software projects - 发现其他令人兴奋的开源软件项目 + + Select Dividends + 选择股息 - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 9 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 113 - - Visit - 访问 + + Select Activities + 选择活动 - apps/client/src/app/pages/about/oss-friends/oss-friends-page.html - 28 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 115 - - Accounts - 账户 + + Back + 后退 - apps/client/src/app/pages/accounts/accounts-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 144 - - - Oops, cash balance transfer has failed. - 糟糕,现金余额转账失败。 - apps/client/src/app/pages/accounts/accounts-page.component.ts - 317 + apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html + 178 - - Update account - 更新账户 + + Allocations + 分配 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 8 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 4 - - - Add account - 新增帐户 - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 10 + apps/client/src/app/pages/portfolio/allocations/allocations-page.routes.ts + 12 - - - Account ID - 帐户ID - apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html - 96 + libs/common/src/lib/routes/routes.ts + 133 - - From - + + Proportion of Net Worth + 占净资产的比例 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 11 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 12 - - To - + + By Platform + 按平台 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 32 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 44 - - Transfer - 转移 + + By Currency + 按货币 - apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html - 72 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 63 - - Admin Control - 管理控制 + + By Asset Class + 按资产类别 - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 20 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 85 - - Market Data - 市场数据 + + By Holding + 通过持有 - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 30 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 107 + + + By Sector + 按部门 - apps/client/src/app/pages/admin/admin-page.component.ts - 37 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 130 - - Settings - 设置 + + By Continent + 按大陆 - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 35 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 153 + + + By Market + 按市场 - apps/client/src/app/pages/admin/admin-page.component.ts - 32 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 175 + + + Regions + 区域 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 18 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 198 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 35 + apps/client/src/app/pages/public/public-page.html + 143 - - Users - 用户 + + Developed Markets + 发达市场 - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 40 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 222 - apps/client/src/app/pages/admin/admin-page.component.ts - 47 + apps/client/src/app/pages/public/public-page.html + 160 - - Overview - 概述 + + Emerging Markets + 新兴市场 - apps/client/src/app/pages/admin/admin-page.component.ts - 27 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 231 - apps/client/src/app/pages/home/home-page.component.ts - 37 + apps/client/src/app/pages/public/public-page.html + 169 + + + Other Markets + 其他市场 - apps/client/src/app/pages/resources/resources-page.component.ts - 16 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 240 - apps/client/src/app/pages/zen/zen-page-routing.module.ts - 19 + apps/client/src/app/pages/public/public-page.html + 178 + + + By Account + 按帐户 - apps/client/src/app/pages/zen/zen-page.component.ts - 34 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 286 - - Blog - 博客 + + By ETF Provider + 按 ETF 提供商 - apps/client/src/app/pages/blog/blog-page-routing.module.ts - 13 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 306 - - Discover the latest Ghostfolio updates and insights on personal finance - 了解最新的 Ghostfolio 更新和个人理财见解 + + By Country + 按国家/地区 - apps/client/src/app/pages/blog/blog-page.html - 7 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 264 - - As you are already logged in, you cannot access the demo account. - 由于您已经登录,因此无法访问模拟帐户。 + + Analysis + 分析 - apps/client/src/app/pages/demo/demo-page.component.ts - 35 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 2 + + + libs/common/src/lib/routes/routes.ts + 138 - - Frequently Asked Questions (FAQ) - 常见问题 (FAQ) + + Dividend + 股息 - apps/client/src/app/pages/faq/faq-page-routing.module.ts - 34 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 182 - apps/client/src/app/pages/faq/overview/faq-overview-page-routing.module.ts - 13 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 307 - - - Frequently Asked Questions (FAQ) - 常见问题 (FAQ) - apps/client/src/app/pages/faq/overview/faq-overview-page.html - 4 + apps/client/src/app/pages/features/features-page.html + 63 - apps/client/src/app/pages/faq/saas/saas-page.html - 4 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 202 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html - 4 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 73 - - - Features - 功能 - apps/client/src/app/app-routing.module.ts - 74 + libs/ui/src/lib/i18n.ts + 36 - - Check out the numerous features of Ghostfolio to manage your wealth - 查看 Ghostfolio 的众多功能来管理您的财富 + + Deposit + 存款 - apps/client/src/app/pages/features/features-page.html - 6 + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 360 - - Stocks - 股票 + + Monthly + 每月 - apps/client/src/app/pages/features/features-page.html - 15 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 88 - - ETFs - ETF + + Yearly + 每年 - apps/client/src/app/pages/features/features-page.html - 25 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 89 - - Bonds - 债券 + + Top + 顶部 - apps/client/src/app/pages/features/features-page.html - 38 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 239 - - Cryptocurrencies - 加密货币 + + Bottom + 底部 - apps/client/src/app/pages/features/features-page.html - 51 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 - - Wealth Items - 财富项目 + + Portfolio Evolution + 投资组合演变 - apps/client/src/app/pages/features/features-page.html - 76 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 341 - - Import and Export - 导入和导出 + + Investment Timeline + 投资时间表 - apps/client/src/app/pages/features/features-page.html - 115 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 368 - - Multi-Accounts - 多账户 + + Current Streak + 当前连胜 - apps/client/src/app/pages/features/features-page.html - 127 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 389 - - Portfolio Calculations - 投资组合计算 + + Longest Streak + 最长连续纪录 - apps/client/src/app/pages/features/features-page.html - 141 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 398 - - Dark Mode - 深色模式 + + Dividend Timeline + 股息时间表 - apps/client/src/app/pages/features/features-page.html - 178 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 425 - - Market Mood - 市场情绪 + + FIRE + 财务独立 - apps/client/src/app/pages/features/features-page.html - 206 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 4 - - Static Analysis - 静态分析 + + Calculator + 计算器 - apps/client/src/app/pages/features/features-page.html - 225 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 7 - - Multi-Language - 多语言 + + 4% Rule + 4%规则 - apps/client/src/app/pages/features/features-page.html - 242 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 - - Open Source Software - 开源软件 + + Currency Cluster Risks + 货币集群风险 - apps/client/src/app/pages/features/features-page.html - 278 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 93 - - Get Started - 立即开始 + + Account Cluster Risks + 账户集群风险 - apps/client/src/app/pages/features/features-page.html - 303 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 141 + + + Holdings + 持仓 - apps/client/src/app/pages/public/public-page.html - 220 + libs/ui/src/lib/assistant/assistant.html + 82 - - Holdings - 控股 - - apps/client/src/app/pages/home/home-page-routing.module.ts - 23 - - - apps/client/src/app/pages/home/home-page-routing.module.ts - 28 - - - apps/client/src/app/pages/home/home-page.component.ts - 42 - - - apps/client/src/app/pages/zen/zen-page.component.ts - 39 - - - - Summary - 概括 + + Pricing + 价格 - apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + apps/client/src/app/app.component.html + 99 - apps/client/src/app/pages/home/home-page.component.ts - 47 + apps/client/src/app/components/header/header.component.html + 105 - - - Markets - 市场 - apps/client/src/app/pages/home/home-page-routing.module.ts - 38 + apps/client/src/app/components/header/header.component.html + 313 - apps/client/src/app/pages/home/home-page.component.ts - 52 + apps/client/src/app/components/header/header.component.html + 389 - apps/client/src/app/pages/markets/markets-page-routing.module.ts + apps/client/src/app/pages/pricing/pricing-page-routing.module.ts 13 - apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 287 - apps/client/src/app/pages/resources/resources-page.component.ts - 26 + libs/common/src/lib/routes/routes.ts + 271 - - Ghostfolio is a personal finance dashboard to keep track of your net worth including cash, stocks, ETFs and cryptocurrencies across multiple platforms. - Ghostfolio 是一个个人财务仪表板,用于跨多个平台跟踪您的净资产,包括现金、股票、ETF 和加密货币。 + + Pricing Plans + 定价计划 - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/pricing/pricing-page.html 4 - - app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3 - 应用程序、资产、加密货币、仪表板、etf、财务、管理、绩效、投资组合、软件、股票、交易、财富、web3 + + Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. + 我们的官方 Ghostfolio Premium 云产品是最简单的入门方法。由于它节省了时间,这对于大多数人来说将是最佳选择。收入用于支付托管基础设施的成本和资助持续开发。 - apps/client/src/app/pages/i18n/i18n-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 7 - - Open Source Wealth Management Software - 开源财富管理软件 + + If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. + 如果你希望在自己的基础设施上运行 Ghostfolio,请查看源代码和进一步的说明GitHub - apps/client/src/app/pages/i18n/i18n-page.html + apps/client/src/app/pages/pricing/pricing-page.html 14 - - Manage your wealth like a boss - 像老板一样管理您的财富 + + For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. + 适合喜欢在自己的基础设施上运行 Ghostfolio 的精通技术的投资者。 - apps/client/src/app/pages/landing/landing-page.html - 5 + apps/client/src/app/pages/pricing/pricing-page.html + 26 - - Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. - Ghostfolio 是一个隐私优先、开源的个人财务仪表板。分解您的资产配置,了解您的净资产并做出可靠的、数据驱动的投资决策。 + + Unlimited Transactions + 无限交易 - apps/client/src/app/pages/landing/landing-page.html - 9 + apps/client/src/app/pages/pricing/pricing-page.html + 32 - - - Get Started - 开始使用 - apps/client/src/app/pages/landing/landing-page.html - 41 + apps/client/src/app/pages/pricing/pricing-page.html + 121 apps/client/src/app/pages/pricing/pricing-page.html - 324 + 193 - - Live Demo - 现场演示 + + Unlimited Accounts + 无限账户 - apps/client/src/app/pages/landing/landing-page.html - 49 + apps/client/src/app/pages/pricing/pricing-page.html + 36 - apps/client/src/app/pages/landing/landing-page.html - 451 + apps/client/src/app/pages/pricing/pricing-page.html + 125 - - - Monthly Active Users - 每月活跃用户数 - apps/client/src/app/pages/landing/landing-page.html - 70 + apps/client/src/app/pages/pricing/pricing-page.html + 197 - - Stars on GitHub - GitHub 上的星星 + + Portfolio Performance + 投资组合表现 - apps/client/src/app/pages/landing/landing-page.html - 88 + apps/client/src/app/pages/pricing/pricing-page.html + 40 - apps/client/src/app/pages/open/open-page.html - 103 + apps/client/src/app/pages/pricing/pricing-page.html + 129 + + + apps/client/src/app/pages/pricing/pricing-page.html + 201 - - Pulls on Docker Hub - 拉动 Docker Hub + + Data Import and Export + 数据导入与导出 - apps/client/src/app/pages/landing/landing-page.html - 106 + apps/client/src/app/pages/pricing/pricing-page.html + 60 - apps/client/src/app/pages/open/open-page.html - 117 + apps/client/src/app/pages/pricing/pricing-page.html + 133 - - - As seen in - 如图所示 - apps/client/src/app/pages/landing/landing-page.html - 115 + apps/client/src/app/pages/pricing/pricing-page.html + 221 - - Protect your assets. Refine your personal investment strategy. - 保护你的资产。完善你的个人投资策略 + + Community Support + 社区支持 - apps/client/src/app/pages/landing/landing-page.html - 225 + apps/client/src/app/pages/pricing/pricing-page.html + 77 - - Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. - Ghostfolio 使忙碌的人们能够在不被追踪的情况下跟踪股票、ETF 或加密货币。 + + Self-hosted, update manually. + 自托管,手动更新。 - apps/client/src/app/pages/landing/landing-page.html - 229 + apps/client/src/app/pages/pricing/pricing-page.html + 81 - - 360° View - 360° 视角 + + Free + 自由的 - apps/client/src/app/pages/landing/landing-page.html - 240 + apps/client/src/app/pages/pricing/pricing-page.html + 83 - - - Get the full picture of your personal finances across multiple platforms. - 跨多个平台全面了解您的个人财务状况。 - apps/client/src/app/pages/landing/landing-page.html - 242 + apps/client/src/app/pages/pricing/pricing-page.html + 146 - - Web3 Ready - Web3 就绪 + + For new investors who are just getting started with trading. + 适合刚开始交易的新投资者。 - apps/client/src/app/pages/landing/landing-page.html - 251 + apps/client/src/app/pages/pricing/pricing-page.html + 116 - - Use Ghostfolio anonymously and own your financial data. - 匿名使用 Ghostfolio 并拥有您的财务数据。 + + Fully managed Ghostfolio cloud offering. + 完全托管的 Ghostfolio 云产品。 - apps/client/src/app/pages/landing/landing-page.html - 253 + apps/client/src/app/pages/pricing/pricing-page.html + 144 - - - Open Source - 开源 - apps/client/src/app/pages/landing/landing-page.html - 261 + apps/client/src/app/pages/pricing/pricing-page.html + 270 - - Benefit from continuous improvements through a strong community. - 通过强大的社区不断改进,从中受益。 + + For ambitious investors who need the full picture of their financial assets. + 适合需要全面了解其金融资产的雄心勃勃的投资者。 - apps/client/src/app/pages/landing/landing-page.html - 263 + apps/client/src/app/pages/pricing/pricing-page.html + 187 - - Why Ghostfolio? - 为什么使用Ghostfolio + + Email and Chat Support + 电子邮件和聊天支持 - apps/client/src/app/pages/landing/landing-page.html - 272 + apps/client/src/app/pages/pricing/pricing-page.html + 266 - - Ghostfolio is for you if you are... - 如果您符合以下条件,那么 Ghostfolio 适合您... + + Renew Plan + 更新计划 - apps/client/src/app/pages/landing/landing-page.html - 273 + apps/client/src/app/components/header/header.component.html + 191 - - - trading stocks, ETFs or cryptocurrencies on multiple platforms - 在多个平台上交易股票、ETF 或加密货币 - apps/client/src/app/pages/landing/landing-page.html - 280 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 18 - - - pursuing a buy & hold strategy - 采取买入并持有策略 - apps/client/src/app/pages/landing/landing-page.html - 286 + apps/client/src/app/pages/pricing/pricing-page.html + 297 - - interested in getting insights of your portfolio composition - 有兴趣深入了解您的投资组合构成 + + One-time payment, no auto-renewal. + 一次性付款,无自动续订。 - apps/client/src/app/pages/landing/landing-page.html - 291 + apps/client/src/app/pages/pricing/pricing-page.html + 303 - - valuing privacy and data ownership - 重视隐私和数据所有权 + + It’s free. + 免费。 - apps/client/src/app/pages/landing/landing-page.html - 296 + apps/client/src/app/pages/pricing/pricing-page.html + 353 - - into minimalism - 进入极简主义 + + Hello, has shared a Portfolio with you! + 你好,分享了一个投资组合给你! - apps/client/src/app/pages/landing/landing-page.html - 299 + apps/client/src/app/pages/public/public-page.html + 5 - - caring about diversifying your financial resources - 关心您的财务资源多元化 + + Continents + 大陆 - apps/client/src/app/pages/landing/landing-page.html - 303 + apps/client/src/app/pages/public/public-page.html + 124 - - interested in financial independence - 对财务独立感兴趣 + + Ghostfolio empowers you to keep track of your wealth. + Ghostfolio 使您能够跟踪您的财富。 - apps/client/src/app/pages/landing/landing-page.html - 307 + apps/client/src/app/pages/public/public-page.html + 216 - - saying no to spreadsheets in - 对电子表格说不 + + Registration + 注册 - apps/client/src/app/pages/landing/landing-page.html - 311 + apps/client/src/app/components/admin-users/admin-users.html + 98 - - - still reading this list - 仍在阅读此列表 - apps/client/src/app/pages/landing/landing-page.html - 314 + libs/common/src/lib/routes/routes.ts + 281 - - Learn more about Ghostfolio - 了解有关 Ghostfolio 的更多信息 + + Continue with Internet Identity + 继续互联网身份 - apps/client/src/app/pages/landing/landing-page.html - 319 + apps/client/src/app/pages/register/register-page.html + 42 - - What our users are saying - 我们的什么用户正在说 + + Continue with Google + 继续使用谷歌 - apps/client/src/app/pages/landing/landing-page.html - 327 + apps/client/src/app/pages/register/register-page.html + 53 - - Members from around the globe are using Ghostfolio Premium - 来自世界各地的会员正在使用Ghostfolio 高级版 + + Copy to clipboard + 复制到剪贴板 - apps/client/src/app/pages/landing/landing-page.html - 366 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 88 - - How does Ghostfolio work? - 如何幽灵作品集工作? + + Personal Finance Tools + 个人理财工具 - apps/client/src/app/pages/landing/landing-page.html - 383 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 351 - - - Get started in only 3 steps - 只需 3 步即可开始 - apps/client/src/app/pages/landing/landing-page.html - 386 + libs/common/src/lib/routes/routes.ts + 329 - - Sign up anonymously* - 匿名注册* + + open-source-alternative-to + open-source-alternative-to + kebab-case - apps/client/src/app/pages/landing/landing-page.html - 392 + libs/common/src/lib/routes/routes.ts + 320 - - - * no e-mail address nor credit card required - * 无需电子邮件地址或信用卡 - apps/client/src/app/pages/landing/landing-page.html - 394 + libs/common/src/lib/routes/routes.ts + 324 - - Add any of your historical transactions - 添加您的任何历史交易 + + Discover Open Source Alternatives for Personal Finance Tools + 发现个人理财工具的开源替代品 - apps/client/src/app/pages/landing/landing-page.html - 405 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 5 - - Get valuable insights of your portfolio composition - 获取有关您的投资组合构成的宝贵见解 + + This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. + 此概述页面包含与开源替代方案相比的精选个人理财工具集合Ghostfolio。如果您重视透明度、数据隐私和社区协作,Ghostfolio 提供了一个绝佳的机会来控制您的财务管理。 - apps/client/src/app/pages/landing/landing-page.html - 417 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 9 - - Are you ready? - 准备好? + + Explore the links below to compare a variety of personal finance tools with Ghostfolio. + 浏览下面的链接,将各种个人理财工具与 Ghostfolio 进行比较。 - apps/client/src/app/pages/landing/landing-page.html - 431 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 17 - - At Ghostfolio, transparency is at the core of our values. We publish the source code as open source software (OSS) under the AGPL-3.0 license and we openly share aggregated key metrics of the platform’s operational status. - 在 Ghostfolio,透明度是我们价值观的核心。我们将源代码发布为开源软件(OSS)下AGPL-3.0许可证我们公开分享平台运营状态的汇总关键指标。 + + Open Source Alternative to + 的开源替代品 - apps/client/src/app/pages/open/open-page.html - 6 + apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html + 43 - - (Last 24 hours) - (最近 24 小时) + + The Open Source Alternative to + 开源替代方案 - apps/client/src/app/pages/open/open-page.html - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 8 - - Active Users - 活跃用户 - - apps/client/src/app/pages/open/open-page.html - 40 - + + Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. + 您是否正在寻找开源替代方案幽灵作品集是一个强大的投资组合管理工具,为个人提供一个全面的平台来跟踪、分析和优化他们的投资。无论您是经验丰富的投资者还是刚刚起步的投资者,Ghostfolio 都提供直观的用户界面和广泛的功能帮助您做出明智的决定并掌控您的财务未来。 - apps/client/src/app/pages/open/open-page.html - 62 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 19 - - (Last 30 days) - (最近 30 天) + + Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. + Ghostfolio 是一款开源软件 (OSS),提供了一种经济高效的替代方案使其特别适合预算紧张的个人,例如追求财务独立,提前退休(FIRE) 。通过利用开发者社区和个人理财爱好者的集体努力,Ghostfolio 不断增强其功能、安全性和用户体验。 - apps/client/src/app/pages/open/open-page.html - 48 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 33 + + + Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. + 让我们更深入地了解 Ghostfolio 与下面的比较表可帮助您全面了解 Ghostfolio 相对于其他产品的定位。我们将探讨功能、数据隐私、定价等各个方面,让您根据个人需求做出明智的选择。 - apps/client/src/app/pages/open/open-page.html - 59 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 44 - - New Users - 新用户 + + Ghostfolio vs comparison table + Ghostfolio vs比较表 - apps/client/src/app/pages/open/open-page.html - 51 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 55 - - Users in Slack community - Slack 社区的用户 + + Founded + 成立 - apps/client/src/app/pages/open/open-page.html - 75 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 77 - - Contributors on GitHub - GitHub 上的贡献者 + + Origin + 来源 - apps/client/src/app/pages/open/open-page.html - 89 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 82 - - (Last 90 days) - (过去 90 天) + + Region + 地区 - apps/client/src/app/pages/open/open-page.html - 127 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 87 - - Uptime - 正常运行时间 + + Available in + 可用于 - apps/client/src/app/pages/open/open-page.html - 132 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 109 - - Activities - 活动 + + ✅ Yes + ✅ 是的 - apps/client/src/app/pages/portfolio/activities/activities-page-routing.module.ts - 13 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 140 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 157 - - - Do you really want to delete these activities? - 您真的要删除所有活动吗? - libs/ui/src/lib/activities-table/activities-table.component.ts - 219 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 179 - - - Update activity - 更新活动 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 10 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 196 - - - Stocks, ETFs, bonds, cryptocurrencies, commodities - 股票、ETF、债券、加密货币、大宗商品 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 218 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 65 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 235 - - - One-time fee, annual account fees - 一次性费用、年度账户费用 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 257 - - - Distribution of corporate earnings - 企业盈利分配 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 41 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 274 - - Revenue for lending out money - 放贷收入 + + ❌ No + ❌ 没有 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 49 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 147 - - - Mortgages, personal loans, credit cards - 抵押贷款、个人贷款、信用卡 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 57 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 164 - - - Luxury items, real estate, private companies - 奢侈品、房地产、私营公司 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 73 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 186 - - - Account - 帐户 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 85 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 203 - libs/ui/src/lib/activities-table/activities-table.component.html - 308 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 225 - libs/ui/src/lib/assistant/assistant.html - 107 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 242 - - - Update Cash Balance - 更新现金余额 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 112 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 264 - - - Unit Price - 单价 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 213 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 281 + + + Self-Hosting + 自托管 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 171 + + + Use anonymously + 匿名使用 - libs/ui/src/lib/activities-table/activities-table.component.html + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html 210 - - Oops! Could not get the historical exchange rate from - 哎呀!无法从以下来源获取历史汇率 + + Free Plan + 免费计划 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 249 - - Fee - 费用 + + Starting from + 从...开始 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 289 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 294 + + + Notes + 笔记 - libs/ui/src/lib/activities-table/activities-table.component.html - 234 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 302 - - Oops! Could not get the historical exchange rate from - 哎呀!无法获取历史汇率 + + Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. + 请注意,在 Ghostfolio 与的比较表中提供的信息基于我们的独立研究和分析。该网站不隶属于或比较中提到的任何其他产品。随着个人理财工具格局的不断发展,直接从相应的产品页面验证任何具体的细节或变化至关重要。数据需要刷新吗?帮助我们在GitHub 上维护准确的数据。 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 312 - - Import Activities - 导入活动 + + Ready to take your investments to the next level? + 准备好将您的投资提升到新的高度了吗? - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 45 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 325 - - Import Dividends - 导入股息 + + Effortlessly track, analyze, and visualize your wealth with Ghostfolio. + 使用 Ghostfolio 轻松跟踪、分析和可视化您的财富。 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 86 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 329 - - Importing data... - 正在导入数据... + + Switzerland + 瑞士 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 124 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 57 - - - Import has been completed - 导入已完成 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 132 + libs/ui/src/lib/i18n.ts + 96 - - Validating data... - 验证数据... + + Global + 全球的 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 238 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 58 - - - Select Holding - 选择控股 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 20 + libs/ui/src/lib/i18n.ts + 16 - - Select File - 选择文件 + + Resources + 资源 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 22 + apps/client/src/app/app.component.html + 64 - - - Holding - 保持 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 32 + apps/client/src/app/components/header/header.component.html + 88 - libs/ui/src/lib/assistant/assistant.html - 127 + apps/client/src/app/components/header/header.component.html + 301 - - - Load Dividends - 加载股息 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 68 + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 4 - - - Choose or drop a file here - 在此处选择或放置文件 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 84 + libs/common/src/lib/routes/routes.ts + 332 - - The following file formats are supported: - 支持以下文件格式: + + Membership + 会员资格 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 90 + libs/common/src/lib/routes/routes.ts + 31 - - - Select Dividends - 选择股息 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 113 + libs/ui/src/lib/membership-card/membership-card.component.html + 37 - - Select Activities - 选择活动 + + Access + 权限 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 115 + libs/common/src/lib/routes/routes.ts + 26 - - Back - 后退 + + My Ghostfolio + 我的 Ghostfolio - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 144 + apps/client/src/app/components/header/header.component.html + 277 - apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html - 178 + apps/client/src/app/pages/user-account/user-account-page.routes.ts + 33 - - Allocations - 分配 + + Oops, authentication has failed. + 糟糕,身份验证失败。 - apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts - 13 + apps/client/src/app/pages/webauthn/webauthn-page.html + 19 + + + Try again + 再试一次 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + apps/client/src/app/pages/webauthn/webauthn-page.html + 27 - - Allocations - 分配 + + Go back to Home Page + 返回首页 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 4 + apps/client/src/app/pages/webauthn/webauthn-page.html + 33 - - Proportion of Net Worth - 占净资产的比例 + + Do you really want to delete this account balance? + 您确实要删除该帐户余额吗? - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 12 + libs/ui/src/lib/account-balances/account-balances.component.ts + 120 - - By Platform - 按平台 + + Export Activities + 导出活动记录 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 44 + libs/ui/src/lib/activities-table/activities-table.component.html + 41 - - - By Currency - 按货币 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 63 + libs/ui/src/lib/activities-table/activities-table.component.html + 396 - - By Asset Class - 按资产类别 + + Export Drafts as ICS + 将汇票导出为 ICS - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 85 + libs/ui/src/lib/activities-table/activities-table.component.html + 54 - - - By Holding - 通过持有 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 107 + libs/ui/src/lib/activities-table/activities-table.component.html + 409 - - By Sector - 按部门 + + Draft + 草稿 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 130 + libs/ui/src/lib/activities-table/activities-table.component.html + 145 - - By Continent - 按大陆 + + Clone + 克隆 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 153 + libs/ui/src/lib/activities-table/activities-table.component.html + 436 - - By Market - 按市场 + + Export Draft as ICS + 将汇票导出为 ICS - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 175 + libs/ui/src/lib/activities-table/activities-table.component.html + 446 - - Regions - 区域 + + Do you really want to delete this activity? + 您确实要删除此活动吗? - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 198 + libs/ui/src/lib/activities-table/activities-table.component.ts + 260 + + + Asset Profiles + 资产概况 - apps/client/src/app/pages/public/public-page.html - 143 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 106 - - Developed Markets - 发达市场 + + 50-Day Trend + 50 天趋势 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 222 + libs/ui/src/lib/benchmark/benchmark.component.html + 25 + + + 200-Day Trend + 200天趋势 - apps/client/src/app/pages/public/public-page.html - 160 + libs/ui/src/lib/benchmark/benchmark.component.html + 54 - - Emerging Markets - 新兴市场 + + Last All Time High + 上次历史最高纪录 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 231 + libs/ui/src/lib/benchmark/benchmark.component.html + 83 + + + Change from All Time High + 较历史最高纪录涨跌 - apps/client/src/app/pages/public/public-page.html - 169 + libs/ui/src/lib/benchmark/benchmark.component.html + 110 - - Other Markets - 其他市场 + + from ATH + 从 ATH - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 240 + libs/ui/src/lib/benchmark/benchmark.component.html + 112 + + + Market data provided by + 市场数据提供者 - apps/client/src/app/pages/public/public-page.html - 178 + libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html + 2 - - No data available - 无可用数据 + + Savings Rate per Month + 每月储蓄率 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 250 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 10 + + + + Annual Interest Rate + 年利率 + + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 21 + + + Retirement Date + 退休日期 - apps/client/src/app/pages/public/public-page.html - 188 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 32 + + + Projected Total Amount + 预计总额 - libs/ui/src/lib/benchmark/benchmark.component.html - 137 + libs/ui/src/lib/fire-calculator/fire-calculator.component.html + 59 + + + + Interest + 利息 + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 295 + + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 370 + + + libs/ui/src/lib/i18n.ts + 38 + + + + Savings + 储蓄 + + libs/ui/src/lib/fire-calculator/fire-calculator.component.ts + 380 + + + + Allocation + 分配 + + apps/client/src/app/components/accounts-table/accounts-table.component.html + 241 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 98 libs/ui/src/lib/top-holdings/top-holdings.component.html - 181 + 40 + + + libs/ui/src/lib/top-holdings/top-holdings.component.html + 116 - - By Account - 按帐户 + + Show all + 显示所有 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 286 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 197 - - By ETF Provider - 按 ETF 提供商 + + Account + 帐户 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 85 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 308 + + + libs/ui/src/lib/assistant/assistant.html + 157 + + + libs/ui/src/lib/i18n.ts + 4 + + + + Asia-Pacific + 亚太 + + libs/ui/src/lib/i18n.ts + 5 + + + + Asset Class + 资产类别 + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 115 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 216 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 306 + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 237 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 290 + + + libs/ui/src/lib/assistant/assistant.html + 218 + + + libs/ui/src/lib/i18n.ts + 6 + - - By Country - 按国家/地区 + + Asset Sub Class + 资产子类别 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 264 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 124 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 225 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 246 + + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 306 + + + libs/ui/src/lib/i18n.ts + 7 - - Analysis - 分析 + + Core + 核心 - apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 10 + + + Switch to Ghostfolio Premium or Ghostfolio Open Source easily + 轻松切换到 Ghostfolio Premium 或 Ghostfolio Open Source - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 34 + libs/ui/src/lib/i18n.ts + 12 - - Dividend - 股息 + + Switch to Ghostfolio Premium easily + 轻松切换到 Ghostfolio Premium - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 37 + libs/ui/src/lib/i18n.ts + 13 + + + Switch to Ghostfolio Open Source or Ghostfolio Basic easily + 轻松切换到 Ghostfolio Open Source 或 Ghostfolio Basic libs/ui/src/lib/i18n.ts - 36 + 14 - - Deposit - 订金 + + Emergency Fund + 应急基金 - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 361 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 156 + + + apps/client/src/app/pages/features/features-page.html + 89 + + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 69 + + + libs/ui/src/lib/i18n.ts + 15 + + + + Grant + 授予 + + libs/ui/src/lib/i18n.ts + 17 + + + + Higher Risk + 风险较高 + + libs/ui/src/lib/i18n.ts + 18 + + + + This activity already exists. + 这项活动已经存在。 + + libs/ui/src/lib/i18n.ts + 19 + + + + Japan + 日本 + + libs/ui/src/lib/i18n.ts + 89 + + + + Lower Risk + 降低风险 + + libs/ui/src/lib/i18n.ts + 20 + + + + Month + + + libs/ui/src/lib/i18n.ts + 21 + + + + Months + 几个月 + + libs/ui/src/lib/i18n.ts + 22 + + + + Other + 其他 + + libs/ui/src/lib/i18n.ts + 23 + + + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 412 + + + + Preset + 预设 + + libs/ui/src/lib/i18n.ts + 25 + + + + Retirement Provision + 退休金 + + libs/ui/src/lib/i18n.ts + 26 + + + + Satellite + 卫星 + + libs/ui/src/lib/i18n.ts + 27 + + + + Symbol + 代码 + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 46 + + + apps/client/src/app/components/admin-market-data/admin-market-data.html + 75 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 155 + + + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 39 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 310 + + + libs/ui/src/lib/i18n.ts + 28 + + + + Tag + 标签 + + libs/ui/src/lib/assistant/assistant.html + 207 + + + libs/ui/src/lib/i18n.ts + 29 + + + + Year + + + libs/ui/src/lib/i18n.ts + 30 + + + + Years + + + libs/ui/src/lib/i18n.ts + 31 + + + + Buy + 买入 + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 31 + + + libs/ui/src/lib/i18n.ts + 35 + + + + Fee + 费用 + + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 262 + + + libs/ui/src/lib/activities-table/activities-table.component.html + 234 + + + libs/ui/src/lib/i18n.ts + 37 + + + + Valuable + 贵重物品 + + libs/ui/src/lib/i18n.ts + 39 + + + + Liability + 负债 + + libs/ui/src/lib/i18n.ts + 40 + + + + Sell + 卖出 + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 43 + + + libs/ui/src/lib/i18n.ts + 41 + + + + Cash + 现金 + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 190 + + + libs/ui/src/lib/i18n.ts + 53 + + + + Commodity + 商品 + + libs/ui/src/lib/i18n.ts + 45 + + + + Equity + 股权 + + apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html + 58 + + + libs/ui/src/lib/i18n.ts + 46 + + + + Fixed Income + 固定收益 + + libs/ui/src/lib/i18n.ts + 47 + + + + Real Estate + 房地产 + + libs/ui/src/lib/i18n.ts + 49 + + + + Bond + 债券 + + libs/ui/src/lib/i18n.ts + 52 + + + + Cryptocurrency + 加密货币 + + libs/ui/src/lib/i18n.ts + 55 + + + + ETF + 交易所交易基金 + + libs/ui/src/lib/i18n.ts + 56 + + + + Mutual Fund + 共同基金 + + libs/ui/src/lib/i18n.ts + 57 + + + + Precious Metal + 贵金属 + + libs/ui/src/lib/i18n.ts + 58 - - Monthly - 每月 + + Private Equity + 私募股权 - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 49 + libs/ui/src/lib/i18n.ts + 59 - - Yearly - 每年 + + Stock + 股票 - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 50 + libs/ui/src/lib/i18n.ts + 60 - - Analysis - 分析 + + Africa + 非洲 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 2 + libs/ui/src/lib/i18n.ts + 67 - - Top - 顶部 + + Asia + 亚洲 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 165 + libs/ui/src/lib/i18n.ts + 68 - - Bottom - 底部 + + Europe + 欧洲 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 214 + libs/ui/src/lib/i18n.ts + 69 - - Portfolio Evolution - 投资组合演变 + + North America + 北美 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 267 + libs/ui/src/lib/i18n.ts + 70 - - Investment Timeline - 投资时间表 + + Oceania + 大洋洲 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 294 + libs/ui/src/lib/i18n.ts + 71 - - Current Streak - 当前连胜 + + South America + 南美洲 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 315 + libs/ui/src/lib/i18n.ts + 72 - - Longest Streak - 最长连续纪录 + + Extreme Fear + 极度恐惧 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 324 + libs/ui/src/lib/i18n.ts + 103 - - Dividend Timeline - 股息时间表 + + Extreme Greed + 极度贪婪 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 351 + libs/ui/src/lib/i18n.ts + 104 - - FIRE - 财务独立 + + Neutral + 中性的 - apps/client/src/app/pages/portfolio/fire/fire-page.html - 4 + libs/ui/src/lib/i18n.ts + 107 - - Calculator - 计算器 + + Valid until + 有效期至 - apps/client/src/app/pages/portfolio/fire/fire-page.html - 7 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 74 - - - 4% Rule - 4%规则 - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 + libs/ui/src/lib/membership-card/membership-card.component.html + 42 - - Currency Cluster Risks - 货币集群风险 + + Time to add your first activity. + 是时候添加您的第一个活动了。 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 58 + libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html + 12 - - Account Cluster Risks - 账户集群风险 + + No data available + 无可用数据 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 106 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 250 - - - Holdings - 控股 - apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html - 79 + apps/client/src/app/pages/public/public-page.html + 188 - apps/client/src/app/components/home-holdings/home-holdings.html - 4 + libs/ui/src/lib/benchmark/benchmark.component.html + 202 - apps/client/src/app/pages/public/public-page.html - 70 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 414 - libs/ui/src/lib/assistant/assistant.html - 46 + libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts + 427 - - - Pricing - 价钱 - apps/client/src/app/pages/pricing/pricing-page-routing.module.ts - 13 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 181 - - Pricing Plans - 定价计划 + + If a translation is missing, kindly support us in extending it here. + 如果翻译缺失,欢迎在这里进行扩展。 - apps/client/src/app/pages/pricing/pricing-page.html - 4 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 59 - - Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. - 我们的官方 Ghostfolio Premium 云产品是最简单的入门方法。由于它节省了时间,这对于大多数人来说将是最佳选择。收入用于支付托管基础设施的成本和资助持续开发。 + + Date Range + 日期范围 - apps/client/src/app/pages/pricing/pricing-page.html - 6 + libs/ui/src/lib/assistant/assistant.html + 143 - - If you prefer to run Ghostfolio on your own infrastructure, please find the source code and further instructions on GitHub. - 如果你希望在自己的基础设施上运行 Ghostfolio,请查看源代码和进一步的说明GitHub + + The current market price is + 当前市场价格为 - apps/client/src/app/pages/pricing/pricing-page.html - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 637 - - For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. - 适合喜欢在自己的基础设施上运行 Ghostfolio 的精通技术的投资者。 + + Test + 测试 - apps/client/src/app/pages/pricing/pricing-page.html - 38 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 481 - - Unlimited Transactions - 无限交易 + + Oops! Could not grant access. + 哎呀!无法授予访问权限。 - apps/client/src/app/pages/pricing/pricing-page.html - 45 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts + 91 + + + Restricted view + 受限视图 - apps/client/src/app/pages/pricing/pricing-page.html - 134 + apps/client/src/app/components/access-table/access-table.component.html + 26 - apps/client/src/app/pages/pricing/pricing-page.html - 201 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 34 - - Unlimited Accounts - 无限账户 + + Permission + 权限 - apps/client/src/app/pages/pricing/pricing-page.html - 49 + apps/client/src/app/components/access-table/access-table.component.html + 18 - apps/client/src/app/pages/pricing/pricing-page.html - 138 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 32 + + + Private + 私人的 - apps/client/src/app/pages/pricing/pricing-page.html - 205 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 24 - - Portfolio Performance - 投资组合表现 + + Job Queue + 任务队列 - apps/client/src/app/pages/pricing/pricing-page.html - 53 + libs/common/src/lib/routes/routes.ts + 46 + + + Market data is delayed for + 市场数据延迟 - apps/client/src/app/pages/pricing/pricing-page.html - 142 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts + 91 + + + + Absolute Currency Performance + 绝对货币表现 + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 145 + + + Absolute Net Performance + 绝对净回报 - apps/client/src/app/pages/pricing/pricing-page.html - 209 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 193 - - Data Import and Export - 数据导入与导出 + + Absolute Asset Performance + 绝对资产回报 - apps/client/src/app/pages/pricing/pricing-page.html - 73 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 102 + + + Investment + 投资 - apps/client/src/app/pages/pricing/pricing-page.html - 146 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 167 - apps/client/src/app/pages/pricing/pricing-page.html - 229 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 58 - - - Community Support - 社区支持 - apps/client/src/app/pages/pricing/pricing-page.html - 90 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 78 - - - Self-hosted, update manually. - 自托管,手动更新。 - apps/client/src/app/pages/pricing/pricing-page.html + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts 94 - - - Free - 自由的 - - apps/client/src/app/pages/pricing/pricing-page.html - 95 - - apps/client/src/app/pages/pricing/pricing-page.html - 158 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 86 - - For new investors who are just getting started with trading. - 适合刚开始交易的新投资者。 + + Asset Performance + 资产回报 - apps/client/src/app/pages/pricing/pricing-page.html - 128 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 124 - - Fully managed Ghostfolio cloud offering. - 完全托管的 Ghostfolio 云产品。 + + Net Performance + 净回报 - apps/client/src/app/pages/pricing/pricing-page.html - 157 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 212 + + + Currency Performance + 货币表现 - apps/client/src/app/pages/pricing/pricing-page.html - 261 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 170 - - For ambitious investors who need the full picture of their financial assets. - 适合需要全面了解其金融资产的雄心勃勃的投资者。 + + Year to date + 今年迄今为止 - apps/client/src/app/pages/pricing/pricing-page.html - 194 + libs/ui/src/lib/assistant/assistant.component.ts + 360 - - Email and Chat Support - 电子邮件和聊天支持 + + Week to date + 本周至今 - apps/client/src/app/pages/pricing/pricing-page.html - 257 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - Renew Plan - 更新计划 + + Month to date + 本月至今 - apps/client/src/app/components/header/header.component.html - 191 + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + MTD + 本月至今 - apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + libs/ui/src/lib/assistant/assistant.component.ts + 356 + + + WTD + 本周至今 - apps/client/src/app/pages/pricing/pricing-page.html - 294 + libs/ui/src/lib/assistant/assistant.component.ts + 352 - - One-time payment, no auto-renewal. - 一次性付款,无自动续订。 + + Oops! A data provider is experiencing the hiccups. + 哎呀!数据提供商遇到了问题。 - apps/client/src/app/pages/pricing/pricing-page.html - 298 + apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html + 8 - - Get Started - 开始使用 + + View + 查看 - apps/client/src/app/pages/landing/landing-page.html - 446 + apps/client/src/app/components/access-table/access-table.component.html + 23 - - - It’s free. - 免费。 - apps/client/src/app/pages/pricing/pricing-page.html - 327 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 36 - - Hello, has shared a Portfolio with you! - 你好,分享了一个文件夹与你! + + Reset Filters + 重置过滤器 - apps/client/src/app/pages/public/public-page.html - 4 + libs/ui/src/lib/assistant/assistant.html + 238 - - Currencies - 货币 + + If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. + 如果你今天退休,你可以领取每年或者每月,根据您的总资产提款率为4%。 - apps/client/src/app/pages/public/public-page.html - 88 + apps/client/src/app/pages/portfolio/fire/fire-page.html + 68 - - Continents - 大陆 + + year + - apps/client/src/app/pages/public/public-page.html - 124 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 290 - - - Ghostfolio empowers you to keep track of your wealth. - Ghostfolio 使您能够跟踪您的财富。 - apps/client/src/app/pages/public/public-page.html - 215 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 296 - - - Registration - 注册 - apps/client/src/app/pages/register/register-page-routing.module.ts - 13 + libs/ui/src/lib/assistant/assistant.component.ts + 370 - - Continue with Internet Identity - 继续互联网身份 + + years + - apps/client/src/app/pages/register/register-page.html - 42 + libs/ui/src/lib/assistant/assistant.component.ts + 395 - - Continue with Google - 继续使用谷歌 + + Apply Filters + 应用过滤器 - apps/client/src/app/pages/register/register-page.html - 53 + libs/ui/src/lib/assistant/assistant.html + 248 - - Copy to clipboard - 复制到剪贴板 + + self-hosting + self-hosting + kebab-case - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 26 + libs/common/src/lib/routes/routes.ts + 243 - - - I agree to have stored my Security Token from above in a secure place. If I lose it, I cannot get my account back. - 我同意存储我的保安编码器从上面看,在一个安全的地方。如果我丢失了它,我将无法找回我的帐户。 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 32 + libs/common/src/lib/routes/routes.ts + 246 - - Agree and continue - 同意并继续 + + Self-Hosting + 自托管 - apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html - 45 + apps/client/src/app/pages/faq/faq-page.component.ts + 60 - - - Personal Finance Tools - 个人理财工具 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 14 + libs/common/src/lib/routes/routes.ts + 248 - - open-source-alternative-to - 开源替代方案 + + Data Gathering + 数据收集 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 549 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts - 13 + apps/client/src/app/components/admin-overview/admin-overview.html + 60 - - Open Source Alternative to - 开源替代方案 + + General + 一般的 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts - 27 + apps/client/src/app/pages/faq/faq-page.component.ts + 49 - - Discover Open Source Alternatives for Personal Finance Tools - 发现个人理财工具的开源替代品 + + Cloud + - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 4 + apps/client/src/app/pages/faq/faq-page.component.ts + 54 + + + libs/common/src/lib/routes/routes.ts + 240 - - This overview page features a curated collection of personal finance tools compared to the open source alternative Ghostfolio. If you value transparency, data privacy, and community collaboration, Ghostfolio provides an excellent opportunity to take control of your financial management. - 此概述页面包含与开源替代方案相比的精选个人理财工具集合Ghostfolio。如果您重视透明度、数据隐私和社区协作,Ghostfolio 提供了一个绝佳的机会来控制您的财务管理。 + + Oops! It looks like you’re making too many requests. Please slow down a bit. + 哎呀!看来您提出了太多要求。请慢一点。 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 8 + apps/client/src/app/core/http-response.interceptor.ts + 106 - - Explore the links below to compare a variety of personal finance tools with Ghostfolio. - 浏览下面的链接,将各种个人理财工具与 Ghostfolio 进行比较。 + + My Account + 我的账户 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 16 + apps/client/src/app/pages/i18n/i18n-page.html + 13 - - Open Source Alternative to - 开源替代方案 + + Closed + 已关闭 - apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html - 42 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 65 - - The Open Source Alternative to - 开源替代方案 + + Active + 活跃 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 8 + apps/client/src/app/components/home-holdings/home-holdings.component.ts + 64 - - Are you looking for an open source alternative to ? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their investments. Whether you are an experienced investor or just starting out, Ghostfolio offers an intuitive user interface and a wide range of functionalities to help you make informed decisions and take control of your financial future. - 您是否正在寻找开源替代方案幽灵作品集是一个强大的投资组合管理工具,为个人提供一个全面的平台来跟踪、分析和优化他们的投资。无论您是经验丰富的投资者还是刚刚起步的投资者,Ghostfolio 都提供直观的用户界面和广泛的功能帮助您做出明智的决定并掌控您的财务未来。 + + Indonesia + Indonesia - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 18 + libs/ui/src/lib/i18n.ts + 87 - - Ghostfolio is an open source software (OSS), providing a cost-effective alternative to making it particularly suitable for individuals on a tight budget, such as those pursuing Financial Independence, Retire Early (FIRE). By leveraging the collective efforts of a community of developers and personal finance enthusiasts, Ghostfolio continuously enhances its capabilities, security, and user experience. - Ghostfolio 是一款开源软件 (OSS),提供了一种经济高效的替代方案使其特别适合预算紧张的个人,例如追求财务独立,提前退休(FIRE) 。通过利用开发者社区和个人理财爱好者的集体努力,Ghostfolio 不断增强其功能、安全性和用户体验。 + + Activity + 活动 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 32 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 224 - - Let’s dive deeper into the detailed Ghostfolio vs comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to . We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements. - 让我们更深入地了解 Ghostfolio 与下面的比较表可帮助您全面了解 Ghostfolio 相对于其他产品的定位。我们将探讨功能、数据隐私、定价等各个方面,让您根据个人需求做出明智的选择。 + + Dividend Yield + 股息收益率 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 43 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 192 - - Ghostfolio vs comparison table - Ghostfolio vs比较表 + + Execute Job + 执行作业 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 54 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 176 - - Founded - 成立 + + Priority + 优先级 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 77 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 64 - - Origin - 来源 + + This action is not allowed. + 不允许执行此操作。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 82 + apps/client/src/app/core/http-response.interceptor.ts + 67 - - Region - 地区 + + Liquidity + 流动性 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 87 + libs/ui/src/lib/i18n.ts + 48 - - Available in - 可用于 + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {活动} other {活动}} - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 108 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 - - ✅ Yes - ✅ 是的 + + Buy and sell + 买入和卖出 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 140 + libs/ui/src/lib/i18n.ts + 8 + + + Delete Activities + 删除活动 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 157 + libs/ui/src/lib/activities-table/activities-table.component.html + 67 + + + Internationalization + 国际化 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 179 + libs/common/src/lib/routes/routes.ts + 119 + + + Do you really want to close your Ghostfolio account? + 您确定要关闭您的 Ghostfolio 账户吗? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 196 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 206 + + + Danger Zone + 危险区域 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 218 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 272 + + + Close Account + 关闭账户 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 235 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 307 + + + By ETF Holding + 按 ETF 持仓 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 257 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 333 + + + Approximation based on the top holdings of each ETF + 基于每个 ETF 的主要持仓的近似值 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 274 + apps/client/src/app/pages/portfolio/allocations/allocations-page.html + 340 - - ❌ No - ❌ 没有 + + Join now or check out the example account + 立即加入 或查看示例账户 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 147 + apps/client/src/app/pages/landing/landing-page.html + 435 + + + Oops! There was an error setting up biometric authentication. + 哎呀!设置生物识别认证时发生错误。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 164 + apps/client/src/app/components/user-account-settings/user-account-settings.component.ts + 334 + + + Show more + 显示更多 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 186 + libs/ui/src/lib/top-holdings/top-holdings.component.html + 174 + + + Benchmarks + 基准 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 203 + apps/client/src/app/components/admin-market-data/admin-market-data.component.ts + 120 + + + Delete Profiles + 删除配置文件 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 225 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 243 + + + Do you really want to delete these profiles? + 您确定要删除这些配置文件吗? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 242 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 68 + + + Oops! Could not delete profiles. + 哎呀!无法删除配置文件。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 264 + apps/client/src/app/components/admin-market-data/admin-market-data.service.ts + 56 + + + Table + 表格 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 281 + apps/client/src/app/components/home-holdings/home-holdings.html + 16 - - Self-Hosting - 自托管 + + Chart + 图表 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 170 + apps/client/src/app/components/home-holdings/home-holdings.html + 19 - - Use anonymously - 匿名使用 + + Would you like to refine your personal investment strategy? + 您想 优化 您的 个人投资策略吗? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 209 + apps/client/src/app/pages/public/public-page.html + 212 - - Free Plan - 免费计划 + + Alternative + 另类 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 248 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 80 - - Starting from - 从...开始 + + App + 应用 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 289 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 81 + + + Budgeting + 预算管理 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 294 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 82 - - year - + + Community + 社区 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 290 + apps/client/src/app/app.component.html + 130 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 296 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 85 - - - Notes - 笔记 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 302 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 90 - - - Please note that the information provided in the Ghostfolio vs comparison table is based on our independent research and analysis. This website is not affiliated with or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain accurate data on GitHub. - 请注意,Ghostfolio 与 Ghostfolio 中提供的信息比较表基于我们的独立研究和分析。该网站不隶属于或比较中提到的任何其他产品。随着个人理财工具格局的不断发展,直接从相应的产品页面验证任何具体的细节或变化至关重要。数据需要刷新吗?帮助我们维护准确的数据GitHub - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 311 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 94 - - - Ready to take your investments to the next level? - 准备好带走你的投资下一级 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 324 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 98 - - - Effortlessly track, analyze, and visualize your wealth with Ghostfolio. - 使用 Ghostfolio 轻松跟踪、分析和可视化您的财富。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 328 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 102 - - - Get Started - 开始使用 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 333 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 106 - - - Personal Finance Tools - 个人理财工具 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 351 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 110 - - - Switzerland - 瑞士 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 60 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 114 - - libs/ui/src/lib/i18n.ts - 90 + + apps/client/src/app/components/user-account-settings/user-account-settings.html + 118 - - - Global - 全球的 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 61 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 123 - libs/ui/src/lib/i18n.ts - 16 + apps/client/src/app/pages/features/features-page.html + 276 - - - Resources - 资源 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 50 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 83 - - Guides - 指南 + + Family Office + 家族办公室 - apps/client/src/app/pages/resources/guides/resources-guides.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 84 - - Glossary - 词汇表 + + Investor + 投资者 - apps/client/src/app/pages/resources/glossary/resources-glossary.component.html - 4 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 87 - - Membership - 会员资格 + + Open Source + 开源 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 23 + apps/client/src/app/pages/landing/landing-page.html + 261 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 40 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 88 - - Access - 使用权 + + Personal Finance + 个人理财 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 28 + apps/client/src/app/app.component.html + 57 - apps/client/src/app/pages/user-account/user-account-page.component.ts - 46 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 90 - - My Ghostfolio - 我的 Ghostfolio + + Privacy + 隐私 - apps/client/src/app/pages/user-account/user-account-page-routing.module.ts - 33 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 91 - - Oops, authentication has failed. - 糟糕,身份验证失败。 + + Software + 软件 - apps/client/src/app/pages/webauthn/webauthn-page.html - 19 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 93 - - Try again - 再试一次 + + Tool + 工具 - apps/client/src/app/pages/webauthn/webauthn-page.html - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 94 - - Go back to Home Page - 返回首页 + + User Experience + 用户体验 - apps/client/src/app/pages/webauthn/webauthn-page.html - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 95 - - Do you really want to delete this account balance? - 您确实要删除该帐户余额吗? + + Wealth + 财富 - libs/ui/src/lib/account-balances/account-balances.component.ts - 110 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 96 - - Import Activities - 进口活动 + + Wealth Management + 财富管理 - libs/ui/src/lib/activities-table/activities-table.component.html - 9 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts + 97 + + + Australia + 澳大利亚 - libs/ui/src/lib/activities-table/activities-table.component.html - 371 + libs/ui/src/lib/i18n.ts + 76 - - Import Dividends - 导入股息 + + Austria + 奥地利 - libs/ui/src/lib/activities-table/activities-table.component.html - 29 + libs/ui/src/lib/i18n.ts + 77 + + + Belgium + 比利时 - libs/ui/src/lib/activities-table/activities-table.component.html - 383 + libs/ui/src/lib/i18n.ts + 78 - - Export Activities - 出口活动 + + Bulgaria + 保加利亚 - libs/ui/src/lib/activities-table/activities-table.component.html - 41 + libs/ui/src/lib/i18n.ts + 80 + + + Canada + 加拿大 - libs/ui/src/lib/activities-table/activities-table.component.html - 396 + libs/ui/src/lib/i18n.ts + 81 - - Export Drafts as ICS - 将汇票导出为 ICS + + Czech Republic + 捷克共和国 - libs/ui/src/lib/activities-table/activities-table.component.html - 54 + libs/ui/src/lib/i18n.ts + 82 + + + Finland + 芬兰 - libs/ui/src/lib/activities-table/activities-table.component.html - 409 + libs/ui/src/lib/i18n.ts + 83 - - Draft - 草稿 + + France + 法国 - libs/ui/src/lib/activities-table/activities-table.component.html - 145 + libs/ui/src/lib/i18n.ts + 84 - - Clone - 克隆 + + Germany + 德国 - libs/ui/src/lib/activities-table/activities-table.component.html - 436 + libs/ui/src/lib/i18n.ts + 85 - - Export Draft as ICS - 将汇票导出为 ICS + + India + 印度 - libs/ui/src/lib/activities-table/activities-table.component.html - 446 + libs/ui/src/lib/i18n.ts + 86 - - Do you really want to delete this activity? - 您确实要删除此活动吗? + + Italy + 意大利 - libs/ui/src/lib/activities-table/activities-table.component.ts - 229 + libs/ui/src/lib/i18n.ts + 88 - - Find holding... - 查找持有... + + Netherlands + 荷兰 - libs/ui/src/lib/assistant/assistant.component.ts - 144 + libs/ui/src/lib/i18n.ts + 90 - - No entries... - 没有条目... + + New Zealand + 新西兰 - libs/ui/src/lib/assistant/assistant.html - 63 + libs/ui/src/lib/i18n.ts + 91 + + + Poland + 波兰 - libs/ui/src/lib/assistant/assistant.html - 84 + libs/ui/src/lib/i18n.ts + 92 - - Asset Profiles - 资产概况 + + Romania + 罗马尼亚 - libs/ui/src/lib/assistant/assistant.html - 67 + libs/ui/src/lib/i18n.ts + 93 - - Index - 指数 + + South Africa + 南非 - libs/ui/src/lib/benchmark/benchmark.component.html - 3 + libs/ui/src/lib/i18n.ts + 95 - - 50-Day Trend - 50 天趋势 + + Thailand + 泰国 - libs/ui/src/lib/benchmark/benchmark.component.html - 15 + libs/ui/src/lib/i18n.ts + 97 - - 200-Day Trend - 200天趋势 + + United States + 美国 - libs/ui/src/lib/benchmark/benchmark.component.html - 40 + libs/ui/src/lib/i18n.ts + 100 - - Last All Time High - 上次历史最高纪录 + + Error + 错误 - libs/ui/src/lib/benchmark/benchmark.component.html - 65 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 628 - - Change from All Time High - 从历史最高点开始变化 + + Deactivate + 停用 - libs/ui/src/lib/benchmark/benchmark.component.html - 81 + apps/client/src/app/components/rule/rule.component.html + 72 + + + + Activate + 激活 + + apps/client/src/app/components/rule/rule.component.html + 74 - - from ATH - 来自 ATH + + Inactive + 非活跃 - libs/ui/src/lib/benchmark/benchmark.component.html - 83 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 232 - - Market data provided by - 市场数据提供者 + + Cancel + 取消 - libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html - 2 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 148 - - - Savings Rate per Month - 每月储蓄率 - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 10 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 552 - - - Annual Interest Rate - 年利率 - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 21 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 56 - - - Retirement Date - 退休日期 - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 32 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 42 - - - Projected Total Amount - 预计总额 - libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html + 25 - - - Interest - 利息 - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 371 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 15 - libs/ui/src/lib/i18n.ts - 38 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 58 - - - Savings - 储蓄 - libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 381 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 103 - - - Allocation - 分配 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 98 + apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html + 65 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 40 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 338 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 116 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 48 - - - Show all - 显示所有 - libs/ui/src/lib/holdings-table/holdings-table.component.html - 197 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 46 - - - Account - 帐户 libs/ui/src/lib/i18n.ts - 4 + 9 - - Asia-Pacific - 亚太 + + Close + 关闭 + + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 129 + libs/ui/src/lib/i18n.ts - 5 + 11 - - Asset Class - 资产类别 + + Yes + libs/ui/src/lib/i18n.ts - 6 + 32 - - Asset Sub Class - 资产子类别 + + Copy link to clipboard + 复制链接到剪贴板 - libs/ui/src/lib/i18n.ts - 7 + apps/client/src/app/components/access-table/access-table.component.html + 70 - - Core - 核心 + + Portfolio Snapshot + 投资组合快照 - libs/ui/src/lib/i18n.ts - 10 + apps/client/src/app/components/admin-jobs/admin-jobs.html + 39 - - Switch to Ghostfolio Premium or Ghostfolio Open Source easily - 轻松切换到 Ghostfolio Premium 或 Ghostfolio Open Source + + Change with currency effect Change + 含货币影响的涨跌 涨跌 - libs/ui/src/lib/i18n.ts - 12 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 64 - - Switch to Ghostfolio Premium easily - 轻松切换到 Ghostfolio Premium + + Performance with currency effect Performance + 含货币影响的表现 表现 - libs/ui/src/lib/i18n.ts - 13 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 83 - - Switch to Ghostfolio Open Source or Ghostfolio Basic easily - 轻松切换到 Ghostfolio Open Source 或 Ghostfolio Basic + + Threshold Min + 最小阈值 - libs/ui/src/lib/i18n.ts - 14 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 54 - - Emergency Fund - 应急基金 + + Threshold Max + 阈值上限 - libs/ui/src/lib/i18n.ts - 15 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 92 - - Grant - 授予 + + Customize + 自定义 - libs/ui/src/lib/i18n.ts - 17 + apps/client/src/app/components/rule/rule.component.html + 67 - - Higher Risk - 风险较高 + + No auto-renewal. + 不自动续订。 - libs/ui/src/lib/i18n.ts - 18 + apps/client/src/app/components/user-account-membership/user-account-membership.html + 70 - - This activity already exists. - 这项活动已经存在。 + + This year + 今年 - libs/ui/src/lib/i18n.ts - 19 + apps/client/src/app/pages/public/public-page.html + 42 - - Japan - 日本 + + From the beginning + 从头开始 - libs/ui/src/lib/i18n.ts - 84 + apps/client/src/app/pages/public/public-page.html + 60 - - Lower Risk - 降低风险 + + Oops! Invalid currency. + 哎呀!无效的货币。 - libs/ui/src/lib/i18n.ts - 20 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 49 - - Month - + + This page has been archived. + 此页面已存档。 - libs/ui/src/lib/i18n.ts - 21 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 14 - - Months - 几个月 + + is Open Source Software + 是开源软件 - libs/ui/src/lib/i18n.ts - 22 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 139 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 156 - - Other - 其他 + + is not Open Source Software + 不是开源软件 - libs/ui/src/lib/i18n.ts - 23 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 146 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 403 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 163 - - Preset - 预设 + + can be self-hosted + 可以自托管 - libs/ui/src/lib/i18n.ts - 25 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 178 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 195 - - Retirement Provision - 退休金 + + cannot be self-hosted + 无法自托管 - libs/ui/src/lib/i18n.ts - 26 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 185 + + + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 202 - - Satellite - 卫星 + + can be used anonymously + 可以匿名使用 - libs/ui/src/lib/i18n.ts - 27 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 217 - - - Symbol - 符号 - libs/ui/src/lib/i18n.ts - 28 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 234 - - Tag - 标签 + + cannot be used anonymously + 无法匿名使用 - libs/ui/src/lib/i18n.ts - 29 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 224 - - - Year - - libs/ui/src/lib/i18n.ts - 30 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 241 - - Years - + + offers a free plan + 提供免费计划 - libs/ui/src/lib/i18n.ts - 31 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 256 - - - Buy - - libs/ui/src/lib/i18n.ts - 35 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 273 - - Fee - 费用 + + does not offer a free plan + 不提供免费计划 - libs/ui/src/lib/i18n.ts - 37 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 263 - - - Valuable - 有价值的 - libs/ui/src/lib/i18n.ts - 39 + apps/client/src/app/pages/resources/personal-finance-tools/product-page.html + 280 - - Liability - 责任 + + Oops! Could not find any assets. + 哎呀!找不到任何资产。 - libs/ui/src/lib/i18n.ts + libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html 40 - - Sell - + + Data Providers + 数据提供者 - libs/ui/src/lib/i18n.ts - 41 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 4 - - Cash - 现金 + + Set API key + 设置 API 密钥 - libs/ui/src/lib/i18n.ts - 44 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 171 - - Commodity - 商品 + + Get access to 80’000+ tickers from over 50 exchanges + 获取来自 50 多个交易所的 80,000+ 股票代码访问权限 libs/ui/src/lib/i18n.ts - 45 + 24 - - Equity - 公平 + + Ukraine + 乌克兰 libs/ui/src/lib/i18n.ts - 46 + 98 - - Fixed Income - 固定收入 + + Join now + 立即加入 - libs/ui/src/lib/i18n.ts - 47 + apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html + 110 - - Real Estate - 房地产 + + Glossary + 词汇表 - libs/ui/src/lib/i18n.ts - 49 + apps/client/src/app/pages/resources/glossary/resources-glossary.component.html + 4 - - - Bond - 纽带 - libs/ui/src/lib/i18n.ts - 52 + apps/client/src/app/pages/resources/resources-page.component.ts + 45 - - - Cryptocurrency - 加密货币 - libs/ui/src/lib/i18n.ts - 53 + libs/common/src/lib/routes/routes.ts + 293 - - ETF - 交易所交易基金 + + Guides + 指南 - libs/ui/src/lib/i18n.ts - 54 + apps/client/src/app/pages/resources/guides/resources-guides.component.html + 4 - - - Mutual Fund - 共同基金 - libs/ui/src/lib/i18n.ts - 55 + apps/client/src/app/pages/resources/resources-page.component.ts + 34 - - - Precious Metal - 贵金属 - libs/ui/src/lib/i18n.ts - 56 + libs/common/src/lib/routes/routes.ts + 301 - - Private Equity - 私人产权 + + guides + guides + kebab-case - libs/ui/src/lib/i18n.ts - 57 + libs/common/src/lib/routes/routes.ts + 296 - - - Stock - 库存 - libs/ui/src/lib/i18n.ts - 58 + libs/common/src/lib/routes/routes.ts + 299 - - Africa - 非洲 + + glossary + glossary + kebab-case - libs/ui/src/lib/i18n.ts - 65 + libs/common/src/lib/routes/routes.ts + 288 - - - Asia - 亚洲 - libs/ui/src/lib/i18n.ts - 66 + libs/common/src/lib/routes/routes.ts + 291 - - Europe - 欧洲 + + Threshold range + 阈值范围 - libs/ui/src/lib/i18n.ts - 67 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 9 - - North America - 北美 + + Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + Ghostfolio X-ray 使用静态分析来发现您投资组合中的潜在问题和风险。调整以下规则并设置自定义阈值,使其与您的个人投资策略保持一致。 - libs/ui/src/lib/i18n.ts - 68 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 6 - - Oceania - 大洋洲 + + Economic Market Cluster Risks + 经济市场集群风险 - libs/ui/src/lib/i18n.ts - 69 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 165 - - South America - 南美洲 + + of + - libs/ui/src/lib/i18n.ts - 70 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 135 - - Extreme Fear - 极度恐惧 + + daily requests + 每日请求 - libs/ui/src/lib/i18n.ts - 96 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 137 - - Extreme Greed - 极度贪婪 + + Remove API key + 移除 API 密钥 - libs/ui/src/lib/i18n.ts - 97 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 161 - - Neutral - 中性的 + + Do you really want to delete the API key? + 您确定要删除此 API 密钥吗? - libs/ui/src/lib/i18n.ts - 100 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 128 - - Membership - 会员资格 + + Please enter your Ghostfolio API key: + 请输入您的 Ghostfolio API 密钥: - libs/ui/src/lib/membership-card/membership-card.component.html - 37 + apps/client/src/app/pages/api/api-page.component.ts + 41 - - Valid until - 有效期至 - - apps/client/src/app/components/admin-settings/admin-settings.component.html - 26 - + + API Requests Today + 今日 API 请求数 - libs/ui/src/lib/membership-card/membership-card.component.html - 42 + apps/client/src/app/components/admin-users/admin-users.html + 179 - - Time to add your first activity. - 是时候添加您的第一个活动了。 + + Could not generate an API key + 无法生成 API 密钥 - libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html - 12 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 141 - - No data available - 无可用数据 + + Set this API key in your self-hosted environment: + 在您的自托管环境中设置此 API 密钥: - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 405 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 156 + + + Ghostfolio Premium Data Provider API Key + Ghostfolio Premium 数据提供者 API 密钥 - libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 418 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 159 - - If a translation is missing, kindly support us in extending it here. - 如果翻译缺失,请支持我们进行扩展这里 + + Do you really want to generate a new API key? + 您确定要生成新的 API 密钥吗? - apps/client/src/app/components/user-account-settings/user-account-settings.html - 50 + apps/client/src/app/components/user-account-membership/user-account-membership.component.ts + 164 - - Date Range - 日期范围 + + API Key + API 密钥 - libs/ui/src/lib/assistant/assistant.html - 93 + libs/ui/src/lib/membership-card/membership-card.component.html + 18 - - The current market price is - 当前市场价格为 + + Generate Ghostfolio Premium Data Provider API key for self-hosted environments... + 为自托管环境生成 Ghostfolio Premium 数据提供者 API 密钥... - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 325 + libs/ui/src/lib/membership-card/membership-card.component.html + 26 - - Test - 测试 + + out of + / - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 56 - - Oops! Could not grant access. - 哎呀!无法授予访问权限。 + + rules align with your portfolio. + 条规则与您的投资组合一致。 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 90 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 58 - - Restricted view - 视野受限 + + Save + 保存 - apps/client/src/app/components/access-table/access-table.component.html - 26 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 559 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 34 + apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html + 63 - - - Permission - 允许 - apps/client/src/app/components/access-table/access-table.component.html - 18 + apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html + 49 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html 32 - - - Private - 私人的 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 24 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 22 - - - Job Queue - 作业队列 - apps/client/src/app/pages/admin/admin-page-routing.module.ts - 25 + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts + 69 - apps/client/src/app/pages/admin/admin-page.component.ts - 42 + apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html + 135 - - - Market data is delayed for - 市场数据延迟 - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 86 + apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html + 65 - - - Absolute Currency Performance - 绝对货币表现 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 71 + apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html + 110 - - - Absolute Net Performance - 绝对净性能 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 118 + apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html + 345 - - - Absolute Asset Performance - 绝对资产绩效 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 28 + libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html + 48 - - Investment - 投资 + + Asset Class Cluster Risks + 资产类别集群风险 - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 117 + + + Me + - apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + apps/client/src/app/components/header/header.component.html + 213 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 89 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 211 - - Asset Performance - 资产绩效 + + Received Access + 已获得访问权限 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 49 + apps/client/src/app/components/user-account-access/user-account-access.html + 53 - - Net Performance - 净绩效 + + Please enter your Ghostfolio API key. + 请输入您的 Ghostfolio API 密钥。 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 137 + apps/client/src/app/components/admin-settings/admin-settings.component.ts + 147 - - Currency Performance - 货币表现 + + AI prompt has been copied to the clipboard + AI 提示已复制到剪贴板 - apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 95 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 197 - - Year to date - 今年迄今为止 + + Link has been copied to the clipboard + 链接已复制到剪贴板 - libs/ui/src/lib/assistant/assistant.component.ts - 231 + apps/client/src/app/components/access-table/access-table.component.ts + 94 - - Week to date - 本周至今 + + Regional Market Cluster Risks + 区域市场集群风险 - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 189 - - Month to date - 本月至今 + + Lazy + 延迟 - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - MTD - 最大输运量 + + Instant + 即时 - libs/ui/src/lib/assistant/assistant.component.ts - 227 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - WTD - 世界贸易组织 + + Default Market Price + 默认市场价格 - libs/ui/src/lib/assistant/assistant.component.ts - 223 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 394 - - Oops! A data provider is experiencing the hiccups. - 哎呀!数据提供商遇到了问题。 + + Mode + 模式 - apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html - 8 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 431 - - View - 看法 + + Selector + 选择器 - apps/client/src/app/components/access-table/access-table.component.html - 23 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 447 + + + HTTP Request Headers + HTTP 请求标头 - apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html - 36 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 407 - - Reset Filters - 重置过滤器 + + end of day + 收盘 - libs/ui/src/lib/assistant/assistant.html - 185 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 200 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - 如果你今天退休,你可以领取每年或者每月,根据您的总资产提款率为4%。 + + real-time + 实时 - apps/client/src/app/pages/portfolio/fire/fire-page.html - 67 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 204 - - year - + + Open Duck.ai + 打开 Duck.ai - libs/ui/src/lib/assistant/assistant.component.ts - 235 + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 198 - - years - + + Create + 创建 - libs/ui/src/lib/assistant/assistant.component.ts - 257 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 - - Apply Filters - 应用过滤器 + + Change + 涨跌 - libs/ui/src/lib/assistant/assistant.html - 195 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 - - - self-hosting - 自托管 - apps/client/src/app/pages/faq/faq-page.component.ts - 48 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 - - FAQ - 常见问题 + + Performance + 表现 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.html + 6 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + apps/client/src/app/components/home-overview/home-overview.component.ts + 55 - - - Self-Hosting - 自托管 - apps/client/src/app/pages/faq/faq-page.component.ts - 47 + libs/ui/src/lib/holdings-table/holdings-table.component.html + 142 - apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts - 13 + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 367 + + + libs/ui/src/lib/treemap-chart/treemap-chart.component.ts + 380 - - Data Gathering - 数据收集 + + Copy portfolio data to clipboard for AI prompt + 复制投资组合数据到剪贴板以供 AI 提示使用 - apps/client/src/app/components/admin-overview/admin-overview.html - 137 + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 42 + + + + Copy AI prompt to clipboard for analysis + 复制 AI 提示到剪贴板进行分析 + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 67 - - General - 一般的 + + Armenia + 亚美尼亚 - apps/client/src/app/pages/faq/faq-page.component.ts - 36 + libs/ui/src/lib/i18n.ts + 75 - - Cloud - + + British Virgin Islands + 英属维尔京群岛 - apps/client/src/app/pages/faq/faq-page.component.ts - 41 + libs/ui/src/lib/i18n.ts + 79 + + + Singapore + 新加坡 - apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts - 13 + libs/ui/src/lib/i18n.ts + 94 - - Oops! It looks like you’re making too many requests. Please slow down a bit. - 哎呀!看来您提出了太多要求。请慢一点。 + + Terms and Conditions + 条款和条件 - apps/client/src/app/core/http-response.interceptor.ts - 96 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 15 - - My Account - 我的账户 + + Please keep your security token safe. If you lose it, you will not be able to recover your account. + 请妥善保管您的安全令牌。如果您丢失它,将无法恢复您的账户。 - apps/client/src/app/pages/i18n/i18n-page.html - 13 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 18 - - Closed - 关闭 + + I understand that if I lose my security token, I cannot recover my account + 我理解如果我丢失了安全令牌,将无法恢复我的账户 - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 36 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 28 - - Active - 积极的 + + Continue + 继续 - apps/client/src/app/components/home-holdings/home-holdings.component.ts - 35 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 57 - - Activity - 活动 + + Here is your security token. It is only visible once, please store and keep it in a safe place. + 这是您的安全令牌。它仅显示一次,请妥善保管。 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 207 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 67 - - Dividend Yield - Dividend Yield + + Security token + 安全令牌 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 175 + apps/client/src/app/components/admin-users/admin-users.component.ts + 198 - - - Execute Job - Execute Job - apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 169 - - Priority - Priority + + Do you really want to generate a new security token for this user? + 您确定要为此用户生成新的安全令牌吗? - apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + apps/client/src/app/components/admin-users/admin-users.component.ts + 203 - - This action is not allowed. - This action is not allowed. + + Generate Security Token + 生成安全令牌 - apps/client/src/app/core/http-response.interceptor.ts - 61 + apps/client/src/app/components/admin-users/admin-users.html + 250 - - Liquidity - Liquidity + + United Kingdom + 英国 libs/ui/src/lib/i18n.ts - 48 + 99 - - {VAR_PLURAL, plural, =1 {activity} other {activities}} - {VAR_PLURAL, plural, =1 {activity} other {activities}} + + Terms of Service + 服务条款 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.html + 5 - - Buy and sell - Buy and sell + + terms-of-service + terms-of-service + kebab-case - libs/ui/src/lib/i18n.ts - 8 + libs/common/src/lib/routes/routes.ts + 212 - - - Delete Activities - Delete Activities - libs/ui/src/lib/activities-table/activities-table.component.html - 67 + libs/common/src/lib/routes/routes.ts + 215 - - Internationalization - Internationalization + + Terms of Service + 服务条款 - apps/client/src/app/app-routing.module.ts - 88 + apps/client/src/app/app.component.html + 112 - - - Do you really want to close your Ghostfolio account? - Do you really want to close your Ghostfolio account? - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 172 + libs/common/src/lib/routes/routes.ts + 217 - - Danger Zone - Danger Zone + + and I agree to the Terms of Service. + 我同意 服务条款 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 244 + apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html + 34 - - Close Account - Close Account + + () is already in use. + () 已在使用中。 - apps/client/src/app/components/user-account-settings/user-account-settings.html - 279 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 564 - - By ETF Holding - By ETF Holding + + An error occurred while updating to (). + 在更新到 () 时发生错误。 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 333 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 572 - - Approximation based on the top holdings of each ETF - Approximation based on the top holdings of each ETF + + Apply + 应用 - apps/client/src/app/pages/portfolio/allocations/allocations-page.html - 340 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 140 - - Join now or check out the example account - Join now or check out the example account + + with API access for + 包含 API 访问权限,适用于 - apps/client/src/app/pages/landing/landing-page.html - 434 + apps/client/src/app/pages/pricing/pricing-page.html + 253 - - Oops! There was an error setting up biometric authentication. - Oops! There was an error setting up biometric authentication. + + Gather Recent Historical Market Data + 收集近期历史市场数据 - apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 300 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 226 - - Show more - Show more + + Gather All Historical Market Data + 收集所有历史市场数据 - libs/ui/src/lib/top-holdings/top-holdings.component.html - 174 + apps/client/src/app/components/admin-market-data/admin-market-data.html + 231 - - Benchmarks - Benchmarks + + Gather Historical Market Data + 收集历史市场数据 - apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 80 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 29 - - Delete Profiles - Delete Profiles + + Data Gathering is off + 数据收集已关闭 apps/client/src/app/components/admin-market-data/admin-market-data.html - 206 + 38 - - Do you really want to delete these profiles? - Do you really want to delete these profiles? + + Performance Calculation + 绩效计算 - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 67 + apps/client/src/app/components/user-account-settings/user-account-settings.html + 31 - - Oops! Could not delete profiles. - Oops! Could not delete profiles. + + someone + 某人 - apps/client/src/app/components/admin-market-data/admin-market-data.service.ts - 55 + apps/client/src/app/pages/public/public-page.component.ts + 33 - - Table - Table + + Add asset to watchlist + 添加资产到关注列表 - apps/client/src/app/components/home-holdings/home-holdings.html - 16 + apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.html + 7 - - Chart - Chart + + Watchlist + 关注列表 - apps/client/src/app/components/home-holdings/home-holdings.html - 19 + apps/client/src/app/components/home-watchlist/home-watchlist.html + 4 + + + apps/client/src/app/pages/features/features-page.html + 197 + + + libs/common/src/lib/routes/routes.ts + 110 - - Would you like to refine your personal investment strategy? - Would you like to refine your personal investment strategy? + + Do you really want to delete this item? + 您确定要删除此项目吗? - apps/client/src/app/pages/public/public-page.html - 211 + libs/ui/src/lib/benchmark/benchmark.component.ts + 138 - - Alternative - Alternative + + Log out + 登出 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 83 + apps/client/src/app/components/header/header.component.html + 329 - - App - App + + Calculations are based on delayed market data and may not be displayed in real-time. + 计算基于延迟的市场数据,可能无法实时显示。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 84 + apps/client/src/app/components/home-market/home-market.html + 44 + + + apps/client/src/app/components/markets/markets.html + 53 - - Budgeting - Budgeting + + changelog + changelog + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 85 + libs/common/src/lib/routes/routes.ts + 180 + + + libs/common/src/lib/routes/routes.ts + 183 - - Community - Community + + Demo user account has been synced. + 演示用户账户已同步。 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 86 + apps/client/src/app/components/admin-overview/admin-overview.component.ts + 275 - - Family Office - Family Office + + Sync Demo User Account + 同步演示用户账户 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 87 + apps/client/src/app/components/admin-overview/admin-overview.html + 195 - - Investor - Investor + + Set up + 应急资金:设置 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 90 + apps/client/src/app/pages/i18n/i18n-page.html + 132 - - Open Source - Open Source + + No emergency fund has been set up + 未设置应急资金 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 91 + apps/client/src/app/pages/i18n/i18n-page.html + 134 - - Personal Finance - Personal Finance + + An emergency fund has been set up + 已设置应急资金 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 137 - - Privacy - Privacy + + Fee Ratio + 费率 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 94 + apps/client/src/app/pages/i18n/i18n-page.html + 139 - - Software - Software + + The fees do exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + 费用超过了您初始投资的 ${thresholdMax}% (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 96 + apps/client/src/app/pages/i18n/i18n-page.html + 141 - - Tool - Tool + + The fees do not exceed ${thresholdMax}% of your initial investment (${feeRatio}%) + 费用未超过您初始投资的 ${thresholdMax}% (${feeRatio}%) - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 97 + apps/client/src/app/pages/i18n/i18n-page.html + 145 - - User Experience - User Experience + + Name + 名称 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 98 + libs/ui/src/lib/benchmark/benchmark.component.html + 12 - - Wealth - Wealth + + Find holding or page... + 查找持仓或页面... - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 99 + libs/ui/src/lib/assistant/assistant.component.ts + 161 + + + + Quick Links + 快速链接 + + libs/ui/src/lib/assistant/assistant.html + 56 - - Wealth Management - Wealth Management + + Asset Profiles + 资产概况 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts - 100 + libs/ui/src/lib/assistant/assistant.html + 112 - - Australia - Australia + + Live Demo + 现场演示 - libs/ui/src/lib/i18n.ts - 73 + apps/client/src/app/pages/landing/landing-page.html + 49 - - - Austria - Austria - libs/ui/src/lib/i18n.ts - 74 + apps/client/src/app/pages/landing/landing-page.html + 452 - - - Belgium - Belgium - libs/ui/src/lib/i18n.ts - 75 + libs/common/src/lib/routes/routes.ts + 231 - - Bulgaria - Bulgaria + + Open Source Alternative to + 开源替代方案 - libs/ui/src/lib/i18n.ts - 76 + libs/common/src/lib/routes/routes.ts + 326 - - Canada - Canada + + Single Account + 单一账户 - libs/ui/src/lib/i18n.ts - 77 + apps/client/src/app/pages/i18n/i18n-page.html + 28 - - Czech Republic - Czech Republic + + Your net worth is managed by a single account + 您的净资产由单一账户管理 - libs/ui/src/lib/i18n.ts - 78 + apps/client/src/app/pages/i18n/i18n-page.html + 30 - - Finland - Finland + + Your net worth is managed by ${accountsLength} accounts + 您的净资产由 ${accountsLength} 个账户管理 - libs/ui/src/lib/i18n.ts - 79 + apps/client/src/app/pages/i18n/i18n-page.html + 36 - - France - France + + personal-finance-tools + personal-finance-tools + kebab-case - libs/ui/src/lib/i18n.ts - 80 + libs/common/src/lib/routes/routes.ts + 312 - - - Germany - Germany - libs/ui/src/lib/i18n.ts - 81 + libs/common/src/lib/routes/routes.ts + 315 - - - India - India - libs/ui/src/lib/i18n.ts - 82 + libs/common/src/lib/routes/routes.ts + 323 - - Italy - Italy + + markets + markets + kebab-case - libs/ui/src/lib/i18n.ts - 83 + libs/common/src/lib/routes/routes.ts + 304 - - - Netherlands - Netherlands - libs/ui/src/lib/i18n.ts - 85 + libs/common/src/lib/routes/routes.ts + 307 - - New Zealand - New Zealand + + Fuel your self-hosted Ghostfolio with a powerful data provider to access 80,000+ tickers from over 50 exchanges worldwide. + 使用 强大的数据提供商为您的 自托管 Ghostfolio 提供数据,访问来自全球超过 50 家交易所80,000+ 个股票代码 - libs/ui/src/lib/i18n.ts - 86 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 16 - - Poland - Poland + + Get Access + 获取访问权限 - libs/ui/src/lib/i18n.ts - 87 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 27 - - Romania - Romania + + Learn more + 了解更多 - libs/ui/src/lib/i18n.ts - 88 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 38 - - South Africa - South Africa + + Limited Offer! + 限时优惠! - libs/ui/src/lib/i18n.ts - 89 + apps/client/src/app/pages/pricing/pricing-page.html + 312 - - Thailand - Thailand + + Get extra + 获取额外 - libs/ui/src/lib/i18n.ts - 91 + apps/client/src/app/pages/pricing/pricing-page.html + 314 - - United States - United States + + Available + 可用 - libs/ui/src/lib/i18n.ts - 93 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 3 - - Error - Error + + Unavailable + 不可用 - apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 316 + apps/client/src/app/components/data-provider-status/data-provider-status.component.html + 5 - - Deactivate - Deactivate + + new + 新增 - apps/client/src/app/components/rule/rule.component.html - 72 + apps/client/src/app/components/admin-settings/admin-settings.component.html + 67 - - - Activate - Activate - apps/client/src/app/components/rule/rule.component.html - 74 + apps/client/src/app/pages/admin/admin-page.component.ts + 56 - - Inactive - Inactive + + Investment + 投资 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + apps/client/src/app/pages/i18n/i18n-page.html + 15 - - Cancel - Cancel + + Over ${thresholdMax}% of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) + 您当前投资中有超过 ${thresholdMax}% 的资金在 ${maxAccountName} (${maxInvestmentRatio}%) - libs/ui/src/lib/i18n.ts - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 17 - - Close - Close + + The major part of your current investment is at ${maxAccountName} (${maxInvestmentRatio}%) and does not exceed ${thresholdMax}% + 您的当前投资大部分位于 ${maxAccountName} (${maxInvestmentRatio}%) 且不超过 ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 11 + apps/client/src/app/pages/i18n/i18n-page.html + 24 - - Yes - Yes + + Equity + 股权 - libs/ui/src/lib/i18n.ts - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 41 - - Copy link to clipboard - Copy link to clipboard + + The equity contribution of your current investment (${equityValueRatio}%) exceeds ${thresholdMax}% + 您目前投资中股权占比 (${equityValueRatio}%) 超过了 ${thresholdMax}% - apps/client/src/app/components/access-table/access-table.component.html - 70 + apps/client/src/app/pages/i18n/i18n-page.html + 43 - - Portfolio Snapshot - Portfolio Snapshot + + The equity contribution of your current investment (${equityValueRatio}%) is below ${thresholdMin}% + 您目前投资中股权占比 (${equityValueRatio}%) 低于 ${thresholdMin}% - apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + apps/client/src/app/pages/i18n/i18n-page.html + 47 - - Change with currency effect Change - Change with currency effect Change + + The equity contribution of your current investment (${equityValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 您目前投资中股权占比 (${equityValueRatio}%) 在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 50 + apps/client/src/app/pages/i18n/i18n-page.html + 51 - - Performance with currency effect Performance - Performance with currency effect Performance + + Fixed Income + 固定收益 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 69 + apps/client/src/app/pages/i18n/i18n-page.html + 55 - - Threshold Min - Threshold Min + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) exceeds ${thresholdMax}% + 您目前投资中固定收益占比 (${fixedIncomeValueRatio}%) 超过了 ${thresholdMax}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 54 + apps/client/src/app/pages/i18n/i18n-page.html + 57 - - Threshold Max - Threshold Max + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is below ${thresholdMin}% + 您目前投资中固定收益占比 (${fixedIncomeValueRatio}%) 低于 ${thresholdMin}% - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 61 - - Close - Close + + The fixed income contribution of your current investment (${fixedIncomeValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 您目前投资中固定收益占比 (${fixedIncomeValueRatio}%) 在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 129 + apps/client/src/app/pages/i18n/i18n-page.html + 66 - - Customize - Customize + + Investment: Base Currency + 投资:基础货币 - apps/client/src/app/components/rule/rule.component.html - 67 + apps/client/src/app/pages/i18n/i18n-page.html + 72 - - No auto-renewal. - No auto-renewal. + + The major part of your current investment is not in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + 您的当前投资的主要部分未以您的基础货币计价 ( ${baseCurrency} 仅占 ${baseCurrencyValueRatio}%) - apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + apps/client/src/app/pages/i18n/i18n-page.html + 75 - - Today - Today + + The major part of your current investment is in your base currency (${baseCurrencyValueRatio}% in ${baseCurrency}) + 您的当前投资的主要部分以您的基础货币计价(其中 ${baseCurrency} 占比 ${baseCurrencyValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 79 - - This year - This year + + Investment + 投资 - apps/client/src/app/pages/public/public-page.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 82 - - From the beginning - From the beginning + + Over ${thresholdMax}% of your current investment is in ${currency} (${maxValueRatio}%) + 超过 ${thresholdMax}% 的当前投资在 ${currency} 中(占比 ${maxValueRatio}%) - apps/client/src/app/pages/public/public-page.html - 60 + apps/client/src/app/pages/i18n/i18n-page.html + 84 - - Oops! Invalid currency. - Oops! Invalid currency. + + The major part of your current investment is in ${currency} (${maxValueRatio}%) and does not exceed ${thresholdMax}% + 您的当前投资的主要部分以 ${currency} 计价(占比 ${maxValueRatio}%),并且未超过 ${thresholdMax}% - apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html - 49 + apps/client/src/app/pages/i18n/i18n-page.html + 88 - - This page has been archived. - This page has been archived. + + start + start + kebab-case - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 14 + libs/common/src/lib/routes/routes.ts + 336 - - - is Open Source Software - is Open Source Software - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 139 + libs/common/src/lib/routes/routes.ts + 337 - - is not Open Source Software - is not Open Source Software + + Do you really want to generate a new security token? + 您真的想要生成一个新的安全令牌吗? - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 146 + apps/client/src/app/components/user-account-access/user-account-access.component.ts + 174 - - is Open Source Software - is Open Source Software + + Generate + 生成 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 156 + apps/client/src/app/components/user-account-access/user-account-access.html + 43 - - is not Open Source Software - is not Open Source Software + + Stocks + 股票 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 163 + apps/client/src/app/components/markets/markets.component.ts + 52 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 178 + apps/client/src/app/pages/features/features-page.html + 15 - - cannot be self-hosted - cannot be self-hosted + + Cryptocurrencies + 加密货币 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 185 + apps/client/src/app/components/markets/markets.component.ts + 53 - - - can be self-hosted - can be self-hosted - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 195 + apps/client/src/app/pages/features/features-page.html + 51 - - cannot be self-hosted - cannot be self-hosted + + + - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 202 + apps/client/src/app/components/admin-users/admin-users.html + 57 - - can be used anonymously - can be used anonymously + + Manage Asset Profile + 管理资产概况 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 217 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 437 - - cannot be used anonymously - cannot be used anonymously + + Alternative Investment + 另类投资 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 224 + libs/ui/src/lib/i18n.ts + 44 - - can be used anonymously - can be used anonymously + + Collectible + 收藏品 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 234 + libs/ui/src/lib/i18n.ts + 54 - - cannot be used anonymously - cannot be used anonymously + + Average Unit Price + 平均单位价格 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 241 + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts + 105 + + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 100 - - offers a free plan - offers a free plan + + Account Cluster Risks + 账户集群风险 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 256 + apps/client/src/app/pages/i18n/i18n-page.html + 14 - - does not offer a free plan - does not offer a free plan + + Asset Class Cluster Risks + 资产类别集群风险 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 263 + apps/client/src/app/pages/i18n/i18n-page.html + 39 - - offers a free plan - offers a free plan + + Currency Cluster Risks + 货币集群风险 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 273 + apps/client/src/app/pages/i18n/i18n-page.html + 70 - - does not offer a free plan - does not offer a free plan + + Economic Market Cluster Risks + 经济市场集群风险 - apps/client/src/app/pages/resources/personal-finance-tools/product-page.html - 280 + apps/client/src/app/pages/i18n/i18n-page.html + 93 - - Oops! Could not find any assets. - Oops! Could not find any assets. + + Emergency Fund + 应急基金 - libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 131 - - Data Providers - Data Providers + + Fees + 费用 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 4 + apps/client/src/app/pages/i18n/i18n-page.html + 148 - - NEW - NEW + + Regional Market Cluster Risks + 区域市场集群风险 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 15 + apps/client/src/app/pages/i18n/i18n-page.html + 150 - - Set API key - Set API key + + No results found... + 未找到结果... - apps/client/src/app/components/admin-settings/admin-settings.component.html - 68 + libs/ui/src/lib/assistant/assistant.html + 49 - - Want to stay updated? Click below to get notified as soon as it’s available. - Want to stay updated? Click below to get notified as soon as it’s available. + + Developed Markets + 发达市场 - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 23 + apps/client/src/app/pages/i18n/i18n-page.html + 96 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) exceeds ${thresholdMax}% + 发达市场对您的当前投资 (${developedMarketsValueRatio}%) 的贡献超过了 ${thresholdMax}% - libs/ui/src/lib/i18n.ts - 24 + apps/client/src/app/pages/i18n/i18n-page.html + 99 - - Ukraine - Ukraine + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is below ${thresholdMin}% + 发达市场对您的当前投资 (${developedMarketsValueRatio}%) 的贡献低于 ${thresholdMin}% - libs/ui/src/lib/i18n.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 104 - - Skip - Skip + + The developed markets contribution of your current investment (${developedMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 发达市场对您的当前投资 (${developedMarketsValueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 83 + apps/client/src/app/pages/i18n/i18n-page.html + 109 - - Join now - Join now + + Emerging Markets + 新兴市场 - apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html - 93 + apps/client/src/app/pages/i18n/i18n-page.html + 114 - - Glossary - Glossary + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) exceeds ${thresholdMax}% + 新兴市场对您的当前投资 (${emergingMarketsValueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 117 + + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is below ${thresholdMin}% + 新兴市场对您的当前投资 (${emergingMarketsValueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page.component.ts - 31 + apps/client/src/app/pages/i18n/i18n-page.html + 122 - - Guides - Guides + + The emerging markets contribution of your current investment (${emergingMarketsValueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 新兴市场对您的当前投资 (${emergingMarketsValueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts - 10 + apps/client/src/app/pages/i18n/i18n-page.html + 127 + + + No accounts have been set up + 未设置任何帐户 - apps/client/src/app/pages/resources/resources-page.component.ts + apps/client/src/app/pages/i18n/i18n-page.html 21 - - guides - guides - snake-case + + Your net worth is managed by 0 accounts + 您的净资产由 0 个帐户管理 - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 22 + apps/client/src/app/pages/i18n/i18n-page.html + 33 + + + Asia-Pacific + 亚太地区 - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 28 + apps/client/src/app/pages/i18n/i18n-page.html + 152 - - glossary - glossary - snake-case + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + 亚太地区对您的当前投资 (${valueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/pages/resources/overview/resources-overview.component.ts - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 154 + + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + 亚太地区对您的当前投资 (${valueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/pages/resources/resources-page-routing.module.ts - 21 + apps/client/src/app/pages/i18n/i18n-page.html + 158 - - Threshold range - Threshold range + + The Asia-Pacific market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 亚太地区对您的当前投资 (${valueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html - 9 + apps/client/src/app/pages/i18n/i18n-page.html + 162 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. + + Emerging Markets + 新兴市场 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 5 + apps/client/src/app/pages/i18n/i18n-page.html + 167 - - Economic Market Cluster Risks - Economic Market Cluster Risks + + The Emerging Markets contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + 新兴市场对您的当前投资 (${valueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 130 + apps/client/src/app/pages/i18n/i18n-page.html + 170 - - of - of + + The Emerging Markets contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + 新兴市场对您的当前投资 (${valueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/components/admin-settings/admin-settings.component.html - 40 + apps/client/src/app/pages/i18n/i18n-page.html + 174 - - daily requests - daily requests + + The Emerging Markets contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 新兴市场对您的当前投资 (${valueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 178 - - Remove API key - Remove API key + + Europe + 欧洲市场 - apps/client/src/app/components/admin-settings/admin-settings.component.html - 56 + apps/client/src/app/pages/i18n/i18n-page.html + 182 - - Do you really want to delete the API key? - Do you really want to delete the API key? + + The Europe market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + 欧洲市场对您的当前投资 (${valueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/components/admin-settings/admin-settings.component.ts - 92 + apps/client/src/app/pages/i18n/i18n-page.html + 184 - - Please enter your Ghostfolio API key: - Please enter your Ghostfolio API key: + + The Europe market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + 欧洲市场对您的当前投资 (${valueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts - 45 + apps/client/src/app/pages/i18n/i18n-page.html + 188 + + + The Europe market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 欧洲市场对您的当前投资 (${valueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/pages/api/api-page.component.ts - 41 + apps/client/src/app/pages/i18n/i18n-page.html + 192 - - Notify me - Notify me + + Japan + 日本市场 - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 32 + apps/client/src/app/pages/i18n/i18n-page.html + 196 - - I have an API key - I have an API key + + The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + 日本市场对您的当前投资 (${valueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html - 42 + apps/client/src/app/pages/i18n/i18n-page.html + 198 - - API Requests Today - API Requests Today + + The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + 日本市场对您的当前投资 (${valueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/components/admin-users/admin-users.html - 178 + apps/client/src/app/pages/i18n/i18n-page.html + 202 - - Could not generate an API key - Could not generate an API key + + The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 日本市场对您的当前投资 (${valueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 138 + apps/client/src/app/pages/i18n/i18n-page.html + 206 - - Set this API key in your self-hosted environment: - Set this API key in your self-hosted environment: + + North America + 北美市场 - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 153 + apps/client/src/app/pages/i18n/i18n-page.html + 210 - - Ghostfolio Premium Data Provider API Key - Ghostfolio Premium Data Provider API Key + + The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% + 北美市场对您的当前投资 (${valueRatio}%) 的贡献超过了 ${thresholdMax}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 156 + apps/client/src/app/pages/i18n/i18n-page.html + 212 - - Do you really want to generate a new API key? - Do you really want to generate a new API key? + + The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% + 北美市场对您的当前投资 (${valueRatio}%) 的贡献低于 ${thresholdMin}% - apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 161 + apps/client/src/app/pages/i18n/i18n-page.html + 216 - - Tag - Tag + + The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% + 北美市场对您的当前投资 (${valueRatio}%) 的贡献在 ${thresholdMin}% 和 ${thresholdMax}% 之间 - libs/ui/src/lib/assistant/assistant.html - 155 + apps/client/src/app/pages/i18n/i18n-page.html + 220 - - API Key - API Key + + Find Ghostfolio on GitHub + 在 GitHub 上查找 Ghostfolio - libs/ui/src/lib/membership-card/membership-card.component.html - 18 + apps/client/src/app/pages/about/overview/about-overview-page.html + 74 - - - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - Generate Ghostfolio Premium Data Provider API key for self-hosted environments... - libs/ui/src/lib/membership-card/membership-card.component.html - 26 + apps/client/src/app/pages/about/overview/about-overview-page.html + 113 - - out of - out of + + Join the Ghostfolio Slack community + 加入 Ghostfolio Slack 社区 - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 22 + apps/client/src/app/pages/about/overview/about-overview-page.html + 84 - - rules align with your portfolio. - rules align with your portfolio. + + Follow Ghostfolio on X (formerly Twitter) + 在 X (前身为 Twitter) 上关注 Ghostfolio - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 24 + apps/client/src/app/pages/about/overview/about-overview-page.html + 93 - - Save - Save + + Send an e-mail + 发送电子邮件 - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 61 + apps/client/src/app/pages/about/overview/about-overview-page.html + 103 - - Asset Class Cluster Risks - Asset Class Cluster Risks + + Follow Ghostfolio on LinkedIn + 在 LinkedIn 上关注 Ghostfolio - apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 82 + apps/client/src/app/pages/about/overview/about-overview-page.html + 122 - - Me - Me + + Ghostfolio is an independent & bootstrapped business + Ghostfolio 是一家独立的自筹资金企业 - apps/client/src/app/components/user-account-access/user-account-access.component.ts - 134 + apps/client/src/app/pages/about/overview/about-overview-page.html + 132 - - Received Access - Received Access + + Support Ghostfolio + 支持 Ghostfolio - apps/client/src/app/components/user-account-access/user-account-access.html - 3 + apps/client/src/app/pages/about/overview/about-overview-page.html + 141 diff --git a/apps/client/src/styles.scss b/apps/client/src/styles.scss index b13b088b7..c13c3388f 100644 --- a/apps/client/src/styles.scss +++ b/apps/client/src/styles.scss @@ -1,7 +1,7 @@ @import './styles/bootstrap'; @import './styles/table'; -@import 'node_modules/svgmap/dist/svgMap'; +@import 'svgmap/dist/svgMap'; :root { --dark-background: rgb(25, 25, 25); @@ -237,10 +237,10 @@ body { } .mat-mdc-dialog-container { - --mdc-dialog-container-color: var(--dark-background); + --mat-dialog-container-color: var(--dark-background); .mdc-dialog__content { - --mdc-dialog-supporting-text-color: rgba(var(--light-primary-text)); + --mat-dialog-supporting-text-color: rgba(var(--light-primary-text)); } } @@ -252,13 +252,13 @@ body { } .mat-mdc-card { - --mdc-elevated-card-container-color: var(--dark-background); - --mdc-outlined-card-container-color: var(--dark-background); + --mat-card-elevated-container-color: var(--dark-background); + --mat-card-outlined-container-color: var(--dark-background); } .mat-mdc-fab { &.mat-primary { - --mdc-fab-icon-color: rgba(var(--dark-primary-text)); + --mat-fab-icon-color: rgba(var(--dark-primary-text)); --mat-mdc-fab-color: rgba(var(--dark-primary-text)); } } @@ -270,16 +270,14 @@ body { .mdc-button { &.mat-accent, &.mat-primary { - --mdc-filled-button-label-text-color: rgba(var(--dark-primary-text)); + --mat-button-filled-label-text-color: rgba(var(--dark-primary-text)); } } .page { &.has-tabs { .mat-mdc-tab-nav-bar { - --mat-tab-header-inactive-label-text-color: rgba( - var(--light-primary-text) - ); + --mat-tab-inactive-label-text-color: rgba(var(--light-primary-text)); } @media (min-width: 576px) { @@ -414,6 +412,14 @@ ngx-skeleton-loader { } } +.mat-mdc-card { + .mat-mdc-card-title { + --mat-card-title-text-line-height: 1.2; + + margin-bottom: 0.5rem; + } +} + .mat-mdc-checkbox { label { margin-bottom: 0; @@ -422,7 +428,7 @@ ngx-skeleton-loader { .mat-mdc-dialog-container { .mdc-dialog__content { - --mdc-dialog-supporting-text-color: rgba(var(--dark-primary-text)); + --mat-dialog-supporting-text-color: rgba(var(--dark-primary-text)); } } @@ -437,7 +443,7 @@ ngx-skeleton-loader { color: var(--mat-mdc-fab-color, inherit) !important; &.mat-primary { - --mdc-fab-icon-color: rgba(var(--light-primary-text)); + --mat-fab-icon-color: rgba(var(--light-primary-text)); --mat-mdc-fab-color: rgba(var(--light-primary-text)); } } @@ -451,7 +457,7 @@ ngx-skeleton-loader { } .mat-mdc-menu-panel { - &.assistant { + &.no-max-width { max-width: unset !important; .mat-mdc-menu-content { @@ -499,7 +505,7 @@ ngx-skeleton-loader { .mdc-button { &.mat-accent, &.mat-primary { - --mdc-filled-button-label-text-color: rgba(var(--light-primary-text)); + --mat-button-filled-label-text-color: rgba(var(--light-primary-text)); } } @@ -549,12 +555,10 @@ ngx-skeleton-loader { } .mat-mdc-tab-nav-bar { - --mat-tab-header-active-focus-indicator-color: transparent; - --mat-tab-header-active-hover-indicator-color: transparent; - --mat-tab-header-inactive-label-text-color: rgba( - var(--dark-primary-text) - ); - --mdc-tab-indicator-active-indicator-color: transparent; + --mat-tab-active-focus-indicator-color: transparent; + --mat-tab-active-hover-indicator-color: transparent; + --mat-tab-inactive-label-text-color: rgba(var(--dark-primary-text)); + --mat-tab-active-indicator-color: transparent; } .mat-mdc-tab-nav-panel { @@ -563,7 +567,7 @@ ngx-skeleton-loader { @media (max-width: 575.98px) { .mat-mdc-tab-link { - --mdc-secondary-navigation-tab-container-height: 3rem; + --mat-tab-container-height: 3rem; } } @@ -574,8 +578,8 @@ ngx-skeleton-loader { background-color: rgba(var(--palette-foreground-base), 0.02); padding: 2rem 0; width: 14rem; - --mat-tab-header-label-text-tracking: normal; - --mdc-secondary-navigation-tab-container-height: 2rem; + --mat-tab-label-text-tracking: normal; + --mat-tab-container-height: 2rem; .mat-mdc-tab-links { flex-direction: column; diff --git a/apps/client/src/styles/bootstrap.scss b/apps/client/src/styles/bootstrap.scss index 5e49e3e99..cf9d4d2e3 100644 --- a/apps/client/src/styles/bootstrap.scss +++ b/apps/client/src/styles/bootstrap.scss @@ -1,44 +1,44 @@ /*! - * Bootstrap v4.5.2 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors - * Copyright 2011-2020 Twitter, Inc. + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ -@import 'node_modules/bootstrap/scss/functions'; -@import 'node_modules/bootstrap/scss/variables'; -@import 'node_modules/bootstrap/scss/mixins'; -@import 'node_modules/bootstrap/scss/root'; -@import 'node_modules/bootstrap/scss/reboot'; -@import 'node_modules/bootstrap/scss/type'; -@import 'node_modules/bootstrap/scss/images'; -// @import 'node_modules/bootstrap/scss/code'; -@import 'node_modules/bootstrap/scss/grid'; -// @import 'node_modules/bootstrap/scss/tables'; -// @import 'node_modules/bootstrap/scss/forms'; -// @import 'node_modules/bootstrap/scss/buttons'; -// @import 'node_modules/bootstrap/scss/transitions'; -// @import 'node_modules/bootstrap/scss/dropdown'; -// @import 'node_modules/bootstrap/scss/button-group'; -// @import 'node_modules/bootstrap/scss/input-group'; -// @import 'node_modules/bootstrap/scss/custom-forms'; -// @import 'node_modules/bootstrap/scss/nav'; -// @import 'node_modules/bootstrap/scss/navbar'; -// @import 'node_modules/bootstrap/scss/card'; -@import 'node_modules/bootstrap/scss/breadcrumb'; -// @import 'node_modules/bootstrap/scss/pagination'; -@import 'node_modules/bootstrap/scss/badge'; -// @import 'node_modules/bootstrap/scss/jumbotron'; -// @import 'node_modules/bootstrap/scss/alert'; -// @import 'node_modules/bootstrap/scss/progress'; -// @import 'node_modules/bootstrap/scss/media'; -// @import 'node_modules/bootstrap/scss/list-group'; -// @import 'node_modules/bootstrap/scss/close'; -// @import 'node_modules/bootstrap/scss/toasts'; -// @import 'node_modules/bootstrap/scss/modal'; -// @import 'node_modules/bootstrap/scss/tooltip'; -// @import 'node_modules/bootstrap/scss/popover'; -// @import 'node_modules/bootstrap/scss/carousel'; -// @import 'node_modules/bootstrap/scss/spinners'; -@import 'node_modules/bootstrap/scss/utilities'; -// @import 'node_modules/bootstrap/scss/print'; +@import 'bootstrap/scss/functions'; +@import 'bootstrap/scss/variables'; +@import 'bootstrap/scss/mixins'; +@import 'bootstrap/scss/root'; +@import 'bootstrap/scss/reboot'; +@import 'bootstrap/scss/type'; +@import 'bootstrap/scss/images'; +// @import 'bootstrap/scss/code'; +@import 'bootstrap/scss/grid'; +// @import 'bootstrap/scss/tables'; +// @import 'bootstrap/scss/forms'; +// @import 'bootstrap/scss/buttons'; +// @import 'bootstrap/scss/transitions'; +// @import 'bootstrap/scss/dropdown'; +// @import 'bootstrap/scss/button-group'; +// @import 'bootstrap/scss/input-group'; +// @import 'bootstrap/scss/custom-forms'; +// @import 'bootstrap/scss/nav'; +// @import 'bootstrap/scss/navbar'; +// @import 'bootstrap/scss/card'; +@import 'bootstrap/scss/breadcrumb'; +// @import 'bootstrap/scss/pagination'; +@import 'bootstrap/scss/badge'; +// @import 'bootstrap/scss/jumbotron'; +// @import 'bootstrap/scss/alert'; +// @import 'bootstrap/scss/progress'; +// @import 'bootstrap/scss/media'; +// @import 'bootstrap/scss/list-group'; +// @import 'bootstrap/scss/close'; +// @import 'bootstrap/scss/toasts'; +// @import 'bootstrap/scss/modal'; +// @import 'bootstrap/scss/tooltip'; +// @import 'bootstrap/scss/popover'; +// @import 'bootstrap/scss/carousel'; +// @import 'bootstrap/scss/spinners'; +@import 'bootstrap/scss/utilities'; +// @import 'bootstrap/scss/print'; diff --git a/apps/client/src/styles/theme.scss b/apps/client/src/styles/theme.scss index 23ab5bcae..9add22d6a 100644 --- a/apps/client/src/styles/theme.scss +++ b/apps/client/src/styles/theme.scss @@ -189,7 +189,7 @@ $_tertiary: map.merge(map.get($_palettes, tertiary), $_rest); --gf-theme-secondary-500-rgb: 78, 208, 94; --mat-dialog-container-small-max-width: 96vw; - --mdc-filled-button-label-text-tracking: normal; - --mdc-outlined-button-label-text-tracking: normal; - --mdc-text-button-label-text-tracking: normal; + --mat-button-filled-label-text-tracking: normal; + --mat-button-outlined-label-text-tracking: normal; + --mat-button-text-label-text-tracking: normal; } diff --git a/apps/client/tsconfig.app.json b/apps/client/tsconfig.app.json index 56a5535d4..6f3ea7448 100644 --- a/apps/client/tsconfig.app.json +++ b/apps/client/tsconfig.app.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "moduleResolution": "bundler", "outDir": "../../dist/out-tsc", "types": ["node"], "typeRoots": ["../../node_modules/@types"], diff --git a/apps/ui-e2e/.eslintrc.json b/apps/ui-e2e/.eslintrc.json deleted file mode 100644 index e1ff28793..000000000 --- a/apps/ui-e2e/.eslintrc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "parserOptions": { - "project": ["apps/ui-e2e/tsconfig.json"] - }, - "rules": {} - }, - { - "files": ["src/plugins/index.js"], - "rules": { - "@typescript-eslint/no-var-requires": "off", - "no-undef": "off" - } - } - ] -} diff --git a/apps/ui-e2e/eslint.config.cjs b/apps/ui-e2e/eslint.config.cjs new file mode 100644 index 000000000..5e6707635 --- /dev/null +++ b/apps/ui-e2e/eslint.config.cjs @@ -0,0 +1,33 @@ +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); +const baseConfig = require('../../eslint.config.cjs'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended +}); + +module.exports = [ + { + ignores: ['**/dist'] + }, + ...baseConfig, + ...compat.extends('plugin:cypress/recommended'), + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {}, + languageOptions: { + parserOptions: { + project: ['apps/ui-e2e/tsconfig.json'] + } + } + }, + { + files: ['src/plugins/index.js'], + rules: { + '@typescript-eslint/no-var-requires': 'off', + 'no-undef': 'off' + } + } +]; diff --git a/apps/ui-e2e/project.json b/apps/ui-e2e/project.json index 4595b6c66..a5b4cf53a 100644 --- a/apps/ui-e2e/project.json +++ b/apps/ui-e2e/project.json @@ -3,13 +3,14 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "apps/ui-e2e/src", "projectType": "application", + "tags": [], + "implicitDependencies": ["ui"], "targets": { "e2e": { "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "apps/ui-e2e/cypress.json", - "devServerTarget": "ui:storybook", - "tsConfig": "apps/ui-e2e/tsconfig.json" + "devServerTarget": "ui:storybook" }, "configurations": { "ci": { @@ -23,7 +24,5 @@ "lintFilePatterns": ["apps/ui-e2e/**/*.{js,ts}"] } } - }, - "tags": [], - "implicitDependencies": ["ui"] + } } diff --git a/docker/docker-compose.build.yml b/docker/docker-compose.build.yml index 96829ad34..a2b3e7cb4 100644 --- a/docker/docker-compose.build.yml +++ b/docker/docker-compose.build.yml @@ -2,51 +2,22 @@ name: ghostfolio_build services: ghostfolio: build: ../ - container_name: ghostfolio-build - init: true - env_file: - - ../.env - environment: - DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer - REDIS_HOST: redis - REDIS_PASSWORD: ${REDIS_PASSWORD} - ports: - - 3333:3333 - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - healthcheck: - test: ['CMD-SHELL', 'curl -f http://localhost:3333/api/v1/health'] - interval: 10s - timeout: 5s - retries: 5 + image: ghostfolio/ghostfolio:local + extends: + file: docker-compose.yml + service: ghostfolio postgres: - image: docker.io/library/postgres:15 container_name: gf-postgres-build - env_file: - - ../.env - healthcheck: - test: ['CMD-SHELL', 'pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}'] - interval: 10s - timeout: 5s - retries: 5 - volumes: - - postgres:/var/lib/postgresql/data + extends: + file: docker-compose.yml + service: postgres redis: - image: docker.io/library/redis:alpine container_name: gf-redis-build - env_file: - - ../.env - command: ['redis-server', '--requirepass', $REDIS_PASSWORD] - healthcheck: - test: ['CMD-SHELL', 'redis-cli --pass "$REDIS_PASSWORD" ping | grep PONG'] - interval: 10s - timeout: 5s - retries: 5 + extends: + file: docker-compose.yml + service: redis volumes: postgres: diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 39a1d56e9..ec91025ea 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -1,23 +1,18 @@ name: ghostfolio_dev services: postgres: - image: docker.io/library/postgres:15 + extends: + file: docker-compose.yml + service: postgres container_name: gf-postgres-dev - restart: unless-stopped - env_file: - - ../.env ports: - ${POSTGRES_PORT:-5432}:5432 - volumes: - - postgres:/var/lib/postgresql/data redis: - image: docker.io/library/redis:alpine + extends: + file: docker-compose.yml + service: redis container_name: gf-redis-dev - restart: unless-stopped - env_file: - - ../.env - command: ['redis-server', '--requirepass', $REDIS_PASSWORD] ports: - ${REDIS_PORT:-6379}:6379 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index c6ec5b3d7..8c69e5420 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,6 +3,7 @@ services: ghostfolio: image: docker.io/ghostfolio/ghostfolio:latest container_name: ghostfolio + restart: unless-stopped init: true cap_drop: - ALL @@ -10,10 +11,6 @@ services: - no-new-privileges:true env_file: - ../.env - environment: - DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer - REDIS_HOST: redis - REDIS_PASSWORD: ${REDIS_PASSWORD} ports: - 3333:3333 depends_on: @@ -28,8 +25,9 @@ services: retries: 5 postgres: - image: docker.io/library/postgres:15 + image: docker.io/library/postgres:15-alpine container_name: gf-postgres + restart: unless-stopped cap_drop: - ALL cap_add: @@ -43,7 +41,8 @@ services: env_file: - ../.env healthcheck: - test: ['CMD-SHELL', 'pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}'] + test: + ['CMD-SHELL', 'pg_isready -d "$${POSTGRES_DB}" -U $${POSTGRES_USER}'] interval: 10s timeout: 5s retries: 5 @@ -53,6 +52,7 @@ services: redis: image: docker.io/library/redis:alpine container_name: gf-redis + restart: unless-stopped user: '999:1000' cap_drop: - ALL @@ -60,9 +60,13 @@ services: - no-new-privileges:true env_file: - ../.env - command: ['redis-server', '--requirepass', $REDIS_PASSWORD] + command: + - /bin/sh + - -c + - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}" healthcheck: - test: ['CMD-SHELL', 'redis-cli --pass "$REDIS_PASSWORD" ping | grep PONG'] + test: + ['CMD-SHELL', 'redis-cli --pass "$${REDIS_PASSWORD}" ping | grep PONG'] interval: 10s timeout: 5s retries: 5 diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 71cf6f2dc..440886903 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -9,4 +9,4 @@ echo "Seeding the database" npx prisma db seed echo "Starting the server" -node main +exec node main diff --git a/eslint.config.cjs b/eslint.config.cjs new file mode 100644 index 000000000..c7e08821c --- /dev/null +++ b/eslint.config.cjs @@ -0,0 +1,196 @@ +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); +const nxEslintPlugin = require('@nx/eslint-plugin'); +const storybook = require('eslint-plugin-storybook'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended +}); + +module.exports = [ + { + ignores: ['**/dist'] + }, + ...storybook.configs['flat/recommended'], + { plugins: { '@nx': nxEslintPlugin } }, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + rules: { + '@nx/enforce-module-boundaries': [ + 'warn', + { + enforceBuildableLibDependency: true, + allow: [], + depConstraints: [ + { + sourceTag: '*', + onlyDependOnLibsWithTags: ['*'] + } + ] + } + ], + '@typescript-eslint/no-extra-semi': 'error', + 'no-extra-semi': 'off' + } + }, + ...compat + .config({ + extends: ['plugin:@nx/typescript'] + }) + .map((config) => ({ + ...config, + files: ['**/*.ts', '**/*.tsx', '**/*.cts', '**/*.mts'], + rules: { + ...config.rules + } + })), + ...compat + .config({ + extends: ['plugin:@nx/javascript'] + }) + .map((config) => ({ + ...config, + files: ['**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs'], + rules: { + ...config.rules + } + })), + ...compat + .config({ + plugins: ['eslint-plugin-import', '@typescript-eslint'], + extends: [ + 'plugin:@typescript-eslint/recommended-type-checked', + 'plugin:@typescript-eslint/stylistic-type-checked' + ] + }) + .map((config) => ({ + ...config, + files: ['**/*.ts'], + rules: { + ...config.rules, + '@typescript-eslint/consistent-indexed-object-style': 'off', + '@typescript-eslint/dot-notation': 'off', + '@typescript-eslint/explicit-member-accessibility': [ + 'off', + { + accessibility: 'explicit' + } + ], + '@typescript-eslint/member-ordering': 'warn', + '@typescript-eslint/naming-convention': [ + 'off', + { + selector: 'default', + format: ['camelCase'], + leadingUnderscore: 'allow', + trailingUnderscore: 'allow' + }, + { + selector: ['variable', 'classProperty', 'typeProperty'], + format: ['camelCase', 'UPPER_CASE'], + leadingUnderscore: 'allow', + trailingUnderscore: 'allow' + }, + { + selector: 'objectLiteralProperty', + format: null + }, + { + selector: 'enumMember', + format: ['camelCase', 'UPPER_CASE', 'PascalCase'] + }, + { + selector: 'typeLike', + format: ['PascalCase'] + } + ], + '@typescript-eslint/no-empty-interface': 'warn', + '@typescript-eslint/no-inferrable-types': [ + 'warn', + { + ignoreParameters: true + } + ], + '@typescript-eslint/no-non-null-assertion': 'warn', + '@typescript-eslint/no-shadow': [ + 'warn', + { + hoist: 'all' + } + ], + '@typescript-eslint/unified-signatures': 'error', + '@typescript-eslint/no-loss-of-precision': 'warn', + '@typescript-eslint/no-var-requires': 'warn', + 'arrow-body-style': 'off', + 'constructor-super': 'error', + eqeqeq: ['error', 'smart'], + 'guard-for-in': 'warn', + 'id-blacklist': 'off', + 'id-match': 'off', + 'import/no-deprecated': 'warn', + 'no-bitwise': 'error', + 'no-caller': 'error', + 'no-debugger': 'error', + 'no-empty': 'off', + 'no-eval': 'error', + 'no-fallthrough': 'error', + 'no-new-wrappers': 'error', + 'no-restricted-imports': ['error', 'rxjs/Rx'], + 'no-undef-init': 'error', + 'no-underscore-dangle': 'off', + 'no-var': 'error', + radix: 'error', + 'no-unsafe-optional-chaining': 'warn', + 'no-extra-boolean-cast': 'warn', + 'no-empty-pattern': 'warn', + 'no-useless-catch': 'warn', + 'no-unsafe-finally': 'warn', + 'no-prototype-builtins': 'warn', + 'no-async-promise-executor': 'warn', + 'no-constant-condition': 'warn', + + // The following rules are part of eslint:recommended + // and can be remove once solved + 'no-constant-binary-expression': 'warn', + 'no-loss-of-precision': 'warn', + + // The following rules are part of @typescript-eslint/recommended-type-checked + // and can be remove once solved + '@typescript-eslint/await-thenable': 'warn', + '@typescript-eslint/ban-ts-comment': 'warn', + '@typescript-eslint/no-base-to-string': 'warn', + '@typescript-eslint/no-empty-object-type': 'warn', + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-floating-promises': 'warn', + '@typescript-eslint/no-misused-promises': 'warn', + '@typescript-eslint/no-redundant-type-constituents': 'warn', + '@typescript-eslint/no-require-imports': 'warn', + '@typescript-eslint/no-unnecessary-type-assertion': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-enum-comparison': 'warn', + '@typescript-eslint/no-unsafe-function-type': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/no-unsafe-return': 'warn', + '@typescript-eslint/no-unsafe-call': 'warn', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + caughtErrors: 'none' + } + ], + '@typescript-eslint/no-wrapper-object-types': 'warn', + '@typescript-eslint/only-throw-error': 'warn', + '@typescript-eslint/prefer-promise-reject-errors': 'warn', + '@typescript-eslint/require-await': 'warn', + '@typescript-eslint/restrict-template-expressions': 'warn', + '@typescript-eslint/unbound-method': 'warn', + + // The following rules are part of @typescript-eslint/stylistic-type-checked + // and can be remove once solved + '@typescript-eslint/prefer-nullish-coalescing': 'warn', // TODO: Requires strictNullChecks: true + '@typescript-eslint/prefer-regexp-exec': 'warn' + } + })) +]; diff --git a/libs/common/.eslintrc.json b/libs/common/.eslintrc.json deleted file mode 100644 index 69cfc2050..000000000 --- a/libs/common/.eslintrc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "parserOptions": { - "project": ["libs/common/tsconfig.*?.json"] - }, - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/libs/common/eslint.config.cjs b/libs/common/eslint.config.cjs new file mode 100644 index 000000000..a78dde897 --- /dev/null +++ b/libs/common/eslint.config.cjs @@ -0,0 +1,28 @@ +const baseConfig = require('../../eslint.config.cjs'); + +module.exports = [ + { + ignores: ['**/dist'] + }, + ...baseConfig, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {}, + languageOptions: { + parserOptions: { + project: ['libs/common/tsconfig.*?.json'] + } + } + }, + { + files: ['**/*.ts', '**/*.tsx'], + // Override or add rules here + rules: {} + }, + { + files: ['**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {} + } +]; diff --git a/libs/common/src/lib/calculation-helper.ts b/libs/common/src/lib/calculation-helper.ts index 4292f2383..d67384a30 100644 --- a/libs/common/src/lib/calculation-helper.ts +++ b/libs/common/src/lib/calculation-helper.ts @@ -23,10 +23,14 @@ export function getAnnualizedPerformancePercent({ }): Big { if (isNumber(daysInMarket) && daysInMarket > 0) { const exponent = new Big(365).div(daysInMarket).toNumber(); + const growthFactor = Math.pow( + netPerformancePercentage.plus(1).toNumber(), + exponent + ); - return new Big( - Math.pow(netPerformancePercentage.plus(1).toNumber(), exponent) - ).minus(1); + if (!isNaN(growthFactor)) { + return new Big(growthFactor).minus(1); + } } return new Big(0); diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 7608e43a8..467716575 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -1,11 +1,15 @@ -import { DataSource } from '@prisma/client'; +import { AssetClass, AssetSubClass, DataSource, Type } from '@prisma/client'; import { JobOptions, JobStatus } from 'bull'; import ms from 'ms'; export const ghostfolioPrefix = 'GF'; export const ghostfolioScraperApiSymbolPrefix = `_${ghostfolioPrefix}_`; -export const ghostfolioFearAndGreedIndexDataSource = DataSource.RAPID_API; +export const ghostfolioFearAndGreedIndexDataSourceCryptocurrencies = + DataSource.MANUAL; +export const ghostfolioFearAndGreedIndexDataSourceStocks = DataSource.RAPID_API; export const ghostfolioFearAndGreedIndexSymbol = `${ghostfolioScraperApiSymbolPrefix}FEAR_AND_GREED_INDEX`; +export const ghostfolioFearAndGreedIndexSymbolCryptocurrencies = `${ghostfolioPrefix}_FEAR_AND_GREED_INDEX_CRYPTOCURRENCIES`; +export const ghostfolioFearAndGreedIndexSymbolStocks = `${ghostfolioPrefix}_FEAR_AND_GREED_INDEX_STOCKS`; export const locale = 'en-US'; @@ -30,6 +34,23 @@ export const warnColorRgb = { b: 69 }; +export const ASSET_CLASS_MAPPING = new Map([ + [AssetClass.ALTERNATIVE_INVESTMENT, [AssetSubClass.COLLECTIBLE]], + [AssetClass.COMMODITY, [AssetSubClass.PRECIOUS_METAL]], + [ + AssetClass.EQUITY, + [ + AssetSubClass.ETF, + AssetSubClass.MUTUALFUND, + AssetSubClass.PRIVATE_EQUITY, + AssetSubClass.STOCK + ] + ], + [AssetClass.FIXED_INCOME, [AssetSubClass.BOND]], + [AssetClass.LIQUIDITY, [AssetSubClass.CRYPTOCURRENCY]], + [AssetClass.REAL_ESTATE, []] +]); + export const CACHE_TTL_NO_CACHE = 1; export const CACHE_TTL_INFINITE = 0; @@ -48,13 +69,14 @@ export const PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_LOW = export const DEFAULT_CURRENCY = 'USD'; export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy'; +export const DEFAULT_HOST = '0.0.0.0'; export const DEFAULT_LANGUAGE_CODE = 'en'; export const DEFAULT_PAGE_SIZE = 50; +export const DEFAULT_PORT = 3333; export const DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY = 1; export const DEFAULT_PROCESSOR_GATHER_HISTORICAL_MARKET_DATA_CONCURRENCY = 1; export const DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_CONCURRENCY = 1; export const DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_TIMEOUT = 30000; -export const DEFAULT_ROOT_URL = 'https://localhost:4200'; // USX is handled separately export const DERIVED_CURRENCIES = [ @@ -75,10 +97,8 @@ export const DERIVED_CURRENCIES = [ } ]; -export const EMERGENCY_FUND_TAG_ID = '4452656d-9fa4-4bd0-ba38-70492e31d180'; - -export const GATHER_ASSET_PROFILE_PROCESS = 'GATHER_ASSET_PROFILE'; -export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = { +export const GATHER_ASSET_PROFILE_PROCESS_JOB_NAME = 'GATHER_ASSET_PROFILE'; +export const GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS: JobOptions = { attempts: 12, backoff: { delay: ms('1 minute'), @@ -98,6 +118,12 @@ export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true }; +export const INVESTMENT_ACTIVITY_TYPES = [ + Type.BUY, + Type.DIVIDEND, + Type.SELL +] as Type[]; + export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME = 'PORTFOLIO'; export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true @@ -113,6 +139,7 @@ export const MAX_TOP_HOLDINGS = 50; export const NUMERICAL_PRECISION_THRESHOLD = 100000; export const PROPERTY_API_KEY_GHOSTFOLIO = 'API_KEY_GHOSTFOLIO'; +export const PROPERTY_API_KEY_OPENROUTER = 'API_KEY_OPENROUTER'; export const PROPERTY_BENCHMARKS = 'BENCHMARKS'; export const PROPERTY_BETTER_UPTIME_MONITOR_ID = 'BETTER_UPTIME_MONITOR_ID'; export const PROPERTY_COUNTRIES_OF_SUBSCRIBERS = 'COUNTRIES_OF_SUBSCRIBERS'; @@ -121,10 +148,12 @@ export const PROPERTY_CURRENCIES = 'CURRENCIES'; export const PROPERTY_DATA_SOURCE_MAPPING = 'DATA_SOURCE_MAPPING'; export const PROPERTY_DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER_MAX_REQUESTS = 'DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER_MAX_REQUESTS'; +export const PROPERTY_DEMO_ACCOUNT_ID = 'DEMO_ACCOUNT_ID'; export const PROPERTY_DEMO_USER_ID = 'DEMO_USER_ID'; export const PROPERTY_IS_DATA_GATHERING_ENABLED = 'IS_DATA_GATHERING_ENABLED'; export const PROPERTY_IS_READ_ONLY_MODE = 'IS_READ_ONLY_MODE'; export const PROPERTY_IS_USER_SIGNUP_ENABLED = 'IS_USER_SIGNUP_ENABLED'; +export const PROPERTY_OPENROUTER_MODEL = 'OPENROUTER_MODEL'; export const PROPERTY_SLACK_COMMUNITY_USERS = 'SLACK_COMMUNITY_USERS'; export const PROPERTY_STRIPE_CONFIG = 'STRIPE_CONFIG'; export const PROPERTY_SYSTEM_MESSAGE = 'SYSTEM_MESSAGE'; @@ -153,6 +182,8 @@ export const REPLACE_NAME_PARTS = [ 'Xtrackers (IE) Plc -' ]; +export const STORYBOOK_PATH = '/development/storybook'; + export const SUPPORTED_LANGUAGE_CODES = [ 'ca', 'de', @@ -164,7 +195,11 @@ export const SUPPORTED_LANGUAGE_CODES = [ 'pl', 'pt', 'tr', + 'uk', 'zh' ]; +export const TAG_ID_EMERGENCY_FUND = '4452656d-9fa4-4bd0-ba38-70492e31d180'; +export const TAG_ID_DEMO = 'efa08cb3-9b9d-4974-ac68-db13a19c4874'; + export const UNKNOWN_KEY = 'UNKNOWN'; diff --git a/libs/common/src/lib/helper.spec.ts b/libs/common/src/lib/helper.spec.ts index 1126c3573..25779cf39 100644 --- a/libs/common/src/lib/helper.spec.ts +++ b/libs/common/src/lib/helper.spec.ts @@ -1,4 +1,7 @@ -import { extractNumberFromString } from '@ghostfolio/common/helper'; +import { + extractNumberFromString, + getNumberFormatGroup +} from '@ghostfolio/common/helper'; describe('Helper', () => { describe('Extract number from string', () => { @@ -32,8 +35,85 @@ describe('Helper', () => { ).toEqual(99999.99); }); + it('Get decimal number (comma notation) for locale where currency is not grouped by default', () => { + expect( + extractNumberFromString({ locale: 'es-ES', value: '999,99' }) + ).toEqual(999.99); + }); + it('Not a number', () => { expect(extractNumberFromString({ value: 'X' })).toEqual(NaN); }); }); + + describe('Get number format group', () => { + let languageGetter: jest.SpyInstance; + + beforeEach(() => { + languageGetter = jest.spyOn(window.navigator, 'language', 'get'); + }); + + it('Get de-CH number format group', () => { + expect(getNumberFormatGroup('de-CH')).toEqual('’'); + }); + + it('Get de-CH number format group when it is default', () => { + languageGetter.mockReturnValue('de-CH'); + expect(getNumberFormatGroup()).toEqual('’'); + }); + + it('Get de-DE number format group', () => { + expect(getNumberFormatGroup('de-DE')).toEqual('.'); + }); + + it('Get de-DE number format group when it is default', () => { + languageGetter.mockReturnValue('de-DE'); + expect(getNumberFormatGroup()).toEqual('.'); + }); + + it('Get en-GB number format group', () => { + expect(getNumberFormatGroup('en-GB')).toEqual(','); + }); + + it('Get en-GB number format group when it is default', () => { + languageGetter.mockReturnValue('en-GB'); + expect(getNumberFormatGroup()).toEqual(','); + }); + + it('Get en-US number format group', () => { + expect(getNumberFormatGroup('en-US')).toEqual(','); + }); + + it('Get en-US number format group when it is default', () => { + languageGetter.mockReturnValue('en-US'); + expect(getNumberFormatGroup()).toEqual(','); + }); + + it('Get es-ES number format group', () => { + expect(getNumberFormatGroup('es-ES')).toEqual('.'); + }); + + it('Get es-ES number format group when it is default', () => { + languageGetter.mockReturnValue('es-ES'); + expect(getNumberFormatGroup()).toEqual('.'); + }); + + it('Get ru-RU number format group', () => { + expect(getNumberFormatGroup('ru-RU')).toEqual(' '); + }); + + it('Get ru-RU number format group when it is default', () => { + languageGetter.mockReturnValue('ru-RU'); + expect(getNumberFormatGroup()).toEqual(' '); + }); + + it('Get zh-CN number format group', () => { + expect(getNumberFormatGroup('zh-CN')).toEqual(','); + }); + + it('Get zh-CN number format group when it is default', () => { + languageGetter.mockReturnValue('zh-CN'); + expect(getNumberFormatGroup()).toEqual(','); + }); + }); }); diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index a7cf59a10..e5dc187ff 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -1,6 +1,6 @@ import * as currencies from '@dinero.js/currencies'; import { NumberParser } from '@internationalized/number'; -import { DataSource, MarketData, Type as ActivityType } from '@prisma/client'; +import { Type as ActivityType, DataSource, MarketData } from '@prisma/client'; import { Big } from 'big.js'; import { getDate, @@ -11,7 +11,7 @@ import { parseISO, subDays } from 'date-fns'; -import { ca, de, es, fr, it, nl, pl, pt, tr, zhCN } from 'date-fns/locale'; +import { ca, de, es, fr, it, nl, pl, pt, tr, uk, zhCN } from 'date-fns/locale'; import { DEFAULT_CURRENCY, @@ -192,6 +192,8 @@ export function getDateFnsLocale(aLanguageCode: string) { return pt; } else if (aLanguageCode === 'tr') { return tr; + } else if (aLanguageCode === 'uk') { + return uk; } else if (aLanguageCode === 'zh') { return zhCN; } @@ -249,7 +251,9 @@ export function getNumberFormatDecimal(aLocale?: string) { } export function getNumberFormatGroup(aLocale = getLocale()) { - const formatObject = new Intl.NumberFormat(aLocale).formatToParts(9999.99); + const formatObject = new Intl.NumberFormat(aLocale, { + useGrouping: true + }).formatToParts(9999.99); return formatObject.find((object) => { return object.type === 'group'; @@ -345,11 +349,21 @@ export function isDerivedCurrency(aCurrency: string) { return true; } - return DERIVED_CURRENCIES.find(({ currency }) => { + return DERIVED_CURRENCIES.some(({ currency }) => { return currency === aCurrency; }); } +export function isRootCurrency(aCurrency: string) { + if (aCurrency === 'USD') { + return true; + } + + return DERIVED_CURRENCIES.find(({ rootCurrency }) => { + return rootCurrency === aCurrency; + }); +} + export function parseDate(date: string): Date { if (!date) { return undefined; diff --git a/libs/common/src/lib/interfaces/account-balance.interface.ts b/libs/common/src/lib/interfaces/account-balance.interface.ts new file mode 100644 index 000000000..00fcf1e53 --- /dev/null +++ b/libs/common/src/lib/interfaces/account-balance.interface.ts @@ -0,0 +1,4 @@ +export interface AccountBalance { + date: string; + value: number; +} diff --git a/libs/common/src/lib/interfaces/admin-data.interface.ts b/libs/common/src/lib/interfaces/admin-data.interface.ts index 3dc476df8..cef983902 100644 --- a/libs/common/src/lib/interfaces/admin-data.interface.ts +++ b/libs/common/src/lib/interfaces/admin-data.interface.ts @@ -1,11 +1,7 @@ -import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; +import { DataProviderInfo } from './data-provider-info.interface'; export interface AdminData { - exchangeRates: ({ - label1: string; - label2: string; - value: number; - } & AssetProfileIdentifier)[]; + dataProviders: (DataProviderInfo & { assetProfileCount: number })[]; settings: { [key: string]: boolean | object | string | string[] }; transactionCount: number; userCount: number; diff --git a/libs/common/src/lib/interfaces/admin-market-data.interface.ts b/libs/common/src/lib/interfaces/admin-market-data.interface.ts index 90fceadb3..953f94e26 100644 --- a/libs/common/src/lib/interfaces/admin-market-data.interface.ts +++ b/libs/common/src/lib/interfaces/admin-market-data.interface.ts @@ -14,6 +14,7 @@ export interface AdminMarketDataItem { dataSource: DataSource; date: Date; id: string; + isActive: boolean; isBenchmark?: boolean; isUsedByUsersWithSubscription?: boolean; lastMarketPrice: number; @@ -21,4 +22,5 @@ export interface AdminMarketDataItem { name: string; sectorsCount: number; symbol: string; + watchedByCount: number; } diff --git a/libs/common/src/lib/interfaces/admin-users.interface.ts b/libs/common/src/lib/interfaces/admin-users.interface.ts index 89e165752..79031425a 100644 --- a/libs/common/src/lib/interfaces/admin-users.interface.ts +++ b/libs/common/src/lib/interfaces/admin-users.interface.ts @@ -4,6 +4,7 @@ export interface AdminUsers { count: number; users: { accountCount: number; + activityCount: number; country: string; createdAt: Date; dailyApiRequests: number; @@ -11,6 +12,5 @@ export interface AdminUsers { id: string; lastActivity: Date; role: Role; - transactionCount: number; }[]; } diff --git a/libs/common/src/lib/interfaces/data-provider-info.interface.ts b/libs/common/src/lib/interfaces/data-provider-info.interface.ts index 79d7d6940..9fba0e62d 100644 --- a/libs/common/src/lib/interfaces/data-provider-info.interface.ts +++ b/libs/common/src/lib/interfaces/data-provider-info.interface.ts @@ -1,4 +1,7 @@ +import { DataSource } from '@prisma/client'; + export interface DataProviderInfo { + dataSource?: DataSource; isPremium: boolean; name?: string; url?: string; diff --git a/libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts b/libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts index ce585c6a3..4cc6ba8aa 100644 --- a/libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts +++ b/libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts @@ -14,6 +14,7 @@ export interface EnhancedSymbolProfile { countries: Country[]; createdAt: Date; currency?: string; + cusip?: string; dataProviderInfo?: DataProviderInfo; dataSource: DataSource; dateOfFirstActivity?: Date; @@ -22,6 +23,7 @@ export interface EnhancedSymbolProfile { figiShareClass?: string; holdings: Holding[]; id: string; + isActive: boolean; isin?: string; name?: string; scraperConfiguration?: ScraperConfiguration; diff --git a/libs/common/src/lib/interfaces/export.interface.ts b/libs/common/src/lib/interfaces/export.interface.ts index de3d7cf02..16a49b0ef 100644 --- a/libs/common/src/lib/interfaces/export.interface.ts +++ b/libs/common/src/lib/interfaces/export.interface.ts @@ -1,11 +1,19 @@ -import { Account, Order } from '@prisma/client'; +import { + Account, + DataSource, + Order, + Platform, + SymbolProfile, + Tag +} from '@prisma/client'; + +import { AccountBalance } from './account-balance.interface'; +import { MarketData } from './market-data.interface'; export interface Export { - meta: { - date: string; - version: string; - }; - accounts: Omit[]; + accounts: (Omit & { + balances: AccountBalance[]; + })[]; activities: (Omit< Order, | 'accountUserId' @@ -15,6 +23,18 @@ export interface Export { | 'symbolProfileId' | 'updatedAt' | 'userId' - > & { date: string; symbol: string })[]; + > & { dataSource: DataSource; date: string; symbol: string })[]; + assetProfiles: (Omit< + SymbolProfile, + 'createdAt' | 'id' | 'updatedAt' | 'userId' + > & { + marketData: MarketData[]; + })[]; + meta: { + date: string; + version: string; + }; + platforms: Platform[]; + tags: Omit[]; user: { settings: { currency: string } }; } diff --git a/libs/common/src/lib/interfaces/holding.interface.ts b/libs/common/src/lib/interfaces/holding.interface.ts index 5a0df62f6..e963bc5a7 100644 --- a/libs/common/src/lib/interfaces/holding.interface.ts +++ b/libs/common/src/lib/interfaces/holding.interface.ts @@ -1,5 +1,5 @@ export interface Holding { - allocationInPercentage?: number; + allocationInPercentage: number; name: string; valueInBaseCurrency: number; } diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index fa5eb25a5..52ca76b3a 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -1,5 +1,5 @@ import type { Access } from './access.interface'; -import type { Accounts } from './accounts.interface'; +import type { AccountBalance } from './account-balance.interface'; import type { AdminData } from './admin-data.interface'; import type { AdminJobs } from './admin-jobs.interface'; import type { AdminMarketDataDetails } from './admin-market-data-details.interface'; @@ -25,34 +25,42 @@ import type { InfoItem } from './info-item.interface'; import type { InvestmentItem } from './investment-item.interface'; import type { LineChartItem } from './line-chart-item.interface'; import type { LookupItem } from './lookup-item.interface'; +import type { MarketData } from './market-data.interface'; import type { PortfolioChart } from './portfolio-chart.interface'; import type { PortfolioDetails } from './portfolio-details.interface'; import type { PortfolioDividends } from './portfolio-dividends.interface'; import type { PortfolioInvestments } from './portfolio-investments.interface'; -import type { PortfolioItem } from './portfolio-item.interface'; -import type { PortfolioOverview } from './portfolio-overview.interface'; import type { PortfolioPerformance } from './portfolio-performance.interface'; import type { PortfolioPosition } from './portfolio-position.interface'; import type { PortfolioReportRule } from './portfolio-report-rule.interface'; import type { PortfolioSummary } from './portfolio-summary.interface'; import type { Position } from './position.interface'; import type { Product } from './product'; +import type { AccessTokenResponse } from './responses/access-token-response.interface'; import type { AccountBalancesResponse } from './responses/account-balances-response.interface'; +import type { AccountsResponse } from './responses/accounts-response.interface'; +import type { AiPromptResponse } from './responses/ai-prompt-response.interface'; import type { ApiKeyResponse } from './responses/api-key-response.interface'; import type { BenchmarkResponse } from './responses/benchmark-response.interface'; +import type { DataEnhancerHealthResponse } from './responses/data-enhancer-health-response.interface'; +import type { DataProviderGhostfolioAssetProfileResponse } from './responses/data-provider-ghostfolio-asset-profile-response.interface'; import type { DataProviderGhostfolioStatusResponse } from './responses/data-provider-ghostfolio-status-response.interface'; +import type { DataProviderHealthResponse } from './responses/data-provider-health-response.interface'; import type { DividendsResponse } from './responses/dividends-response.interface'; import type { ResponseError } from './responses/errors.interface'; import type { HistoricalResponse } from './responses/historical-response.interface'; import type { ImportResponse } from './responses/import-response.interface'; import type { LookupResponse } from './responses/lookup-response.interface'; import type { MarketDataDetailsResponse } from './responses/market-data-details-response.interface'; +import type { MarketDataOfMarketsResponse } from './responses/market-data-of-markets-response.interface'; import type { OAuthResponse } from './responses/oauth-response.interface'; +import { PortfolioHoldingResponse } from './responses/portfolio-holding-response.interface'; import type { PortfolioHoldingsResponse } from './responses/portfolio-holdings-response.interface'; import type { PortfolioPerformanceResponse } from './responses/portfolio-performance-response.interface'; import type { PortfolioReportResponse } from './responses/portfolio-report.interface'; import type { PublicPortfolioResponse } from './responses/public-portfolio-response.interface'; import type { QuotesResponse } from './responses/quotes-response.interface'; +import type { WatchlistResponse } from './responses/watchlist-response.interface'; import type { ScraperConfiguration } from './scraper-configuration.interface'; import type { Statistics } from './statistics.interface'; import type { SubscriptionOffer } from './subscription-offer.interface'; @@ -66,14 +74,17 @@ import type { XRayRulesSettings } from './x-ray-rules-settings.interface'; export { Access, + AccessTokenResponse, + AccountBalance, AccountBalancesResponse, - Accounts, + AccountsResponse, AdminData, AdminJobs, AdminMarketData, AdminMarketDataDetails, AdminMarketDataItem, AdminUsers, + AiPromptResponse, ApiKeyResponse, AssetProfileIdentifier, Benchmark, @@ -81,7 +92,10 @@ export { BenchmarkProperty, BenchmarkResponse, Coupon, + DataEnhancerHealthResponse, + DataProviderGhostfolioAssetProfileResponse, DataProviderGhostfolioStatusResponse, + DataProviderHealthResponse, DataProviderInfo, DividendsResponse, EnhancedSymbolProfile, @@ -98,15 +112,16 @@ export { LineChartItem, LookupItem, LookupResponse, + MarketData, MarketDataDetailsResponse, + MarketDataOfMarketsResponse, OAuthResponse, PortfolioChart, PortfolioDetails, PortfolioDividends, + PortfolioHoldingResponse, PortfolioHoldingsResponse, PortfolioInvestments, - PortfolioItem, - PortfolioOverview, PortfolioPerformance, PortfolioPerformanceResponse, PortfolioPosition, @@ -127,5 +142,6 @@ export { ToggleOption, User, UserSettings, + WatchlistResponse, XRayRulesSettings }; diff --git a/libs/common/src/lib/interfaces/info-item.interface.ts b/libs/common/src/lib/interfaces/info-item.interface.ts index bd3eb1f94..fe4101197 100644 --- a/libs/common/src/lib/interfaces/info-item.interface.ts +++ b/libs/common/src/lib/interfaces/info-item.interface.ts @@ -1,5 +1,3 @@ -import { SubscriptionOfferKey } from '@ghostfolio/common/types'; - import { Platform, SymbolProfile } from '@prisma/client'; import { Statistics } from './statistics.interface'; @@ -18,5 +16,5 @@ export interface InfoItem { platforms: Platform[]; statistics: Statistics; stripePublicKey?: string; - subscriptionOffers: { [offer in SubscriptionOfferKey]: SubscriptionOffer }; + subscriptionOffer?: SubscriptionOffer; } diff --git a/libs/common/src/lib/interfaces/market-data.interface.ts b/libs/common/src/lib/interfaces/market-data.interface.ts new file mode 100644 index 000000000..b7a410cba --- /dev/null +++ b/libs/common/src/lib/interfaces/market-data.interface.ts @@ -0,0 +1,4 @@ +export interface MarketData { + date: string; + marketPrice: number; +} diff --git a/libs/common/src/lib/interfaces/portfolio-details.interface.ts b/libs/common/src/lib/interfaces/portfolio-details.interface.ts index e455f73ca..746736f6b 100644 --- a/libs/common/src/lib/interfaces/portfolio-details.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-details.interface.ts @@ -14,6 +14,7 @@ export interface PortfolioDetails { valueInPercentage?: number; }; }; + createdAt: Date; holdings: { [symbol: string]: PortfolioPosition }; markets?: { [key in Market]: { diff --git a/libs/common/src/lib/interfaces/portfolio-item.interface.ts b/libs/common/src/lib/interfaces/portfolio-item.interface.ts deleted file mode 100644 index a3e42a05f..000000000 --- a/libs/common/src/lib/interfaces/portfolio-item.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Position } from '@ghostfolio/common/interfaces'; - -export interface PortfolioItem { - date: string; - grossPerformancePercent: number; - investment: number; - positions: { [symbol: string]: Position }; - value: number; -} diff --git a/libs/common/src/lib/interfaces/portfolio-overview.interface.ts b/libs/common/src/lib/interfaces/portfolio-overview.interface.ts deleted file mode 100644 index c9c20c28c..000000000 --- a/libs/common/src/lib/interfaces/portfolio-overview.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface PortfolioOverview { - cash: number; - committedFunds: number; - fees: number; - ordersCount: number; - totalBuy: number; - totalSell: number; -} diff --git a/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts b/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts index 0296606b8..4df7a8eac 100644 --- a/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts @@ -1,4 +1,5 @@ export interface PortfolioReportRule { + categoryName: string; configuration?: { threshold?: { max: number; diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index 5b27f4c7e..419915a79 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -1,6 +1,7 @@ import { PortfolioPerformance } from './portfolio-performance.interface'; export interface PortfolioSummary extends PortfolioPerformance { + activityCount: number; annualizedPerformancePercent: number; annualizedPerformancePercentWithCurrencyEffect: number; cash: number; @@ -16,13 +17,10 @@ export interface PortfolioSummary extends PortfolioPerformance { filteredValueInBaseCurrency?: number; filteredValueInPercentage?: number; fireWealth: number; - firstOrderDate: Date; grossPerformance: number; grossPerformanceWithCurrencyEffect: number; interest: number; - items: number; liabilities: number; - ordersCount: number; totalBuy: number; totalSell: number; totalValueInBaseCurrency?: number; diff --git a/libs/common/src/lib/interfaces/responses/access-token-response.interface.ts b/libs/common/src/lib/interfaces/responses/access-token-response.interface.ts new file mode 100644 index 000000000..7aebaae27 --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/access-token-response.interface.ts @@ -0,0 +1,3 @@ +export interface AccessTokenResponse { + accessToken: string; +} diff --git a/libs/common/src/lib/interfaces/accounts.interface.ts b/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts similarity index 84% rename from libs/common/src/lib/interfaces/accounts.interface.ts rename to libs/common/src/lib/interfaces/responses/accounts-response.interface.ts index 7100a6848..5e03ea34a 100644 --- a/libs/common/src/lib/interfaces/accounts.interface.ts +++ b/libs/common/src/lib/interfaces/responses/accounts-response.interface.ts @@ -1,6 +1,6 @@ import { AccountWithValue } from '@ghostfolio/common/types'; -export interface Accounts { +export interface AccountsResponse { accounts: AccountWithValue[]; totalBalanceInBaseCurrency: number; totalValueInBaseCurrency: number; diff --git a/libs/common/src/lib/interfaces/responses/ai-prompt-response.interface.ts b/libs/common/src/lib/interfaces/responses/ai-prompt-response.interface.ts new file mode 100644 index 000000000..4b95bc871 --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/ai-prompt-response.interface.ts @@ -0,0 +1,3 @@ +export interface AiPromptResponse { + prompt: string; +} diff --git a/libs/common/src/lib/interfaces/responses/data-enhancer-health-response.interface.ts b/libs/common/src/lib/interfaces/responses/data-enhancer-health-response.interface.ts new file mode 100644 index 000000000..025f8e8be --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/data-enhancer-health-response.interface.ts @@ -0,0 +1,3 @@ +export interface DataEnhancerHealthResponse { + status: string; +} diff --git a/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts b/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts new file mode 100644 index 000000000..7fd0314fb --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts @@ -0,0 +1,4 @@ +import { SymbolProfile } from '@prisma/client'; + +export interface DataProviderGhostfolioAssetProfileResponse + extends Partial {} diff --git a/libs/common/src/lib/interfaces/responses/data-provider-health-response.interface.ts b/libs/common/src/lib/interfaces/responses/data-provider-health-response.interface.ts new file mode 100644 index 000000000..a32d9b3c3 --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/data-provider-health-response.interface.ts @@ -0,0 +1,3 @@ +export interface DataProviderHealthResponse { + status: string; +} diff --git a/libs/common/src/lib/interfaces/responses/market-data-of-markets-response.interface.ts b/libs/common/src/lib/interfaces/responses/market-data-of-markets-response.interface.ts new file mode 100644 index 000000000..aecfbb28b --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/market-data-of-markets-response.interface.ts @@ -0,0 +1,8 @@ +import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; + +export interface MarketDataOfMarketsResponse { + fearAndGreedIndex: { + CRYPTOCURRENCIES: SymbolItem; + STOCKS: SymbolItem; + }; +} diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-holding-detail.interface.ts b/libs/common/src/lib/interfaces/responses/portfolio-holding-response.interface.ts similarity index 80% rename from apps/api/src/app/portfolio/interfaces/portfolio-holding-detail.interface.ts rename to libs/common/src/lib/interfaces/responses/portfolio-holding-response.interface.ts index 79e4d40dc..000460228 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-holding-detail.interface.ts +++ b/libs/common/src/lib/interfaces/responses/portfolio-holding-response.interface.ts @@ -1,5 +1,6 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { + Benchmark, DataProviderInfo, EnhancedSymbolProfile, HistoricalDataItem @@ -7,7 +8,8 @@ import { import { Tag } from '@prisma/client'; -export interface PortfolioHoldingDetail { +export interface PortfolioHoldingResponse { + activities: Activity[]; averagePrice: number; dataProviderInfo: DataProviderInfo; dividendInBaseCurrency: number; @@ -20,15 +22,15 @@ export interface PortfolioHoldingDetail { grossPerformancePercentWithCurrencyEffect: number; grossPerformanceWithCurrencyEffect: number; historicalData: HistoricalDataItem[]; - investment: number; + investmentInBaseCurrencyWithCurrencyEffect: number; marketPrice: number; - maxPrice: number; - minPrice: number; + marketPriceMax: number; + marketPriceMin: number; netPerformance: number; netPerformancePercent: number; netPerformancePercentWithCurrencyEffect: number; netPerformanceWithCurrencyEffect: number; - orders: Activity[]; + performances: Benchmark['performances']; quantity: number; SymbolProfile: EnhancedSymbolProfile; tags: Tag[]; diff --git a/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts b/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts index 35ff033eb..985a42311 100644 --- a/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts +++ b/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts @@ -1,9 +1,11 @@ import { PortfolioReportRule } from '../portfolio-report-rule.interface'; export interface PortfolioReportResponse { - rules: { [group: string]: PortfolioReportRule[] }; - statistics: { - rulesActiveCount: number; - rulesFulfilledCount: number; + xRay: { + rules: { [group: string]: PortfolioReportRule[] }; + statistics: { + rulesActiveCount: number; + rulesFulfilledCount: number; + }; }; } diff --git a/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts b/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts index dc6e57587..7a98e3c8d 100644 --- a/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts +++ b/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts @@ -32,6 +32,7 @@ export interface PublicPortfolioResponse extends PublicPortfolioResponseV1 { } interface PublicPortfolioResponseV1 { + createdAt: Date; performance: { '1d': { relativeChange: number; diff --git a/libs/common/src/lib/interfaces/responses/watchlist-response.interface.ts b/libs/common/src/lib/interfaces/responses/watchlist-response.interface.ts new file mode 100644 index 000000000..6994d73f7 --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/watchlist-response.interface.ts @@ -0,0 +1,12 @@ +import { + AssetProfileIdentifier, + Benchmark +} from '@ghostfolio/common/interfaces'; + +export interface WatchlistResponse { + watchlist: (AssetProfileIdentifier & { + marketCondition: Benchmark['marketCondition']; + name: string; + performances: Benchmark['performances']; + })[]; +} diff --git a/libs/common/src/lib/interfaces/subscription-offer.interface.ts b/libs/common/src/lib/interfaces/subscription-offer.interface.ts index 8db91da6e..a9ebb54f4 100644 --- a/libs/common/src/lib/interfaces/subscription-offer.interface.ts +++ b/libs/common/src/lib/interfaces/subscription-offer.interface.ts @@ -4,6 +4,8 @@ export interface SubscriptionOffer { coupon?: number; couponId?: string; durationExtension?: StringValue; + isRenewal?: boolean; + label?: string; price: number; priceId: string; } diff --git a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts index 24c1e1db4..c2b70a4bc 100644 --- a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts +++ b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts @@ -51,6 +51,4 @@ export interface SymbolMetrics { totalInvestmentWithCurrencyEffect: Big; totalLiabilities: Big; totalLiabilitiesInBaseCurrency: Big; - totalValuables: Big; - totalValuablesInBaseCurrency: Big; } diff --git a/libs/common/src/lib/interfaces/tab-configuration.interface.ts b/libs/common/src/lib/interfaces/tab-configuration.interface.ts index e475e3efc..7b18b26ec 100644 --- a/libs/common/src/lib/interfaces/tab-configuration.interface.ts +++ b/libs/common/src/lib/interfaces/tab-configuration.interface.ts @@ -1,6 +1,6 @@ export interface TabConfiguration { iconName: string; label: string; - path: string[]; + routerLink: string[]; showCondition?: boolean; } diff --git a/libs/common/src/lib/interfaces/user-settings.interface.ts b/libs/common/src/lib/interfaces/user-settings.interface.ts index d72be7c7c..942f6e616 100644 --- a/libs/common/src/lib/interfaces/user-settings.interface.ts +++ b/libs/common/src/lib/interfaces/user-settings.interface.ts @@ -5,6 +5,7 @@ import { HoldingsViewMode, ViewMode } from '@ghostfolio/common/types'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; export interface UserSettings { annualInterestRate?: number; @@ -22,6 +23,7 @@ export interface UserSettings { isRestrictedView?: boolean; language?: string; locale?: string; + performanceCalculationType?: PerformanceCalculationType; projectedTotalAmount?: number; retirementDate?: string; savingsRate?: number; diff --git a/libs/common/src/lib/interfaces/user.interface.ts b/libs/common/src/lib/interfaces/user.interface.ts index 667e59fd8..a48317fad 100644 --- a/libs/common/src/lib/interfaces/user.interface.ts +++ b/libs/common/src/lib/interfaces/user.interface.ts @@ -1,8 +1,8 @@ -import { SubscriptionOfferKey } from '@ghostfolio/common/types'; import { SubscriptionType } from '@ghostfolio/common/types/subscription-type.type'; import { Access, Account, Tag } from '@prisma/client'; +import { SubscriptionOffer } from './subscription-offer.interface'; import { SystemMessage } from './system-message.interface'; import { UserSettings } from './user-settings.interface'; @@ -10,6 +10,7 @@ import { UserSettings } from './user-settings.interface'; export interface User { access: Pick[]; accounts: Account[]; + activitiesCount: number; dateOfFirstActivity: Date; id: string; permissions: string[]; @@ -17,7 +18,7 @@ export interface User { systemMessage?: SystemMessage; subscription: { expiresAt?: Date; - offer: SubscriptionOfferKey; + offer: SubscriptionOffer; type: SubscriptionType; }; tags: (Tag & { isUsed: boolean })[]; diff --git a/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts b/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts index 858ffa31b..9ae32d802 100644 --- a/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts +++ b/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts @@ -9,6 +9,11 @@ export interface XRayRulesSettings { EconomicMarketClusterRiskEmergingMarkets?: RuleSettings; EmergencyFundSetup?: RuleSettings; FeeRatioInitialInvestment?: RuleSettings; + RegionalMarketClusterRiskAsiaPacific?: RuleSettings; + RegionalMarketClusterRiskEmergingMarkets?: RuleSettings; + RegionalMarketClusterRiskEurope?: RuleSettings; + RegionalMarketClusterRiskJapan?: RuleSettings; + RegionalMarketClusterRiskNorthAmerica?: RuleSettings; } interface RuleSettings { diff --git a/libs/common/src/lib/models/portfolio-snapshot.ts b/libs/common/src/lib/models/portfolio-snapshot.ts index 46bd5c18f..6b13ca048 100644 --- a/libs/common/src/lib/models/portfolio-snapshot.ts +++ b/libs/common/src/lib/models/portfolio-snapshot.ts @@ -9,6 +9,10 @@ import { Big } from 'big.js'; import { Transform, Type } from 'class-transformer'; export class PortfolioSnapshot { + activitiesCount: number; + + createdAt: Date; + @Transform(transformToBig, { toClassOnly: true }) @Type(() => Big) currentValueInBaseCurrency: Big; @@ -41,8 +45,4 @@ export class PortfolioSnapshot { @Transform(transformToBig, { toClassOnly: true }) @Type(() => Big) totalLiabilitiesWithCurrencyEffect: Big; - - @Transform(transformToBig, { toClassOnly: true }) - @Type(() => Big) - totalValuablesWithCurrencyEffect: Big; } diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index d6676ec4e..48ffc95aa 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -13,18 +13,21 @@ export const permissions = { createMarketData: 'createMarketData', createMarketDataOfOwnAssetProfile: 'createMarketDataOfOwnAssetProfile', createOrder: 'createOrder', + createOwnTag: 'createOwnTag', createPlatform: 'createPlatform', createTag: 'createTag', createUserAccount: 'createUserAccount', + createWatchlistItem: 'createWatchlistItem', deleteAccess: 'deleteAccess', - deleteAccount: 'deleteAcccount', - deleteAccountBalance: 'deleteAcccountBalance', + deleteAccount: 'deleteAccount', + deleteAccountBalance: 'deleteAccountBalance', deleteAuthDevice: 'deleteAuthDevice', deleteOrder: 'deleteOrder', deleteOwnUser: 'deleteOwnUser', deletePlatform: 'deletePlatform', deleteTag: 'deleteTag', deleteUser: 'deleteUser', + deleteWatchlistItem: 'deleteWatchlistItem', enableDataProviderGhostfolio: 'enableDataProviderGhostfolio', enableFearAndGreedIndex: 'enableFearAndGreedIndex', enableImport: 'enableImport', @@ -35,17 +38,22 @@ export const permissions = { enableSubscriptionInterstitial: 'enableSubscriptionInterstitial', enableSystemMessage: 'enableSystemMessage', impersonateAllUsers: 'impersonateAllUsers', + readAiPrompt: 'readAiPrompt', readMarketData: 'readMarketData', + readMarketDataOfMarkets: 'readMarketDataOfMarkets', readMarketDataOfOwnAssetProfile: 'readMarketDataOfOwnAssetProfile', readPlatforms: 'readPlatforms', readTags: 'readTags', + readWatchlist: 'readWatchlist', reportDataGlitch: 'reportDataGlitch', + syncDemoUserAccount: 'syncDemoUserAccount', toggleReadOnlyMode: 'toggleReadOnlyMode', updateAccount: 'updateAccount', updateAuthDevice: 'updateAuthDevice', updateMarketData: 'updateMarketData', updateMarketDataOfOwnAssetProfile: 'updateMarketDataOfOwnAssetProfile', updateOrder: 'updateOrder', + updateOwnAccessToken: 'updateOwnAccessToken', updatePlatform: 'updatePlatform', updateTag: 'updateTag', updateUserSettings: 'updateUserSettings', @@ -62,24 +70,28 @@ export function getPermissions(aRole: Role): string[] { permissions.createAccess, permissions.createAccount, permissions.createAccountBalance, + permissions.createWatchlistItem, permissions.deleteAccountBalance, + permissions.deleteWatchlistItem, permissions.createMarketData, permissions.createMarketDataOfOwnAssetProfile, permissions.createOrder, + permissions.createOwnTag, permissions.createPlatform, permissions.createTag, permissions.deleteAccess, permissions.deleteAccount, permissions.deleteAuthDevice, permissions.deleteOrder, - permissions.deleteOwnUser, permissions.deletePlatform, permissions.deleteTag, permissions.deleteUser, + permissions.readAiPrompt, permissions.readMarketData, permissions.readMarketDataOfOwnAssetProfile, permissions.readPlatforms, permissions.readTags, + permissions.readWatchlist, permissions.updateAccount, permissions.updateAuthDevice, permissions.updateMarketData, @@ -95,7 +107,9 @@ export function getPermissions(aRole: Role): string[] { return [ permissions.accessAssistant, permissions.accessHoldingsChart, - permissions.createUserAccount + permissions.createUserAccount, + permissions.readAiPrompt, + permissions.readWatchlist ]; case 'USER': @@ -107,13 +121,17 @@ export function getPermissions(aRole: Role): string[] { permissions.createAccountBalance, permissions.createMarketDataOfOwnAssetProfile, permissions.createOrder, + permissions.createOwnTag, + permissions.createWatchlistItem, permissions.deleteAccess, permissions.deleteAccount, permissions.deleteAccountBalance, permissions.deleteAuthDevice, permissions.deleteOrder, - permissions.deleteOwnUser, + permissions.deleteWatchlistItem, + permissions.readAiPrompt, permissions.readMarketDataOfOwnAssetProfile, + permissions.readWatchlist, permissions.updateAccount, permissions.updateAuthDevice, permissions.updateMarketDataOfOwnAssetProfile, @@ -167,7 +185,7 @@ export function hasReadRestrictedAccessPermission({ return false; } - const access = user.Access?.find(({ id }) => { + const access = user.accessesGet?.find(({ id }) => { return id === impersonationId; }); @@ -179,5 +197,5 @@ export function hasRole(aUser: UserWithSettings, aRole: Role) { } export function isRestrictedView(aUser: UserWithSettings) { - return aUser.Settings.settings.isRestrictedView ?? false; + return aUser.settings.settings.isRestrictedView ?? false; } diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index 63d5805cd..51d847300 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -44,6 +44,25 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$120', slogan: 'Analyze and track your portfolio.' }, + { + founded: 2022, + hasFreePlan: false, + key: 'asseta', + languages: ['English'], + name: 'Asseta', + origin: 'United States', + slogan: 'The Intelligent Family Office Suite' + }, + { + founded: 2020, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'balance-pro', + name: 'Balance Pro', + origin: 'United States', + pricingPerYear: '$47.99', + slogan: 'The Smarter Way to Track Your Finances' + }, { hasFreePlan: false, hasSelfHostingAbility: true, @@ -82,28 +101,6 @@ export const personalFinanceTools: Product[] = [ regions: ['Global'], slogan: 'Take control of your financial future' }, - { - founded: 2013, - hasFreePlan: true, - hasSelfHostingAbility: false, - key: 'cointracking', - languages: ['Deutsch', 'English'], - name: 'CoinTracking', - origin: 'Germany', - pricingPerYear: '$120', - slogan: 'The leading Crypto Portfolio Tracker & Tax Calculator' - }, - { - founded: 2022, - hasFreePlan: true, - hasSelfHostingAbility: false, - key: 'degiro-portfolio-tracker-by-capitalyse', - languages: ['English'], - name: 'DEGIRO Portfolio Tracker by Capitalyse', - origin: 'Netherlands', - pricingPerYear: '€24', - slogan: 'Democratizing Data Analytics' - }, { hasFreePlan: true, hasSelfHostingAbility: false, @@ -122,6 +119,36 @@ export const personalFinanceTools: Product[] = [ note: 'CapMon.org was discontinued in 2023', slogan: 'Next Generation Assets Tracking' }, + { + founded: 2024, + hasFreePlan: true, + isOpenSource: true, + key: 'cleverbilling', + languages: ['Español'], + name: 'CleverBilling', + slogan: 'Toma el control total de tus finanzas.' + }, + { + founded: 2017, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'coinstats', + name: 'CoinStats', + origin: 'Armenia', + pricingPerYear: '$168', + slogan: 'Manage All Your Wallets & Exchanges From One Place' + }, + { + founded: 2013, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'cointracking', + languages: ['Deutsch', 'English'], + name: 'CoinTracking', + origin: 'Germany', + pricingPerYear: '$120', + slogan: 'The leading Crypto Portfolio Tracker & Tax Calculator' + }, { founded: 2019, key: 'compound-planning', @@ -139,6 +166,14 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$70', slogan: 'Do money better with Copilot' }, + { + founded: 2023, + hasFreePlan: false, + key: 'danti', + name: 'Danti', + origin: 'United Kingdom', + slogan: 'Digitising Generational Wealth' + }, { founded: 2020, key: 'de.fi', @@ -146,6 +181,28 @@ export const personalFinanceTools: Product[] = [ name: 'De.Fi', slogan: 'DeFi Portfolio Tracker' }, + { + founded: 2016, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'defi-portfolio-tracker-by-zerion', + languages: ['English'], + name: 'DeFi Portfolio Tracker by Zerion', + origin: 'United States', + pricingPerYear: '$99', + slogan: 'DeFi Portfolio Tracker for All Chains' + }, + { + founded: 2022, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'degiro-portfolio-tracker-by-capitalyse', + languages: ['English'], + name: 'DEGIRO Portfolio Tracker by Capitalyse', + origin: 'Netherlands', + pricingPerYear: '€24', + slogan: 'Democratizing Data Analytics' + }, { founded: 2017, hasFreePlan: true, @@ -154,8 +211,18 @@ export const personalFinanceTools: Product[] = [ name: 'Delta Investment Tracker', note: 'Acquired by eToro', origin: 'Belgium', + pricingPerYear: '$150', slogan: 'The app to track all your investments. Make smart moves only.' }, + { + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'digrin', + languages: ['English'], + name: 'Digrin', + pricingPerYear: '$49.90', + slogan: 'Dividend Portfolio Tracker' + }, { founded: 2019, hasFreePlan: true, @@ -202,6 +269,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$100', slogan: 'All your wealth, in one place.' }, + { + founded: 2018, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'fey', + name: 'Fey', + origin: 'Canada', + pricingPerYear: '$300', + slogan: 'Make better investments.' + }, { founded: 2023, hasFreePlan: true, @@ -242,6 +319,21 @@ export const personalFinanceTools: Product[] = [ slogan: 'The most convenient mobile application for personal finance accounting' }, + { + founded: 2022, + key: 'fincake', + name: 'Fincake', + origin: 'British Virgin Islands', + slogan: 'Easy-to-use Portfolio Tracker' + }, + { + founded: 2021, + hasSelfHostingAbility: false, + key: 'finvest', + name: 'Finvest', + origin: 'United States', + slogan: 'Grow your wealth in a stress-free way' + }, { founded: 2023, hasFreePlan: true, @@ -286,8 +378,10 @@ export const personalFinanceTools: Product[] = [ { hasFreePlan: true, hasSelfHostingAbility: false, + isArchived: true, key: 'gospatz', name: 'goSPATZ', + note: 'Renamed to Money Peak', origin: 'Germany', slogan: 'Volle Kontrolle über deine Investitionen' }, @@ -330,6 +424,15 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '€119', slogan: 'ETF portfolios made simple' }, + { + founded: 2018, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'koinly', + name: 'Koinly', + origin: 'Singapore', + slogan: 'Track all your crypto wallets in one place' + }, { founded: 2016, hasFreePlan: true, @@ -390,12 +493,11 @@ export const personalFinanceTools: Product[] = [ }, { founded: 2021, - hasSelfHostingAbility: false, isArchived: true, key: 'maybe-finance', languages: ['English'], name: 'Maybe Finance', - note: 'Maybe Finance was discontinued in 2023', + note: 'Maybe Finance was discontinued in 2023, relaunched in 2024, and discontinued again in 2025', origin: 'United States', pricingPerYear: '$145', regions: ['United States'], @@ -441,6 +543,15 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$100', slogan: 'Personal Finance Manager for Mac, Windows, and Linux' }, + { + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'moneypeak', + name: 'Money Peak', + note: 'Originally named as goSPATZ', + origin: 'Germany', + slogan: 'Dein smarter Finance Assistant' + }, { hasFreePlan: false, hasSelfHostingAbility: false, @@ -449,6 +560,17 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$60', slogan: 'Gain financial control and keep your data private.' }, + { + founded: 2025, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'monsy', + languages: ['English'], + name: 'Monsy', + origin: 'Indonesia', + pricingPerYear: '$20', + slogan: 'Smart, simple, stress-free money tracking.' + }, { hasFreePlan: true, hasSelfHostingAbility: false, @@ -459,6 +581,16 @@ export const personalFinanceTools: Product[] = [ slogan: 'Track your equity, fund, investment trust, ETF and pension investments in one place.' }, + { + founded: 2020, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'nansen', + name: 'Crypto Portfolio Tracker by Nansen', + origin: 'Singapore', + pricingPerYear: '$1188', + slogan: 'Your Complete Crypto Portfolio, Reimagined' + }, { founded: 2017, hasFreePlan: false, @@ -481,6 +613,23 @@ export const personalFinanceTools: Product[] = [ regions: ['Austria', 'Germany', 'Switzerland'], slogan: 'Dein Vermögen immer im Blick' }, + { + hasSelfHostingAbility: false, + key: 'peek', + name: 'Peek', + origin: 'Singapore', + slogan: 'Feel in control of your money without spreadsheets or shame' + }, + { + founded: 2022, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'pinklion', + name: 'PinkLion', + origin: 'Germany', + pricingPerYear: '€50', + slogan: 'Invest smarter, not harder' + }, { founded: 2023, hasFreePlan: true, @@ -624,6 +773,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '€80', slogan: 'Stock Portfolio Tracker' }, + { + founded: 2014, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'simply-wallstreet', + name: 'Stock Portfolio Tracker & Visualizer by Simply Wall St', + origin: 'Australia', + pricingPerYear: '$120', + slogan: 'Smart portfolio tracker for informed investors' + }, { founded: 2021, hasFreePlan: true, @@ -696,6 +855,28 @@ export const personalFinanceTools: Product[] = [ slogan: 'Your financial life in a spreadsheet, automatically updated each day' }, + { + founded: 2011, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'tradervue', + name: 'Tradervue', + origin: 'United States', + pricingPerYear: '$360', + slogan: 'The Trading Journal to Improve Your Trading Performance' + }, + { + founded: 2020, + hasSelfHostingAbility: false, + hasFreePlan: true, + isArchived: true, + key: 'tresor-one', + name: 'Tresor One', + note: 'Renamed to Parqet', + origin: 'Germany', + regions: ['Austria', 'Germany', 'Switzerland'], + slogan: 'Dein Vermögen immer im Blick' + }, { hasFreePlan: true, hasSelfHostingAbility: false, @@ -716,6 +897,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$348', slogan: 'Virtual Family Office for Smart Wealth Management' }, + { + founded: 2020, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'walletguide', + name: 'Walletguide', + origin: 'Germany', + pricingPerYear: '€90', + slogan: 'Personal finance reimagined with AI' + }, { hasSelfHostingAbility: false, key: 'wallmine', diff --git a/libs/common/src/lib/routes/interfaces/internal-route.interface.ts b/libs/common/src/lib/routes/interfaces/internal-route.interface.ts new file mode 100644 index 000000000..02f205979 --- /dev/null +++ b/libs/common/src/lib/routes/interfaces/internal-route.interface.ts @@ -0,0 +1,9 @@ +import { User } from '@ghostfolio/common/interfaces'; + +export interface InternalRoute { + excludeFromAssistant?: boolean | ((aUser: User) => boolean); + path: string; + routerLink: string[]; + subRoutes?: Record; + title: string; +} diff --git a/libs/common/src/lib/routes/interfaces/public-route.interface.ts b/libs/common/src/lib/routes/interfaces/public-route.interface.ts new file mode 100644 index 000000000..ad133200d --- /dev/null +++ b/libs/common/src/lib/routes/interfaces/public-route.interface.ts @@ -0,0 +1,7 @@ +export interface PublicRoute { + excludeFromSitemap?: boolean; + path: string; + routerLink: string[]; + subRoutes?: Record; + title?: string; +} diff --git a/libs/common/src/lib/routes/routes.ts b/libs/common/src/lib/routes/routes.ts new file mode 100644 index 000000000..9a75f0bc6 --- /dev/null +++ b/libs/common/src/lib/routes/routes.ts @@ -0,0 +1,339 @@ +import { User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; + +import { InternalRoute } from './interfaces/internal-route.interface'; +import { PublicRoute } from './interfaces/public-route.interface'; + +if (typeof window !== 'undefined') { + import('@angular/localize/init'); +} else { + (global as any).$localize = ( + messageParts: TemplateStringsArray, + ...expressions: any[] + ) => { + return String.raw({ raw: messageParts }, ...expressions); + }; +} + +export const internalRoutes: Record = { + account: { + path: 'account', + routerLink: ['/account'], + subRoutes: { + access: { + path: 'access', + routerLink: ['/account', 'access'], + title: $localize`Access` + }, + membership: { + path: 'membership', + routerLink: ['/account', 'membership'], + title: $localize`Membership` + } + }, + title: $localize`Settings` + }, + adminControl: { + excludeFromAssistant: (aUser: User) => { + return hasPermission(aUser?.permissions, permissions.accessAdminControl); + }, + path: 'admin', + routerLink: ['/admin'], + subRoutes: { + jobs: { + path: 'jobs', + routerLink: ['/admin', 'jobs'], + title: $localize`Job Queue` + }, + marketData: { + path: 'market-data', + routerLink: ['/admin', 'market-data'], + title: $localize`Market Data` + }, + settings: { + path: 'settings', + routerLink: ['/admin', 'settings'], + title: $localize`Settings` + }, + users: { + path: 'users', + routerLink: ['/admin', 'users'], + title: $localize`Users` + } + }, + title: $localize`Admin Control` + }, + accounts: { + path: 'accounts', + routerLink: ['/accounts'], + title: $localize`Accounts` + }, + api: { + excludeFromAssistant: true, + path: 'api', + routerLink: ['/api'], + title: 'Ghostfolio API' + }, + auth: { + excludeFromAssistant: true, + path: 'auth', + routerLink: ['/auth'], + title: $localize`Sign in` + }, + home: { + path: 'home', + routerLink: ['/home'], + subRoutes: { + holdings: { + path: 'holdings', + routerLink: ['/home', 'holdings'], + title: $localize`Holdings` + }, + markets: { + path: 'markets', + routerLink: ['/home', 'markets'], + title: $localize`Markets` + }, + marketsPremium: { + path: 'markets-premium', + routerLink: ['/home', 'markets-premium'], + title: $localize`Markets` + }, + summary: { + path: 'summary', + routerLink: ['/home', 'summary'], + title: $localize`Summary` + }, + watchlist: { + path: 'watchlist', + routerLink: ['/home', 'watchlist'], + title: $localize`Watchlist` + } + }, + title: $localize`Overview` + }, + i18n: { + excludeFromAssistant: true, + path: 'i18n', + routerLink: ['/i18n'], + title: $localize`Internationalization` + }, + portfolio: { + path: 'portfolio', + routerLink: ['/portfolio'], + subRoutes: { + activities: { + path: 'activities', + routerLink: ['/portfolio', 'activities'], + title: $localize`Activities` + }, + allocations: { + path: 'allocations', + routerLink: ['/portfolio', 'allocations'], + title: $localize`Allocations` + }, + analysis: { + path: undefined, // Default sub route + routerLink: ['/portfolio'], + title: $localize`Analysis` + }, + fire: { + path: 'fire', + routerLink: ['/portfolio', 'fire'], + title: 'FIRE' + }, + xRay: { + path: 'x-ray', + routerLink: ['/portfolio', 'x-ray'], + title: 'X-ray' + } + }, + title: $localize`Portfolio` + }, + webauthn: { + excludeFromAssistant: true, + path: 'webauthn', + routerLink: ['/webauthn'], + title: $localize`Sign in` + }, + zen: { + excludeFromAssistant: true, + path: 'zen', + routerLink: ['/zen'], + subRoutes: { + holdings: { + path: 'holdings', + routerLink: ['/zen', 'holdings'], + title: $localize`Holdings` + } + }, + title: $localize`Overview` + } +}; + +export const publicRoutes: Record = { + about: { + path: $localize`:kebab-case@@routes.about:about`, + routerLink: ['/' + $localize`:kebab-case@@routes.about:about`], + subRoutes: { + changelog: { + path: $localize`:kebab-case@@routes.about.changelog:changelog`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.about:about`, + $localize`:kebab-case@@routes.about.changelog:changelog` + ], + title: $localize`Changelog` + }, + license: { + path: $localize`:kebab-case@@routes.about.license:license`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.about:about`, + $localize`:kebab-case@@routes.about.license:license` + ], + title: $localize`License` + }, + ossFriends: { + path: 'oss-friends', + routerLink: [ + '/' + $localize`:kebab-case@@routes.about:about`, + 'oss-friends' + ], + title: 'OSS Friends' + }, + privacyPolicy: { + path: $localize`:kebab-case@@routes.about.privacyPolicy:privacy-policy`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.about:about`, + $localize`:kebab-case@@routes.about.privacyPolicy:privacy-policy` + ], + title: $localize`Privacy Policy` + }, + termsOfService: { + path: $localize`:kebab-case@@routes.about.termsOfService:terms-of-service`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.about:about`, + $localize`:kebab-case@@routes.about.termsOfService:terms-of-service` + ], + title: $localize`Terms of Service` + } + }, + title: $localize`About` + }, + blog: { + path: 'blog', + routerLink: ['/blog'], + title: $localize`Blog` + }, + demo: { + excludeFromSitemap: true, + path: 'demo', + routerLink: ['/demo'], + title: $localize`Live Demo` + }, + faq: { + path: $localize`:kebab-case@@routes.faq:faq`, + routerLink: ['/' + $localize`:kebab-case@@routes.faq:faq`], + subRoutes: { + saas: { + path: 'saas', + routerLink: ['/' + $localize`:kebab-case@@routes.faq:faq`, 'saas'], + title: $localize`Cloud` + ' (SaaS)' + }, + selfHosting: { + path: $localize`:kebab-case@@routes.faq.selfHosting:self-hosting`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.faq:faq`, + $localize`:kebab-case@@routes.faq.selfHosting:self-hosting` + ], + title: $localize`Self-Hosting` + } + }, + title: $localize`Frequently Asked Questions (FAQ)` + }, + features: { + path: $localize`:kebab-case@@routes.features:features`, + routerLink: ['/' + $localize`:kebab-case@@routes.features:features`], + title: $localize`Features` + }, + markets: { + path: $localize`:kebab-case@@routes.markets:markets`, + routerLink: ['/' + $localize`:kebab-case@@routes.markets:markets`], + title: $localize`Markets` + }, + openStartup: { + path: 'open', + routerLink: ['/open'], + title: 'Open Startup' + }, + pricing: { + path: $localize`:kebab-case@@routes.pricing:pricing`, + routerLink: ['/' + $localize`:kebab-case@@routes.pricing:pricing`], + title: $localize`Pricing` + }, + public: { + excludeFromSitemap: true, + path: 'p', + routerLink: ['/p'] + }, + register: { + path: $localize`:kebab-case@@routes.register:register`, + routerLink: ['/' + $localize`:kebab-case@@routes.register:register`], + title: $localize`Registration` + }, + resources: { + path: $localize`:kebab-case@@routes.resources:resources`, + routerLink: ['/' + $localize`:kebab-case@@routes.resources:resources`], + subRoutes: { + glossary: { + path: $localize`:kebab-case@@routes.resources.glossary:glossary`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.resources:resources`, + $localize`:kebab-case@@routes.resources.glossary:glossary` + ], + title: $localize`Glossary` + }, + guides: { + path: $localize`:kebab-case@@routes.resources.guides:guides`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.resources:resources`, + $localize`:kebab-case@@routes.resources.guides:guides` + ], + title: $localize`Guides` + }, + markets: { + path: $localize`:kebab-case@@routes.resources.markets:markets`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.resources:resources`, + $localize`:kebab-case@@routes.resources.markets:markets` + ], + title: $localize`Markets` + }, + personalFinanceTools: { + path: $localize`:kebab-case@@routes.resources.personalFinanceTools:personal-finance-tools`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.resources:resources`, + $localize`:kebab-case@@routes.resources.personalFinanceTools:personal-finance-tools` + ], + subRoutes: { + product: { + excludeFromSitemap: true, + path: $localize`:kebab-case@@routes.resources.personalFinanceTools.openSourceAlternativeTo:open-source-alternative-to`, + routerLink: [ + '/' + $localize`:kebab-case@@routes.resources:resources`, + $localize`:kebab-case@@routes.resources.personalFinanceTools:personal-finance-tools`, + $localize`:kebab-case@@routes.resources.personalFinanceTools.openSourceAlternativeTo:open-source-alternative-to` + ], + title: $localize`Open Source Alternative to` + } + }, + title: $localize`Personal Finance Tools` + } + }, + title: $localize`Resources` + }, + start: { + excludeFromSitemap: true, + path: $localize`:kebab-case@@routes.start:start`, + routerLink: ['/' + $localize`:kebab-case@@routes.start:start`] + } +}; diff --git a/libs/common/src/lib/types/access-with-grantee-user.type.ts b/libs/common/src/lib/types/access-with-grantee-user.type.ts index 18c045fc7..98551e0fd 100644 --- a/libs/common/src/lib/types/access-with-grantee-user.type.ts +++ b/libs/common/src/lib/types/access-with-grantee-user.type.ts @@ -1,3 +1,3 @@ import { Access, User } from '@prisma/client'; -export type AccessWithGranteeUser = Access & { GranteeUser?: User }; +export type AccessWithGranteeUser = Access & { granteeUser?: User }; diff --git a/libs/common/src/lib/types/account-with-platform.type.ts b/libs/common/src/lib/types/account-with-platform.type.ts index b0730abce..fbaa47393 100644 --- a/libs/common/src/lib/types/account-with-platform.type.ts +++ b/libs/common/src/lib/types/account-with-platform.type.ts @@ -1,3 +1,3 @@ import { Account, Platform } from '@prisma/client'; -export type AccountWithPlatform = Account & { Platform?: Platform }; +export type AccountWithPlatform = Account & { platform?: Platform }; diff --git a/libs/common/src/lib/types/account-with-value.type.ts b/libs/common/src/lib/types/account-with-value.type.ts index bc7577d91..d86a7ca1f 100644 --- a/libs/common/src/lib/types/account-with-value.type.ts +++ b/libs/common/src/lib/types/account-with-value.type.ts @@ -1,8 +1,9 @@ import { Account as AccountModel, Platform } from '@prisma/client'; export type AccountWithValue = AccountModel & { + allocationInPercentage: number; balanceInBaseCurrency: number; - Platform?: Platform; + platform?: Platform; transactionCount: number; value: number; valueInBaseCurrency: number; diff --git a/libs/common/src/lib/types/ai-prompt-mode.type.ts b/libs/common/src/lib/types/ai-prompt-mode.type.ts new file mode 100644 index 000000000..00a031df0 --- /dev/null +++ b/libs/common/src/lib/types/ai-prompt-mode.type.ts @@ -0,0 +1 @@ +export type AiPromptMode = 'analysis' | 'portfolio'; diff --git a/libs/common/src/lib/types/fear-and-greed-index.type.ts b/libs/common/src/lib/types/fear-and-greed-index.type.ts new file mode 100644 index 000000000..0dc6655a8 --- /dev/null +++ b/libs/common/src/lib/types/fear-and-greed-index.type.ts @@ -0,0 +1 @@ +export type FearAndGreedIndexMode = 'CRYPTOCURRENCIES' | 'STOCKS'; diff --git a/libs/common/src/lib/types/index.ts b/libs/common/src/lib/types/index.ts index 9e8178d3c..903d9c96a 100644 --- a/libs/common/src/lib/types/index.ts +++ b/libs/common/src/lib/types/index.ts @@ -2,9 +2,11 @@ import type { AccessType } from './access-type.type'; import type { AccessWithGranteeUser } from './access-with-grantee-user.type'; import type { AccountWithPlatform } from './account-with-platform.type'; import type { AccountWithValue } from './account-with-value.type'; +import type { AiPromptMode } from './ai-prompt-mode.type'; import type { BenchmarkTrend } from './benchmark-trend.type'; import type { ColorScheme } from './color-scheme.type'; import type { DateRange } from './date-range.type'; +import type { FearAndGreedIndexMode } from './fear-and-greed-index.type'; import type { Granularity } from './granularity.type'; import type { GroupBy } from './group-by.type'; import type { HoldingType } from './holding-type.type'; @@ -16,6 +18,7 @@ import type { Market } from './market.type'; import type { OrderWithAccount } from './order-with-account.type'; import type { RequestWithUser } from './request-with-user.type'; import type { SubscriptionOfferKey } from './subscription-offer-key.type'; +import type { SubscriptionType } from './subscription-type.type'; import type { UserWithSettings } from './user-with-settings.type'; import type { ViewMode } from './view-mode.type'; @@ -24,9 +27,11 @@ export type { AccessWithGranteeUser, AccountWithPlatform, AccountWithValue, + AiPromptMode, BenchmarkTrend, ColorScheme, DateRange, + FearAndGreedIndexMode, Granularity, GroupBy, HoldingType, @@ -38,6 +43,7 @@ export type { OrderWithAccount, RequestWithUser, SubscriptionOfferKey, + SubscriptionType, UserWithSettings, ViewMode }; diff --git a/libs/common/src/lib/types/order-with-account.type.ts b/libs/common/src/lib/types/order-with-account.type.ts index af8803091..b3ae4a990 100644 --- a/libs/common/src/lib/types/order-with-account.type.ts +++ b/libs/common/src/lib/types/order-with-account.type.ts @@ -3,7 +3,7 @@ import { Order, SymbolProfile, Tag } from '@prisma/client'; import { AccountWithPlatform } from './account-with-platform.type'; export type OrderWithAccount = Order & { - Account?: AccountWithPlatform; + account?: AccountWithPlatform; SymbolProfile?: SymbolProfile; tags?: Tag[]; }; diff --git a/libs/common/src/lib/types/performance-calculation-type.type.ts b/libs/common/src/lib/types/performance-calculation-type.type.ts new file mode 100644 index 000000000..a970636b6 --- /dev/null +++ b/libs/common/src/lib/types/performance-calculation-type.type.ts @@ -0,0 +1,6 @@ +export enum PerformanceCalculationType { + MWR = 'MWR', // Money-Weighted Rate of Return + ROAI = 'ROAI', // Return on Average Investment + ROI = 'ROI', // Return on Investment + TWR = 'TWR' // Time-Weighted Rate of Return +} diff --git a/libs/common/src/lib/types/user-with-settings.type.ts b/libs/common/src/lib/types/user-with-settings.type.ts index 5f9835176..18fc90a5c 100644 --- a/libs/common/src/lib/types/user-with-settings.type.ts +++ b/libs/common/src/lib/types/user-with-settings.type.ts @@ -1,20 +1,19 @@ -import { UserSettings } from '@ghostfolio/common/interfaces'; -import { SubscriptionOfferKey } from '@ghostfolio/common/types'; -import { SubscriptionType } from '@ghostfolio/common/types/subscription-type.type'; +import { SubscriptionOffer, UserSettings } from '@ghostfolio/common/interfaces'; +import { SubscriptionType } from '@ghostfolio/common/types'; import { Access, Account, Settings, User } from '@prisma/client'; // TODO: Compare with User interface export type UserWithSettings = User & { - Access: Access[]; - Account: Account[]; + accessesGet: Access[]; + accounts: Account[]; activityCount: number; dataProviderGhostfolioDailyRequests: number; permissions?: string[]; - Settings: Settings & { settings: UserSettings }; + settings: Settings & { settings: UserSettings }; subscription?: { expiresAt?: Date; - offer: SubscriptionOfferKey; + offer: SubscriptionOffer; type: SubscriptionType; }; }; diff --git a/libs/ui/.eslintrc.json b/libs/ui/.eslintrc.json deleted file mode 100644 index edc969121..000000000 --- a/libs/ui/.eslintrc.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*", "**/*.stories.ts"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "parserOptions": { - "project": ["libs/ui/tsconfig.*?.json"] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "gf", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "gf", - "style": "kebab-case" - } - ], - "@angular-eslint/prefer-standalone": "off" - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] -} diff --git a/libs/ui/.storybook/main.js b/libs/ui/.storybook/main.js index 8c8323a0c..e7d1378c7 100644 --- a/libs/ui/.storybook/main.js +++ b/libs/ui/.storybook/main.js @@ -1,9 +1,21 @@ +import { createRequire } from 'node:module'; +import { dirname, join } from 'node:path'; + +const require = createRequire(import.meta.url); + +/** @type {import('@storybook/angular').StorybookConfig} */ const config = { - addons: ['@storybook/addon-essentials'], + addons: [getAbsolutePath('@storybook/addon-docs')], framework: { - name: '@storybook/angular', + name: getAbsolutePath('@storybook/angular'), options: {} }, + staticDirs: [ + { + from: '../../../apps/client/src/assets', + to: '/assets' + } + ], stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'] }; @@ -12,3 +24,7 @@ export default config; // To customize your webpack configuration you can use the webpackFinal field. // Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config // and https://nx.dev/packages/storybook/documents/custom-builder-configs + +function getAbsolutePath(value) { + return dirname(require.resolve(join(value, 'package.json'))); +} diff --git a/libs/ui/.storybook/preview-head.html b/libs/ui/.storybook/preview-head.html deleted file mode 100644 index aa97d5363..000000000 --- a/libs/ui/.storybook/preview-head.html +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/libs/ui/.storybook/preview.js b/libs/ui/.storybook/preview.js index 37eb3a59d..e69de29bb 100644 --- a/libs/ui/.storybook/preview.js +++ b/libs/ui/.storybook/preview.js @@ -1 +0,0 @@ -// import '!style-loader!css-loader!sass-loader!../../../apps/client/src/styles.scss'; diff --git a/libs/ui/eslint.config.cjs b/libs/ui/eslint.config.cjs new file mode 100644 index 000000000..e21452b5f --- /dev/null +++ b/libs/ui/eslint.config.cjs @@ -0,0 +1,66 @@ +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); +const baseConfig = require('../../eslint.config.cjs'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended +}); + +module.exports = [ + { + ignores: ['**/dist'] + }, + ...baseConfig, + ...compat + .config({ + extends: [ + 'plugin:@nx/angular', + 'plugin:@angular-eslint/template/process-inline-templates' + ] + }) + .map((config) => ({ + ...config, + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + rules: { + ...config.rules, + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'gf', + style: 'camelCase' + } + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'gf', + style: 'kebab-case' + } + ], + '@angular-eslint/prefer-inject': 'off', + '@angular-eslint/prefer-standalone': 'off' + }, + languageOptions: { + parserOptions: { + project: ['libs/ui/tsconfig.*?.json'] + } + } + })), + ...compat + .config({ + extends: ['plugin:@nx/angular-template'] + }) + .map((config) => ({ + ...config, + files: ['**/*.html'], + rules: { + ...config.rules + } + })), + { + ignores: ['**/*.stories.ts'] + } +]; diff --git a/libs/ui/project.json b/libs/ui/project.json index 58e959344..b5c6473dd 100644 --- a/libs/ui/project.json +++ b/libs/ui/project.json @@ -26,10 +26,15 @@ "storybook": { "executor": "@storybook/angular:start-storybook", "options": { - "port": 4400, - "configDir": "libs/ui/.storybook", "browserTarget": "ui:build-storybook", - "compodoc": false + "compodoc": false, + "configDir": "libs/ui/.storybook", + "port": 4400, + "styles": [ + "apps/client/src/assets/fonts/inter.css", + "apps/client/src/styles/theme.scss", + "apps/client/src/styles.scss" + ] }, "configurations": { "ci": { @@ -41,10 +46,15 @@ "executor": "@storybook/angular:build-storybook", "outputs": ["{options.outputDir}"], "options": { - "outputDir": "dist/storybook/ui", - "configDir": "libs/ui/.storybook", "browserTarget": "ui:build-storybook", - "compodoc": false + "compodoc": false, + "configDir": "libs/ui/.storybook", + "outputDir": "dist/apps/client/development/storybook", + "styles": [ + "apps/client/src/assets/fonts/inter.css", + "apps/client/src/styles/theme.scss", + "apps/client/src/styles.scss" + ] }, "configurations": { "ci": { @@ -56,7 +66,7 @@ "executor": "@nx/web:file-server", "options": { "buildTarget": "ui:build-storybook", - "staticFilePath": "dist/storybook/ui" + "staticFilePath": "dist/storybook" }, "configurations": { "ci": { diff --git a/libs/ui/src/lib/account-balances/account-balances.component.html b/libs/ui/src/lib/account-balances/account-balances.component.html index 0cfa4a5da..caef922ed 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.html +++ b/libs/ui/src/lib/account-balances/account-balances.component.html @@ -38,7 +38,7 @@
      diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts index 756b3169f..caeaebc64 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.ts +++ b/libs/ui/src/lib/account-balances/account-balances.component.ts @@ -2,7 +2,7 @@ import { CreateAccountBalanceDto } from '@ghostfolio/api/app/account-balance/cre import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; -import { getLocale } from '@ghostfolio/common/helper'; +import { DATE_FORMAT, getLocale } from '@ghostfolio/common/helper'; import { AccountBalancesResponse } from '@ghostfolio/common/interfaces'; import { @@ -31,6 +31,14 @@ import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { IonIcon } from '@ionic/angular/standalone'; +import { format } from 'date-fns'; +import { addIcons } from 'ionicons'; +import { + calendarClearOutline, + ellipsisHorizontal, + trashOutline +} from 'ionicons/icons'; import { get } from 'lodash'; import { Subject } from 'rxjs'; @@ -40,6 +48,7 @@ import { GfValueComponent } from '../value'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [ GfValueComponent, + IonIcon, MatButtonModule, MatDatepickerModule, MatFormFieldModule, @@ -85,7 +94,9 @@ export class GfAccountBalancesComponent public constructor( private dateAdapter: DateAdapter, private notificationService: NotificationService - ) {} + ) { + addIcons({ calendarClearOutline, ellipsisHorizontal, trashOutline }); + } public ngOnInit() { this.dateAdapter.setLocale(this.locale); @@ -114,7 +125,7 @@ export class GfAccountBalancesComponent const accountBalance: CreateAccountBalanceDto = { accountId: this.accountId, balance: this.accountBalanceForm.get('balance').value, - date: this.accountBalanceForm.get('date').value.toISOString() + date: format(this.accountBalanceForm.get('date').value, DATE_FORMAT) }; try { diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.ts b/libs/ui/src/lib/activities-filter/activities-filter.component.ts index 4356ba5ac..c31a5fecd 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts @@ -1,6 +1,5 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { Filter, FilterGroup } from '@ghostfolio/common/interfaces'; -import { translate } from '@ghostfolio/ui/i18n'; import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { CommonModule } from '@angular/common'; @@ -27,15 +26,21 @@ import { MatButtonModule } from '@angular/material/button'; import { MatChipInputEvent, MatChipsModule } from '@angular/material/chips'; import { MatInputModule } from '@angular/material/input'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { closeOutline, searchOutline } from 'ionicons/icons'; import { groupBy } from 'lodash'; import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { translate } from '../i18n'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, GfSymbolModule, + IonIcon, MatAutocompleteModule, MatButtonModule, MatChipsModule, @@ -82,6 +87,8 @@ export class GfActivitiesFilterComponent implements OnChanges, OnDestroy { this.filterGroups$.next(this.getGroupedFilters()); } }); + + addIcons({ closeOutline, searchOutline }); } public ngOnChanges(changes: SimpleChanges) { diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index 4fdc41c59..59ec6315f 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -124,7 +124,7 @@
    - - {{ element.SymbolProfile?.currency }} + {{ element.currency ?? element.SymbolProfile?.currency }}
    - @if (element.Account?.Platform?.url) { - } - {{ element.Account?.name }} + {{ element.account?.name }}
    - - - - +
    +
    Index - {{ element?.name }} -
    + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + Change from All Time High + from ATH + + + - - - - + + + + + + + + + - - -
    + Name + + {{ element?.name }} + - 50-Day Trend - -
    - @if (element?.trend50d !== 'UNKNOWN') { - - } -
    -
    + 50-Day Trend + +
    + @if (element?.trend50d !== 'UNKNOWN') { + + } +
    +
    - 200-Day Trend - -
    - @if (element?.trend200d !== 'UNKNOWN') { - - } -
    -
    + 200-Day Trend + +
    + @if (element?.trend200d !== 'UNKNOWN') { + + } +
    +
    - Last All Time High - -
    - -
    -
    + Last All Time High + +
    + @if (element?.performances?.allTimeHigh?.date) { + + } +
    +
    - Change from All Time High + - from ATH - - - + @if (isNumber(element?.performances?.allTimeHigh?.performancePercent)) { + + } + - @if (element?.marketCondition) { -
    - {{ resolveMarketCondition(element.marketCondition).emoji }} -
    - } -
    + @if (element?.marketCondition) { +
    + {{ resolveMarketCondition(element.marketCondition).emoji }} +
    + } +
    + @if (hasPermissionToDeleteItem) { + + } + + + +
    + + + +
    @if (isLoading) { (); + + @ViewChild(MatSort) sort: MatSort; + + public dataSource = new MatTableDataSource([]); + public displayedColumns = [ + 'name', + 'date', + 'change', + 'marketCondition', + 'actions' + ]; public isLoading = true; + public isNumber = isNumber; public resolveMarketCondition = resolveMarketCondition; public translate = translate; @@ -56,6 +85,7 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { public constructor( private dialog: MatDialog, + private notificationService: NotificationService, private route: ActivatedRoute, private router: Router ) { @@ -73,10 +103,16 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { }); } }); + + addIcons({ ellipsisHorizontal, trashOutline }); } public ngOnChanges() { if (this.benchmarks) { + this.dataSource.data = this.benchmarks; + this.dataSource.sort = this.sort; + this.dataSource.sortingDataAccessor = get; + this.isLoading = false; } @@ -87,11 +123,22 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { 'trend200d', 'date', 'change', - 'marketCondition' + 'marketCondition', + 'actions' ]; } } + public onDeleteItem({ dataSource, symbol }: AssetProfileIdentifier) { + this.notificationService.confirm({ + confirmFn: () => { + this.itemDeleted.emit({ dataSource, symbol }); + }, + confirmType: ConfirmationDialogType.Warn, + title: $localize`Do you really want to delete this item?` + }); + } + public onOpenBenchmarkDialog({ dataSource, symbol }: AssetProfileIdentifier) { this.router.navigate([], { queryParams: { dataSource, symbol, benchmarkDetailDialog: true } diff --git a/libs/ui/src/lib/carousel/carousel.component.ts b/libs/ui/src/lib/carousel/carousel.component.ts index 2c3cc3ec0..4ecd12c79 100644 --- a/libs/ui/src/lib/carousel/carousel.component.ts +++ b/libs/ui/src/lib/carousel/carousel.component.ts @@ -12,10 +12,13 @@ import { } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { chevronBackOutline, chevronForwardOutline } from 'ionicons/icons'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [MatButtonModule], + imports: [IonIcon, MatButtonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-carousel', styleUrls: ['./carousel.component.scss'], @@ -40,6 +43,8 @@ export class GfCarouselComponent { @Optional() @Inject(ANIMATION_MODULE_TYPE) animationsModule?: string ) { this.animationsDisabled = animationsModule === 'NoopAnimations'; + + addIcons({ chevronBackOutline, chevronForwardOutline }); } public next() { diff --git a/libs/ui/src/lib/currency-selector/currency-selector.component.ts b/libs/ui/src/lib/currency-selector/currency-selector.component.ts index 7ab32b5fb..35a911716 100644 --- a/libs/ui/src/lib/currency-selector/currency-selector.component.ts +++ b/libs/ui/src/lib/currency-selector/currency-selector.component.ts @@ -1,11 +1,10 @@ -import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-field'; - import { FocusMonitor } from '@angular/cdk/a11y'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, + DoCheck, ElementRef, Input, OnDestroy, @@ -32,6 +31,8 @@ import { MatInput, MatInputModule } from '@angular/material/input'; import { Subject } from 'rxjs'; import { map, startWith, takeUntil } from 'rxjs/operators'; +import { AbstractMatFormField } from '../shared/abstract-mat-form-field'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { @@ -58,7 +59,7 @@ import { map, startWith, takeUntil } from 'rxjs/operators'; }) export class GfCurrencySelectorComponent extends AbstractMatFormField - implements OnInit, OnDestroy + implements DoCheck, OnDestroy, OnInit { @Input() private currencies: string[] = []; @Input() private formControlName: string; diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html index fb9f2c13b..921433620 100644 --- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html @@ -1,9 +1,16 @@ - Market data provided by {{ + Market data provided by  + @for ( + dataProviderInfo of dataProviderInfos; + track dataProviderInfo; + let last = $last + ) { + {{ dataProviderInfo.name - }}, . + }} + @if (!last) { + ,  + } + } + . diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts index 9be034e64..2d455c0d6 100644 --- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts @@ -1,6 +1,5 @@ import { DataProviderInfo } from '@ghostfolio/common/interfaces'; -import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, @@ -10,7 +9,6 @@ import { @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-data-provider-credits', styleUrls: ['./data-provider-credits.component.scss'], diff --git a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.html b/libs/ui/src/lib/entity-logo/entity-logo.component.html similarity index 100% rename from apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.html rename to libs/ui/src/lib/entity-logo/entity-logo.component.html diff --git a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.scss b/libs/ui/src/lib/entity-logo/entity-logo.component.scss similarity index 100% rename from apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.scss rename to libs/ui/src/lib/entity-logo/entity-logo.component.scss diff --git a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts b/libs/ui/src/lib/entity-logo/entity-logo.component.ts similarity index 77% rename from apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts rename to libs/ui/src/lib/entity-logo/entity-logo.component.ts index 5db862969..7598fb4d5 100644 --- a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts +++ b/libs/ui/src/lib/entity-logo/entity-logo.component.ts @@ -12,11 +12,11 @@ import { DataSource } from '@prisma/client'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], - selector: 'gf-asset-profile-icon', - styleUrls: ['./asset-profile-icon.component.scss'], - templateUrl: './asset-profile-icon.component.html' + selector: 'gf-entity-logo', + styleUrls: ['./entity-logo.component.scss'], + templateUrl: './entity-logo.component.html' }) -export class GfAssetProfileIconComponent implements OnChanges { +export class GfEntityLogoComponent implements OnChanges { @Input() dataSource: DataSource; @Input() size: 'large'; @Input() symbol: string; diff --git a/libs/ui/src/lib/entity-logo/index.ts b/libs/ui/src/lib/entity-logo/index.ts new file mode 100644 index 000000000..9c5885208 --- /dev/null +++ b/libs/ui/src/lib/entity-logo/index.ts @@ -0,0 +1 @@ +export * from './entity-logo.component'; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html index 31c7b334d..60d5204e1 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html @@ -31,7 +31,9 @@ Retirement Date
    - {{ calculatorForm.get('retirementDate').value | date: 'MMMM YYYY' }} + {{ + calculatorForm.get('retirementDate')?.value | date: 'MMMM yyyy' + }}
    ; +} as Meta; -const Template: Story = ( - args: FireCalculatorComponent -) => ({ - props: args -}); +type Story = StoryObj; -export const Simple = Template.bind({}); -Simple.args = { - currency: 'USD', - fireWealth: 0, - locale: locale +export const Simple: Story = { + args: { + currency: 'USD', + fireWealth: 50000, + locale: locale + } }; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts index f8ce3dd50..64fbe1b74 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts @@ -41,7 +41,7 @@ import { Tooltip } from 'chart.js'; import 'chartjs-adapter-date-fns'; -import * as Color from 'color'; +import Color from 'color'; import { add, addYears, diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts index 710cb4020..d2d53f7ca 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts @@ -1,14 +1,14 @@ import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; -import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, Inject, - OnDestroy + OnDestroy, + OnInit } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; @@ -21,6 +21,9 @@ import { } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { calendarClearOutline, refreshOutline } from 'ionicons/icons'; import { Subject, takeUntil } from 'rxjs'; import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces'; @@ -29,8 +32,8 @@ import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces' changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, imports: [ - CommonModule, FormsModule, + IonIcon, MatButtonModule, MatDatepickerModule, MatDialogModule, @@ -43,7 +46,9 @@ import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces' styleUrls: ['./historical-market-data-editor-dialog.scss'], templateUrl: 'historical-market-data-editor-dialog.html' }) -export class GfHistoricalMarketDataEditorDialogComponent implements OnDestroy { +export class GfHistoricalMarketDataEditorDialogComponent + implements OnDestroy, OnInit +{ private unsubscribeSubject = new Subject(); public constructor( @@ -55,7 +60,9 @@ export class GfHistoricalMarketDataEditorDialogComponent implements OnDestroy { private dateAdapter: DateAdapter, public dialogRef: MatDialogRef, @Inject(MAT_DATE_LOCALE) private locale: string - ) {} + ) { + addIcons({ calendarClearOutline, refreshOutline }); + } public ngOnInit() { this.locale = this.data.user?.settings?.locale; diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html index b35e1d812..c64d597b5 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.html @@ -1,7 +1,7 @@
    @for (itemByMonth of marketDataByMonth | keyvalue; track itemByMonth) {
    -
    {{ itemByMonth.key }}
    +
    {{ itemByMonth.key }}
    @for (dayItem of days; track dayItem; let i = $index) {
    diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts index caa0b15e6..7fbb1e621 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts @@ -261,7 +261,9 @@ export class GfHistoricalMarketDataEditorComponent this.snackBar.open( $localize`Oops! Could not parse historical data.`, undefined, - { duration: ms('3 seconds') } + { + duration: ms('3 seconds') + } ); } } diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.html b/libs/ui/src/lib/holdings-table/holdings-table.component.html index 5e4526fdc..2c238b137 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.html +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -10,7 +10,7 @@ -
    } - -@if ( - dataSource.data.length === 0 && hasPermissionToCreateActivity && !isLoading -) { -
    - -
    -} diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.ts b/libs/ui/src/lib/holdings-table/holdings-table.component.ts index 14382f420..a4b86e2d7 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.ts +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.ts @@ -1,12 +1,9 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, PortfolioPosition } from '@ghostfolio/common/interfaces'; -import { GfNoTransactionsInfoComponent } from '@ghostfolio/ui/no-transactions-info'; -import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { @@ -29,12 +26,14 @@ import { AssetSubClass } from '@prisma/client'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject, Subscription } from 'rxjs'; +import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; +import { GfValueComponent } from '../value/value.component'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, - GfAssetProfileIconComponent, - GfNoTransactionsInfoComponent, + GfEntityLogoComponent, GfSymbolModule, GfValueComponent, MatButtonModule, @@ -52,7 +51,6 @@ import { Subject, Subscription } from 'rxjs'; export class GfHoldingsTableComponent implements OnChanges, OnDestroy { @Input() baseCurrency: string; @Input() deviceType: string; - @Input() hasPermissionToCreateActivity: boolean; @Input() hasPermissionToOpenDetails = true; @Input() hasPermissionToShowValues = true; @Input() holdings: PortfolioPosition[]; diff --git a/libs/ui/src/lib/i18n.ts b/libs/ui/src/lib/i18n.ts index c0f95d457..f02da40e1 100644 --- a/libs/ui/src/lib/i18n.ts +++ b/libs/ui/src/lib/i18n.ts @@ -21,7 +21,7 @@ const locales = { MONTH: $localize`Month`, MONTHS: $localize`Months`, OTHER: $localize`Other`, - PROFESSIONAL_DATA_PROVIDER_TOOLTIP_PREMIUM: $localize`Get access to 100’000+ tickers from over 50 exchanges`, + PROFESSIONAL_DATA_PROVIDER_TOOLTIP_PREMIUM: $localize`Get access to 80’000+ tickers from over 50 exchanges`, PRESET_ID: $localize`Preset`, RETIREMENT_PROVISION: $localize`Retirement Provision`, SATELLITE: $localize`Satellite`, @@ -41,7 +41,7 @@ const locales = { SELL: $localize`Sell`, // AssetClass (enum) - CASH: $localize`Cash`, + ALTERNATIVE_INVESTMENT: $localize`Alternative Investment`, COMMODITY: $localize`Commodity`, EQUITY: $localize`Equity`, FIXED_INCOME: $localize`Fixed Income`, @@ -50,6 +50,8 @@ const locales = { // AssetSubClass (enum) BOND: $localize`Bond`, + CASH: $localize`Cash`, + COLLECTIBLE: $localize`Collectible`, CRYPTOCURRENCY: $localize`Cryptocurrency`, ETF: $localize`ETF`, MUTUALFUND: $localize`Mutual Fund`, @@ -70,9 +72,11 @@ const locales = { 'South America': $localize`South America`, // Countries + Armenia: $localize`Armenia`, Australia: $localize`Australia`, Austria: $localize`Austria`, Belgium: $localize`Belgium`, + 'British Virgin Islands': $localize`British Virgin Islands`, Bulgaria: $localize`Bulgaria`, Canada: $localize`Canada`, 'Czech Republic': $localize`Czech Republic`, @@ -80,16 +84,19 @@ const locales = { France: $localize`France`, Germany: $localize`Germany`, India: $localize`India`, + Indonesia: $localize`Indonesia`, Italy: $localize`Italy`, Japan: $localize`Japan`, Netherlands: $localize`Netherlands`, 'New Zealand': $localize`New Zealand`, Poland: $localize`Poland`, Romania: $localize`Romania`, + Singapore: $localize`Singapore`, 'South Africa': $localize`South Africa`, Switzerland: $localize`Switzerland`, Thailand: $localize`Thailand`, Ukraine: $localize`Ukraine`, + 'United Kingdom': $localize`United Kingdom`, 'United States': $localize`United States`, // Fear and Greed Index diff --git a/libs/ui/src/lib/line-chart/line-chart.component.stories.ts b/libs/ui/src/lib/line-chart/line-chart.component.stories.ts index 59580a136..ba8ee1298 100644 --- a/libs/ui/src/lib/line-chart/line-chart.component.stories.ts +++ b/libs/ui/src/lib/line-chart/line-chart.component.stories.ts @@ -1,235 +1,236 @@ import { CommonModule } from '@angular/common'; -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { LineChartComponent } from './line-chart.component'; +import { GfLineChartComponent } from './line-chart.component'; export default { title: 'Line Chart', - component: LineChartComponent, + component: GfLineChartComponent, decorators: [ moduleMetadata({ - declarations: [LineChartComponent], - imports: [CommonModule, NgxSkeletonLoaderModule] + imports: [CommonModule, GfLineChartComponent, NgxSkeletonLoaderModule] }) ] -} as Meta; +} as Meta; -const Template: Story = (args: LineChartComponent) => ({ - props: args -}); +type Story = StoryObj; -export const Simple = Template.bind({}); -Simple.args = { - historicalDataItems: [ - { - date: '2017-01-01', - value: 2561.60376 - }, - { - date: '2017-02-01', - value: 2261.60376 - }, - { - date: '2017-03-01', - value: 2268.68157074 - }, - { - date: '2017-04-01', - value: 2525.2942 - }, - { - date: '2017-05-01', - value: 2929.3595107399997 - }, - { - date: '2017-06-01', - value: 3088.5172438900004 - }, - { - date: '2017-07-01', - value: 3281.2490946300004 - }, - { - date: '2017-08-01', - value: 4714.57822537 - }, - { - date: '2017-09-01', - value: 5717.262455259565 - }, - { - date: '2017-10-01', - value: 5338.742482334544 - }, - { - date: '2017-11-01', - value: 6361.263771554509 - }, - { - date: '2017-12-01', - value: 8373.260491904595 - }, - { - date: '2018-01-01', - value: 9783.208968191562 - }, - { - date: '2018-02-01', - value: 7841.2667100173 - }, - { - date: '2018-03-01', - value: 8582.133039380678 - }, - { - date: '2018-04-01', - value: 5901.8362986766715 - }, - { - date: '2018-05-01', - value: 7367.392976151925 - }, - { - date: '2018-06-01', - value: 6490.164314049853 - }, - { - date: '2018-07-01', - value: 6365.351621654618 - }, - { - date: '2018-08-01', - value: 6614.532706931272 - }, - { - date: '2018-09-01', - value: 6402.052882414409 - }, - { - date: '2018-10-01', - value: 15270.327917651943 - }, - { - date: '2018-11-01', - value: 13929.833891940816 - }, - { - date: '2018-12-01', - value: 12995.832254431414 - }, - { - date: '2019-01-01', - value: 11792.447013828998 - }, - { - date: '2019-02-01', - value: 11988.224284346446 - }, - { - date: '2019-03-01', - value: 13536.39667099519 - }, - { - date: '2019-04-01', - value: 14301.83740090022 - }, - { - date: '2019-05-01', - value: 14902.994910520581 - }, - { - date: '2019-06-01', - value: 15373.418326284132 - }, - { - date: '2019-07-01', - value: 17545.70705465703 - }, - { - date: '2019-08-01', - value: 17206.28500223782 - }, - { - date: '2019-09-01', - value: 17782.445200108898 - }, - { - date: '2019-10-01', - value: 17050.25875252655 - }, - { - date: '2019-11-01', - value: 18517.053521416237 - }, - { - date: '2019-12-01', - value: 17850.649021651363 - }, - { - date: '2020-01-01', - value: 18817.269786559067 - }, - { - date: '2020-02-01', - value: 22769.842312027653 - }, - { - date: '2020-03-01', - value: 23065.56002316582 - }, - { - date: '2020-04-01', - value: 19738.122641884733 - }, - { - date: '2020-05-01', - value: 25112.281463810643 - }, - { - date: '2020-06-01', - value: 28753.054132147452 - }, - { - date: '2020-07-01', - value: 32207.62827031543 - }, - { - date: '2020-08-01', - value: 37837.88816828611 - }, - { - date: '2020-09-01', - value: 50018.740185519295 - }, - { - date: '2020-10-01', - value: 46593.322295801525 - }, - { - date: '2020-11-01', - value: 44440.18743231742 - }, - { - date: '2020-12-01', - value: 57582.23077536893 - }, - { - date: '2021-01-01', - value: 68823.02446077733 - }, - { - date: '2021-02-01', - value: 64516.42092139593 - }, - { - date: '2021-03-01', - value: 82465.97581106682 - }, - { - date: '2021-03-18', - value: 86666.03082624623 - } - ], - isAnimated: true +export const Simple: Story = { + args: { + historicalDataItems: [ + { + date: '2017-01-01', + value: 2561.60376 + }, + { + date: '2017-02-01', + value: 2261.60376 + }, + { + date: '2017-03-01', + value: 2268.68157074 + }, + { + date: '2017-04-01', + value: 2525.2942 + }, + { + date: '2017-05-01', + value: 2929.3595107399997 + }, + { + date: '2017-06-01', + value: 3088.5172438900004 + }, + { + date: '2017-07-01', + value: 3281.2490946300004 + }, + { + date: '2017-08-01', + value: 4714.57822537 + }, + { + date: '2017-09-01', + value: 5717.262455259565 + }, + { + date: '2017-10-01', + value: 5338.742482334544 + }, + { + date: '2017-11-01', + value: 6361.263771554509 + }, + { + date: '2017-12-01', + value: 8373.260491904595 + }, + { + date: '2018-01-01', + value: 9783.208968191562 + }, + { + date: '2018-02-01', + value: 7841.2667100173 + }, + { + date: '2018-03-01', + value: 8582.133039380678 + }, + { + date: '2018-04-01', + value: 5901.8362986766715 + }, + { + date: '2018-05-01', + value: 7367.392976151925 + }, + { + date: '2018-06-01', + value: 6490.164314049853 + }, + { + date: '2018-07-01', + value: 6365.351621654618 + }, + { + date: '2018-08-01', + value: 6614.532706931272 + }, + { + date: '2018-09-01', + value: 6402.052882414409 + }, + { + date: '2018-10-01', + value: 15270.327917651943 + }, + { + date: '2018-11-01', + value: 13929.833891940816 + }, + { + date: '2018-12-01', + value: 12995.832254431414 + }, + { + date: '2019-01-01', + value: 11792.447013828998 + }, + { + date: '2019-02-01', + value: 11988.224284346446 + }, + { + date: '2019-03-01', + value: 13536.39667099519 + }, + { + date: '2019-04-01', + value: 14301.83740090022 + }, + { + date: '2019-05-01', + value: 14902.994910520581 + }, + { + date: '2019-06-01', + value: 15373.418326284132 + }, + { + date: '2019-07-01', + value: 17545.70705465703 + }, + { + date: '2019-08-01', + value: 17206.28500223782 + }, + { + date: '2019-09-01', + value: 17782.445200108898 + }, + { + date: '2019-10-01', + value: 17050.25875252655 + }, + { + date: '2019-11-01', + value: 18517.053521416237 + }, + { + date: '2019-12-01', + value: 17850.649021651363 + }, + { + date: '2020-01-01', + value: 18817.269786559067 + }, + { + date: '2020-02-01', + value: 22769.842312027653 + }, + { + date: '2020-03-01', + value: 23065.56002316582 + }, + { + date: '2020-04-01', + value: 19738.122641884733 + }, + { + date: '2020-05-01', + value: 25112.281463810643 + }, + { + date: '2020-06-01', + value: 28753.054132147452 + }, + { + date: '2020-07-01', + value: 32207.62827031543 + }, + { + date: '2020-08-01', + value: 37837.88816828611 + }, + { + date: '2020-09-01', + value: 50018.740185519295 + }, + { + date: '2020-10-01', + value: 46593.322295801525 + }, + { + date: '2020-11-01', + value: 44440.18743231742 + }, + { + date: '2020-12-01', + value: 57582.23077536893 + }, + { + date: '2021-01-01', + value: 68823.02446077733 + }, + { + date: '2021-02-01', + value: 64516.42092139593 + }, + { + date: '2021-03-01', + value: 82465.97581106682 + }, + { + date: '2021-03-18', + value: 86666.03082624623 + } + ], + isAnimated: true, + label: 'Net Worth', + unit: 'USD' + } }; diff --git a/libs/ui/src/lib/line-chart/line-chart.component.ts b/libs/ui/src/lib/line-chart/line-chart.component.ts index 09f5a98eb..e7f8b132e 100644 --- a/libs/ui/src/lib/line-chart/line-chart.component.ts +++ b/libs/ui/src/lib/line-chart/line-chart.component.ts @@ -54,13 +54,13 @@ export class GfLineChartComponent @Input() currency: string; @Input() historicalDataItems: LineChartItem[]; @Input() isAnimated = false; + @Input() label: string; @Input() locale = getLocale(); @Input() showGradient = false; @Input() showLegend = false; @Input() showLoader = true; @Input() showXAxis = false; @Input() showYAxis = false; - @Input() symbol: string; @Input() unit: string; @Input() yMax: number; @Input() yMaxLabel: string; @@ -162,7 +162,7 @@ export class GfLineChartComponent borderWidth: 2, data: marketPrices, fill: true, - label: this.symbol, + label: this.label, pointRadius: 0 } ] diff --git a/libs/ui/src/lib/logo/logo.component.stories.ts b/libs/ui/src/lib/logo/logo.component.stories.ts index 196043eb3..50f047184 100644 --- a/libs/ui/src/lib/logo/logo.component.stories.ts +++ b/libs/ui/src/lib/logo/logo.component.stories.ts @@ -1,30 +1,32 @@ -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; -import { LogoComponent } from './logo.component'; +import { GfLogoComponent } from './logo.component'; export default { title: 'Logo', - component: LogoComponent, + component: GfLogoComponent, decorators: [ moduleMetadata({ imports: [] }) ] -} as Meta; +} as Meta; -const Template: Story = (args: LogoComponent) => ({ - props: args -}); +type Story = StoryObj; -export const Default = Template.bind({}); -Default.args = {}; +export const Default: Story = { + args: {} +}; -export const Large = Template.bind({}); -Large.args = { - size: 'large' +export const Large: Story = { + args: { + size: 'large' + } }; -export const NoLabel = Template.bind({}); -NoLabel.args = { - showLabel: false +export const WithoutLabel: Story = { + args: { + showLabel: false + } }; diff --git a/libs/ui/src/lib/membership-card/membership-card.component.html b/libs/ui/src/lib/membership-card/membership-card.component.html index 37634b020..1c68f5e3f 100644 --- a/libs/ui/src/lib/membership-card/membership-card.component.html +++ b/libs/ui/src/lib/membership-card/membership-card.component.html @@ -14,7 +14,7 @@ />
    @if (hasPermissionToCreateApiKey) { -
    +
    API Key
    * * * * * * * * *
    diff --git a/libs/ui/src/lib/membership-card/membership-card.component.stories.ts b/libs/ui/src/lib/membership-card/membership-card.component.stories.ts new file mode 100644 index 000000000..6b6fbe038 --- /dev/null +++ b/libs/ui/src/lib/membership-card/membership-card.component.stories.ts @@ -0,0 +1,50 @@ +import { CommonModule } from '@angular/common'; +import '@angular/localize/init'; +import { MatButtonModule } from '@angular/material/button'; +import { ActivatedRoute, RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; +import { addYears } from 'date-fns'; + +import { GfLogoComponent } from '../logo'; +import { GfMembershipCardComponent } from './membership-card.component'; + +export default { + title: 'Membership Card', + component: GfMembershipCardComponent, + decorators: [ + moduleMetadata({ + imports: [ + CommonModule, + GfLogoComponent, + IonIcon, + MatButtonModule, + RouterModule.forChild([]) + ], + providers: [{ provide: ActivatedRoute, useValue: {} }] + }) + ], + argTypes: { + name: { + control: { type: 'select' }, + options: ['Basic', 'Premium'] + } + } +} as Meta; + +type Story = StoryObj; + +export const Basic: Story = { + args: { + name: 'Basic' + } +}; + +export const Premium: Story = { + args: { + expiresAt: addYears(new Date(), 1).toLocaleDateString(), + hasPermissionToCreateApiKey: true, + name: 'Premium' + } +}; diff --git a/libs/ui/src/lib/membership-card/membership-card.component.ts b/libs/ui/src/lib/membership-card/membership-card.component.ts index d40031b18..175a94f42 100644 --- a/libs/ui/src/lib/membership-card/membership-card.component.ts +++ b/libs/ui/src/lib/membership-card/membership-card.component.ts @@ -1,3 +1,5 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, @@ -9,12 +11,21 @@ import { } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { refreshOutline } from 'ionicons/icons'; import { GfLogoComponent } from '../logo'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, GfLogoComponent, MatButtonModule, RouterModule], + imports: [ + CommonModule, + GfLogoComponent, + IonIcon, + MatButtonModule, + RouterModule + ], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-membership-card', styleUrls: ['./membership-card.component.scss'], @@ -27,7 +38,11 @@ export class GfMembershipCardComponent { @Output() generateApiKeyClicked = new EventEmitter(); - public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; + public routerLinkPricing = publicRoutes.pricing.routerLink; + + public constructor() { + addIcons({ refreshOutline }); + } public onGenerateApiKey(event: MouseEvent) { event.preventDefault(); diff --git a/libs/ui/src/lib/mocks/httpClient.mock.ts b/libs/ui/src/lib/mocks/httpClient.mock.ts new file mode 100644 index 000000000..6ef79af61 --- /dev/null +++ b/libs/ui/src/lib/mocks/httpClient.mock.ts @@ -0,0 +1,18 @@ +import { Observable } from 'rxjs'; + +export class HttpClientMock { + public constructor(private mockResponses: Map) {} + + public get(url: string, options?: any): Observable { + if (this.mockResponses.has(url) && options) { + return new Observable((subscriber) => { + subscriber.next(this.mockResponses.get(url)); + subscriber.complete(); + }); + } + + return new Observable((subscriber) => { + subscriber.error(new Error(`No mock data for URL: ${url}`)); + }); + } +} diff --git a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html index 9e31ffabf..f1a2a3f90 100644 --- a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html +++ b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.html @@ -7,7 +7,7 @@ color="primary" mat-button [queryParams]="{ createDialog: true }" - [routerLink]="['/portfolio', 'activities']" + [routerLink]="routerLinkPortfolioActivities" > Time to add your first activity. diff --git a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.stories.ts b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.stories.ts index 13a3404ee..faf536244 100644 --- a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.stories.ts +++ b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.stories.ts @@ -1,25 +1,23 @@ -import { GfLogoModule } from '@ghostfolio/ui/logo'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; import { RouterTestingModule } from '@angular/router/testing'; -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; -import { NoTransactionsInfoComponent } from './no-transactions-info.component'; +import { GfNoTransactionsInfoComponent } from './no-transactions-info.component'; export default { title: 'No Transactions Info', - component: NoTransactionsInfoComponent, + component: GfNoTransactionsInfoComponent, decorators: [ moduleMetadata({ - imports: [GfLogoModule, RouterTestingModule] + imports: [GfLogoComponent, RouterTestingModule] }) ] -} as Meta; +} as Meta; -const Template: Story = ( - args: NoTransactionsInfoComponent -) => ({ - props: args -}); +type Story = StoryObj; -export const Default = Template.bind({}); -Default.args = {}; +export const Default: Story = { + args: {} +}; diff --git a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts index 0d5b044eb..8691dc998 100644 --- a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts +++ b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts @@ -1,3 +1,5 @@ +import { internalRoutes } from '@ghostfolio/common/routes/routes'; + import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, @@ -20,4 +22,7 @@ import { GfLogoComponent } from '../logo'; }) export class GfNoTransactionsInfoComponent { @HostBinding('class.has-border') @Input() hasBorder = true; + + public routerLinkPortfolioActivities = + internalRoutes.portfolio.subRoutes.activities.routerLink; } diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.stories.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.stories.ts index 7d6db1b52..37010954a 100644 --- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.stories.ts +++ b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.stories.ts @@ -1,38 +1,39 @@ import { CommonModule } from '@angular/common'; import '@angular/localize/init'; -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { PortfolioProportionChartComponent } from './portfolio-proportion-chart.component'; +import { GfPortfolioProportionChartComponent } from './portfolio-proportion-chart.component'; export default { title: 'Portfolio Proportion Chart', - component: PortfolioProportionChartComponent, + component: GfPortfolioProportionChartComponent, decorators: [ moduleMetadata({ - declarations: [PortfolioProportionChartComponent], - imports: [CommonModule, NgxSkeletonLoaderModule] + imports: [ + CommonModule, + GfPortfolioProportionChartComponent, + NgxSkeletonLoaderModule + ] }) ] -} as Meta; +} as Meta; -const Template: Story = ( - args: PortfolioProportionChartComponent -) => ({ - props: args -}); +type Story = StoryObj; -export const Simple = Template.bind({}); -Simple.args = { - baseCurrency: 'USD', - keys: ['name'], - locale: 'en-US', - positions: { - Africa: { name: 'Africa', value: 983.22461479889288 }, - Asia: { name: 'Asia', value: 12074.754633964973 }, - Europe: { name: 'Europe', value: 34432.837085290535 }, - 'North America': { name: 'North America', value: 26539.89987780503 }, - Oceania: { name: 'Oceania', value: 1402.220605072031 }, - 'South America': { name: 'South America', value: 4938.25202180719859 } +export const Simple: Story = { + args: { + baseCurrency: 'USD', + data: { + Africa: { name: 'Africa', value: 983.22461479889288 }, + Asia: { name: 'Asia', value: 12074.754633964973 }, + Europe: { name: 'Europe', value: 34432.837085290535 }, + 'North America': { name: 'North America', value: 26539.89987780503 }, + Oceania: { name: 'Oceania', value: 1402.220605072031 }, + 'South America': { name: 'South America', value: 4938.25202180719859 } + }, + keys: ['name'], + locale: 'en-US' } }; diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts index 7f914870b..3f062a374 100644 --- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts +++ b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts @@ -6,7 +6,6 @@ import { PortfolioPosition } from '@ghostfolio/common/interfaces'; import { ColorScheme } from '@ghostfolio/common/types'; -import { translate } from '@ghostfolio/ui/i18n'; import { CommonModule } from '@angular/common'; import { @@ -29,9 +28,12 @@ import { ArcElement } from 'chart.js'; import { DoughnutController } from 'chart.js'; import { Chart } from 'chart.js'; import ChartDataLabels from 'chartjs-plugin-datalabels'; -import * as Color from 'color'; +import { isUUID } from 'class-validator'; +import Color from 'color'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; +import { translate } from '../i18n'; + const { blue, cyan, @@ -60,24 +62,24 @@ export class GfPortfolioProportionChartComponent @Input() baseCurrency: string; @Input() colorScheme: ColorScheme; @Input() cursor: string; - @Input() isInPercent = false; - @Input() keys: string[] = []; - @Input() locale = getLocale(); - @Input() maxItems?: number; - @Input() showLabels = false; - @Input() positions: { + @Input() data: { [symbol: string]: Pick & { dataSource?: DataSource; name: string; value: number; }; } = {}; + @Input() isInPercent = false; + @Input() keys: string[] = []; + @Input() locale = getLocale(); + @Input() maxItems?: number; + @Input() showLabels = false; @Output() proportionChartClicked = new EventEmitter(); @ViewChild('chartCanvas') chartCanvas: ElementRef; - public chart: Chart<'pie'>; + public chart: Chart<'doughnut'>; public isLoading = true; private readonly OTHER_KEY = 'OTHER'; @@ -91,13 +93,13 @@ export class GfPortfolioProportionChartComponent } public ngAfterViewInit() { - if (this.positions) { + if (this.data) { this.initialize(); } } public ngOnChanges() { - if (this.positions) { + if (this.data) { this.initialize(); } } @@ -122,47 +124,45 @@ export class GfPortfolioProportionChartComponent }; if (this.keys.length > 0) { - Object.keys(this.positions).forEach((symbol) => { - if (this.positions[symbol][this.keys[0]]?.toUpperCase()) { - if (chartData[this.positions[symbol][this.keys[0]].toUpperCase()]) { - chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() - ].value = chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() - ].value.plus(this.positions[symbol].value || 0); + Object.keys(this.data).forEach((symbol) => { + if (this.data[symbol][this.keys[0]]?.toUpperCase()) { + if (chartData[this.data[symbol][this.keys[0]].toUpperCase()]) { + chartData[this.data[symbol][this.keys[0]].toUpperCase()].value = + chartData[ + this.data[symbol][this.keys[0]].toUpperCase() + ].value.plus(this.data[symbol].value || 0); if ( - chartData[this.positions[symbol][this.keys[0]].toUpperCase()] - .subCategory[this.positions[symbol][this.keys[1]]] + chartData[this.data[symbol][this.keys[0]].toUpperCase()] + .subCategory[this.data[symbol][this.keys[1]]] ) { chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() - ].subCategory[this.positions[symbol][this.keys[1]]].value = - chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() - ].subCategory[this.positions[symbol][this.keys[1]]].value.plus( - this.positions[symbol].value || 0 - ); + this.data[symbol][this.keys[0]].toUpperCase() + ].subCategory[this.data[symbol][this.keys[1]]].value = chartData[ + this.data[symbol][this.keys[0]].toUpperCase() + ].subCategory[this.data[symbol][this.keys[1]]].value.plus( + this.data[symbol].value || 0 + ); } else { chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() - ].subCategory[ - this.positions[symbol][this.keys[1]] ?? UNKNOWN_KEY - ] = { value: new Big(this.positions[symbol].value || 0) }; + this.data[symbol][this.keys[0]].toUpperCase() + ].subCategory[this.data[symbol][this.keys[1]] ?? UNKNOWN_KEY] = { + value: new Big(this.data[symbol].value || 0) + }; } } else { - chartData[this.positions[symbol][this.keys[0]].toUpperCase()] = { - name: this.positions[symbol][this.keys[0]], + chartData[this.data[symbol][this.keys[0]].toUpperCase()] = { + name: this.data[symbol][this.keys[0]], subCategory: {}, - value: new Big(this.positions[symbol].value || 0) + value: new Big(this.data[symbol].value || 0) }; - if (this.positions[symbol][this.keys[1]]) { + if (this.data[symbol][this.keys[1]]) { chartData[ - this.positions[symbol][this.keys[0]].toUpperCase() + this.data[symbol][this.keys[0]].toUpperCase() ].subCategory = { - [this.positions[symbol][this.keys[1]]]: { - value: new Big(this.positions[symbol].value || 0) + [this.data[symbol][this.keys[1]]]: { + value: new Big(this.data[symbol].value || 0) } }; } @@ -170,24 +170,24 @@ export class GfPortfolioProportionChartComponent } else { if (chartData[UNKNOWN_KEY]) { chartData[UNKNOWN_KEY].value = chartData[UNKNOWN_KEY].value.plus( - this.positions[symbol].value || 0 + this.data[symbol].value || 0 ); } else { chartData[UNKNOWN_KEY] = { - name: this.positions[symbol].name, + name: this.data[symbol].name, subCategory: this.keys[1] ? { [this.keys[1]]: { value: new Big(0) } } : undefined, - value: new Big(this.positions[symbol].value || 0) + value: new Big(this.data[symbol].value || 0) }; } } }); } else { - Object.keys(this.positions).forEach((symbol) => { + Object.keys(this.data).forEach((symbol) => { chartData[symbol] = { - name: this.positions[symbol].name, - value: new Big(this.positions[symbol].value || 0) + name: this.data[symbol].name, + value: new Big(this.data[symbol].value || 0) }; }); } @@ -247,9 +247,13 @@ export class GfPortfolioProportionChartComponent let lightnessRatio = 0.2; Object.keys(item.subCategory ?? {}).forEach((subCategory) => { - backgroundColorSubCategory.push( - Color(item.color).lighten(lightnessRatio).hex() - ); + if (item.name === UNKNOWN_KEY) { + backgroundColorSubCategory.push(item.color); + } else { + backgroundColorSubCategory.push( + Color(item.color).lighten(lightnessRatio).hex() + ); + } dataSubCategory.push(item.subCategory[subCategory].value.toNumber()); labelSubCategory.push(subCategory); @@ -257,7 +261,7 @@ export class GfPortfolioProportionChartComponent }); }); - const datasets: ChartConfiguration['data']['datasets'] = [ + const datasets: ChartConfiguration<'doughnut'>['data']['datasets'] = [ { backgroundColor: chartDataSorted.map(([, item]) => { return item.color; @@ -295,7 +299,7 @@ export class GfPortfolioProportionChartComponent datasets[1].data[1] = Number.MAX_SAFE_INTEGER; } - const data: ChartConfiguration['data'] = { + const data: ChartConfiguration<'doughnut'>['data'] = { datasets, labels }; @@ -308,7 +312,7 @@ export class GfPortfolioProportionChartComponent ) as unknown; this.chart.update(); } else { - this.chart = new Chart(this.chartCanvas.nativeElement, { + this.chart = new Chart<'doughnut'>(this.chartCanvas.nativeElement, { data, options: { animation: false, @@ -321,7 +325,7 @@ export class GfPortfolioProportionChartComponent const dataIndex = activeElements[0].index; const symbol: string = event.chart.data.labels[dataIndex]; - const dataSource = this.positions[symbol]?.dataSource; + const dataSource = this.data[symbol]?.dataSource; this.proportionChartClicked.emit({ dataSource, symbol }); } catch {} @@ -346,8 +350,14 @@ export class GfPortfolioProportionChartComponent align: 'end', anchor: 'end', formatter: (value, context) => { + const symbol = context.chart.data.labels?.[ + context.dataIndex + ] as string; + return value > 0 - ? context.chart.data.labels?.[context.dataIndex] + ? isUUID(symbol) + ? (translate(this.data[symbol]?.name) ?? symbol) + : symbol : ''; }, offset: 8 @@ -404,7 +414,7 @@ export class GfPortfolioProportionChartComponent symbol = $localize`No data available`; } - const name = translate(this.positions[symbol as string]?.name); + const name = translate(this.data[symbol as string]?.name); let sum = 0; for (const item of context.dataset.data) { diff --git a/libs/ui/src/lib/premium-indicator/premium-indicator.component.html b/libs/ui/src/lib/premium-indicator/premium-indicator.component.html index 29903b181..3141414e7 100644 --- a/libs/ui/src/lib/premium-indicator/premium-indicator.component.html +++ b/libs/ui/src/lib/premium-indicator/premium-indicator.component.html @@ -2,6 +2,6 @@ class="align-items-center d-flex" title="Upgrade to Ghostfolio Premium" [ngStyle]="{ 'pointer-events': enableLink ? 'initial' : 'none' }" - [routerLink]="['/pricing']" + [routerLink]="routerLinkPricing" > diff --git a/libs/ui/src/lib/premium-indicator/premium-indicator.component.stories.ts b/libs/ui/src/lib/premium-indicator/premium-indicator.component.stories.ts index bdb9c6543..4cf61084c 100644 --- a/libs/ui/src/lib/premium-indicator/premium-indicator.component.stories.ts +++ b/libs/ui/src/lib/premium-indicator/premium-indicator.component.stories.ts @@ -1,29 +1,28 @@ import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; -import { PremiumIndicatorComponent } from './premium-indicator.component'; +import { GfPremiumIndicatorComponent } from './premium-indicator.component'; export default { title: 'Premium Indicator', - component: PremiumIndicatorComponent, + component: GfPremiumIndicatorComponent, decorators: [ moduleMetadata({ imports: [CommonModule, RouterTestingModule] }) ] -} as Meta; +} as Meta; -const Template: Story = ( - args: PremiumIndicatorComponent -) => ({ - props: args -}); +type Story = StoryObj; -export const Default = Template.bind({}); -Default.args = {}; +export const Default: Story = { + args: {} +}; -export const WithoutLink = Template.bind({}); -WithoutLink.args = { - enableLink: false +export const WithoutLink = { + args: { + enableLink: false + } }; diff --git a/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts b/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts index 17b0f94dd..b3ccfd88f 100644 --- a/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts +++ b/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts @@ -1,3 +1,5 @@ +import { publicRoutes } from '@ghostfolio/common/routes/routes'; + import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, @@ -6,10 +8,13 @@ import { Input } from '@angular/core'; import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { diamondOutline } from 'ionicons/icons'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, RouterModule], + imports: [CommonModule, IonIcon, RouterModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-premium-indicator', styleUrls: ['./premium-indicator.component.scss'], @@ -17,4 +22,10 @@ import { RouterModule } from '@angular/router'; }) export class GfPremiumIndicatorComponent { @Input() enableLink = true; + + public routerLinkPricing = publicRoutes.pricing.routerLink; + + public constructor() { + addIcons({ diamondOutline }); + } } diff --git a/libs/ui/src/lib/shared/abstract-mat-form-field.ts b/libs/ui/src/lib/shared/abstract-mat-form-field.ts index 1938467f5..628f0a659 100644 --- a/libs/ui/src/lib/shared/abstract-mat-form-field.ts +++ b/libs/ui/src/lib/shared/abstract-mat-form-field.ts @@ -17,7 +17,6 @@ import { Subject } from 'rxjs'; template: '', standalone: false }) -// eslint-disable-next-line @angular-eslint/component-class-suffix export abstract class AbstractMatFormField implements ControlValueAccessor, DoCheck, MatFormFieldControl, OnDestroy { @@ -35,7 +34,7 @@ export abstract class AbstractMatFormField protected onChange?: (value: T) => void; protected onTouched?: () => void; - private static nextId: number = 0; + private static nextId = 0; protected constructor( protected _elementRef: ElementRef, @@ -83,7 +82,7 @@ export abstract class AbstractMatFormField return !this._value; } - public _placeholder: string = ''; + public _placeholder = ''; public get placeholder() { return this._placeholder; @@ -95,7 +94,7 @@ export abstract class AbstractMatFormField this.stateChanges.next(); } - public _required: boolean = false; + public _required = false; public get required() { return ( @@ -110,7 +109,7 @@ export abstract class AbstractMatFormField this.stateChanges.next(); } - public _disabled: boolean = false; + public _disabled = false; public get disabled() { if (this.ngControl?.disabled !== null) { diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html index c6327c318..456cd9940 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.html @@ -12,7 +12,7 @@ (optionSelected)="onUpdateSymbol($event)" > @if (!isLoading) { - @for (lookupItem of filteredLookupItems; track lookupItem) { + @for (lookupItem of lookupItems; track lookupItem) { ; + +type Story = StoryObj; + +export const Default: Story = { + args: {} +}; + +export const WithDefaultItems: Story = { + args: { + defaultLookupItems: DEFAULT_OPTIONS + } +}; diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts index 3c56c4748..f6c289b72 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts @@ -1,8 +1,6 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { LookupItem } from '@ghostfolio/common/interfaces'; -import { translate } from '@ghostfolio/ui/i18n'; -import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-field'; import { FocusMonitor } from '@angular/cdk/a11y'; import { @@ -10,10 +8,13 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DoCheck, ElementRef, Input, + OnChanges, OnDestroy, OnInit, + SimpleChanges, ViewChild } from '@angular/core'; import { @@ -43,7 +44,9 @@ import { takeUntil } from 'rxjs/operators'; +import { translate } from '../i18n'; import { GfPremiumIndicatorComponent } from '../premium-indicator'; +import { AbstractMatFormField } from '../shared/abstract-mat-form-field'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -74,18 +77,19 @@ import { GfPremiumIndicatorComponent } from '../premium-indicator'; }) export class GfSymbolAutocompleteComponent extends AbstractMatFormField - implements OnInit, OnDestroy + implements DoCheck, OnChanges, OnDestroy, OnInit { - @Input() private includeIndices = false; + @Input() public defaultLookupItems: LookupItem[] = []; @Input() public isLoading = false; - @ViewChild(MatInput) private input: MatInput; - @ViewChild('symbolAutocomplete') public symbolAutocomplete: MatAutocomplete; + @Input() private includeIndices = false; + + @ViewChild(MatInput) private input: MatInput; + public control = new FormControl(); - public filteredLookupItems: (LookupItem & { assetSubClassString: string })[] = - []; + public lookupItems: (LookupItem & { assetSubClassString: string })[] = []; private unsubscribeSubject = new Subject(); @@ -117,7 +121,13 @@ export class GfSymbolAutocompleteComponent this.control.valueChanges .pipe( filter((query) => { - return isString(query) && query.length > 1; + if (query.length === 0) { + this.showDefaultOptions(); + + return false; + } + + return isString(query); }), tap(() => { this.isLoading = true; @@ -135,7 +145,7 @@ export class GfSymbolAutocompleteComponent }) ) .subscribe((filteredLookupItems) => { - this.filteredLookupItems = filteredLookupItems.map((lookupItem) => { + this.lookupItems = filteredLookupItems.map((lookupItem) => { return { ...lookupItem, assetSubClassString: translate(lookupItem.assetSubClass) @@ -148,6 +158,12 @@ export class GfSymbolAutocompleteComponent }); } + public ngOnChanges(changes: SimpleChanges) { + if (changes['defaultLookupItems'] && this.defaultLookupItems?.length) { + this.showDefaultOptions(); + } + } + public displayFn(aLookupItem: LookupItem) { return aLookupItem?.symbol ?? ''; } @@ -161,7 +177,7 @@ export class GfSymbolAutocompleteComponent } public isValueInOptions(value: string) { - return this.filteredLookupItems.some((item) => { + return this.lookupItems.some((item) => { return item.symbol === value; }); } @@ -193,6 +209,17 @@ export class GfSymbolAutocompleteComponent this.unsubscribeSubject.complete(); } + private showDefaultOptions() { + this.lookupItems = this.defaultLookupItems.map((lookupItem) => { + return { + ...lookupItem, + assetSubClassString: translate(lookupItem.assetSubClass) + }; + }); + + this.changeDetectorRef.markForCheck(); + } + private validateRequired() { const requiredCheck = super.required ? !super.value?.dataSource || !super.value?.symbol diff --git a/libs/ui/src/lib/tags-selector/index.ts b/libs/ui/src/lib/tags-selector/index.ts new file mode 100644 index 000000000..360bce671 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/index.ts @@ -0,0 +1 @@ +export * from './tags-selector.component'; diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.html b/libs/ui/src/lib/tags-selector/tags-selector.component.html new file mode 100644 index 000000000..c3c02f3c7 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -0,0 +1,60 @@ +
    +
    + @if (readonly) { +
    Tags
    + @if (tags?.length > 0) { + + @for (tag of tags; track tag) { + {{ tag.name }} + } + + } @else { +
    -
    + } + } @else { + + Tags + + @for (tag of tagsSelected(); track tag.id) { + + {{ tag.name }} + + + } + + + + @for (tag of filteredOptions | async; track tag.id) { + + {{ tag.name }} + + } + + @if (hasPermissionToCreateTag && tagInputControl.value) { + + + + Create "{{ + tagInputControl.value.trim() + }}" + + + } + + + } +
    +
    diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.scss b/libs/ui/src/lib/tags-selector/tags-selector.component.scss new file mode 100644 index 000000000..5d4e87f30 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts b/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts new file mode 100644 index 000000000..42fb68876 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts @@ -0,0 +1,96 @@ +import { CommonModule } from '@angular/common'; +import '@angular/localize/init'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { Meta, moduleMetadata, StoryObj } from '@storybook/angular'; + +import { GfTagsSelectorComponent } from './tags-selector.component'; + +export default { + title: 'Tags Selector', + component: GfTagsSelectorComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, NoopAnimationsModule] + }) + ] +} as Meta; + +type Story = StoryObj; + +const OPTIONS = [ + { + id: '3ef7e6d9-4598-4eb2-b0e8-00e61cfc0ea6', + name: 'Gambling', + userId: 'c6a71541-d0e3-4e22-ae83-b5e5611b6695' + }, + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + }, + { + id: 'RETIREMENT_FUND', + name: 'Retirement Fund', + userId: null + } +]; + +export const Default: Story = { + args: { + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const CreateCustomTags: Story = { + args: { + hasPermissionToCreateTag: true, + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const Readonly: Story = { + args: { + readonly: true, + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + }, + { + id: 'RETIREMENT_FUND', + name: 'Retirement Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const WithoutValue: Story = { + args: { + tags: [], + tagsAvailable: OPTIONS + } +}; + +export const WithoutOptions: Story = { + args: { + tags: [], + tagsAvailable: [] + } +}; diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.ts b/libs/ui/src/lib/tags-selector/tags-selector.component.ts new file mode 100644 index 000000000..50faab651 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.ts @@ -0,0 +1,139 @@ +import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + CUSTOM_ELEMENTS_SCHEMA, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + signal, + ViewChild +} from '@angular/core'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { + MatAutocompleteModule, + MatAutocompleteSelectedEvent +} from '@angular/material/autocomplete'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { IonIcon } from '@ionic/angular/standalone'; +import { Tag } from '@prisma/client'; +import { addIcons } from 'ionicons'; +import { addCircleOutline, closeOutline } from 'ionicons/icons'; +import { BehaviorSubject, Subject, takeUntil } from 'rxjs'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + FormsModule, + IonIcon, + MatAutocompleteModule, + MatChipsModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-tags-selector', + styleUrls: ['./tags-selector.component.scss'], + templateUrl: 'tags-selector.component.html' +}) +export class GfTagsSelectorComponent implements OnInit, OnChanges, OnDestroy { + @Input() hasPermissionToCreateTag = false; + @Input() readonly = false; + @Input() tags: Tag[]; + @Input() tagsAvailable: Tag[]; + + @Output() tagsChanged = new EventEmitter(); + + @ViewChild('tagInput') tagInput: ElementRef; + + public filteredOptions: Subject = new BehaviorSubject([]); + public readonly separatorKeysCodes: number[] = [COMMA, ENTER]; + public readonly tagInputControl = new FormControl(''); + public readonly tagsSelected = signal([]); + + private unsubscribeSubject = new Subject(); + + public constructor() { + this.tagInputControl.valueChanges + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((value) => { + this.filteredOptions.next(this.filterTags(value)); + }); + + addIcons({ addCircleOutline, closeOutline }); + } + + public ngOnInit() { + this.tagsSelected.set(this.tags); + this.updateFilters(); + } + + public ngOnChanges() { + this.tagsSelected.set(this.tags); + this.updateFilters(); + } + + public onAddTag(event: MatAutocompleteSelectedEvent) { + let tag = this.tagsAvailable.find(({ id }) => { + return id === event.option.value; + }); + + if (!tag && this.hasPermissionToCreateTag) { + tag = { + id: undefined, + name: event.option.value as string, + userId: null + }; + } + + this.tagsSelected.update((tags) => { + return [...(tags ?? []), tag]; + }); + + this.tagsChanged.emit(this.tagsSelected()); + this.tagInput.nativeElement.value = ''; + this.tagInputControl.setValue(undefined); + } + + public onRemoveTag(tag: Tag) { + this.tagsSelected.update((tags) => { + return tags.filter(({ id }) => { + return id !== tag.id; + }); + }); + + this.tagsChanged.emit(this.tagsSelected()); + this.updateFilters(); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private filterTags(query: string = ''): Tag[] { + const tags = this.tagsSelected() ?? []; + const tagIds = tags.map(({ id }) => { + return id; + }); + + return this.tagsAvailable.filter(({ id, name }) => { + return ( + !tagIds.includes(id) && name.toLowerCase().includes(query.toLowerCase()) + ); + }); + } + + private updateFilters() { + this.filteredOptions.next(this.filterTags()); + } +} diff --git a/libs/ui/src/lib/toggle/index.ts b/libs/ui/src/lib/toggle/index.ts new file mode 100644 index 000000000..251899391 --- /dev/null +++ b/libs/ui/src/lib/toggle/index.ts @@ -0,0 +1 @@ +export * from './toggle.component'; diff --git a/apps/client/src/app/components/toggle/toggle.component.html b/libs/ui/src/lib/toggle/toggle.component.html similarity index 100% rename from apps/client/src/app/components/toggle/toggle.component.html rename to libs/ui/src/lib/toggle/toggle.component.html diff --git a/apps/client/src/app/components/toggle/toggle.component.scss b/libs/ui/src/lib/toggle/toggle.component.scss similarity index 93% rename from apps/client/src/app/components/toggle/toggle.component.scss rename to libs/ui/src/lib/toggle/toggle.component.scss index b61a02865..24d1a2975 100644 --- a/apps/client/src/app/components/toggle/toggle.component.scss +++ b/libs/ui/src/lib/toggle/toggle.component.scss @@ -4,7 +4,6 @@ .mat-mdc-radio-button { border-radius: 1rem; margin: 0 0.25rem; - padding: 0.15rem 0.75rem; &.mat-mdc-radio-checked { background-color: rgba(var(--dark-dividers)); @@ -19,7 +18,7 @@ color: rgba(var(--dark-primary-text), 1); cursor: inherit; margin: 0; - padding: 0; + padding: 0.15rem 0.75rem; } } } diff --git a/libs/ui/src/lib/toggle/toggle.component.stories.ts b/libs/ui/src/lib/toggle/toggle.component.stories.ts new file mode 100644 index 000000000..36468ea3c --- /dev/null +++ b/libs/ui/src/lib/toggle/toggle.component.stories.ts @@ -0,0 +1,33 @@ +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule } from '@angular/forms'; +import { MatRadioModule } from '@angular/material/radio'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; + +import { GfToggleComponent } from './toggle.component'; + +export default { + title: 'Toggle', + component: GfToggleComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, MatRadioModule, ReactiveFormsModule] + }) + ] +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + defaultValue: '1d', + isLoading: false, + options: [ + { label: 'Today', value: '1d' }, + { label: 'YTD', value: 'ytd' }, + { label: '1Y', value: '1y' }, + { label: '5Y', value: '5y' }, + { label: 'Max', value: 'max' } + ] + } +}; diff --git a/libs/ui/src/lib/toggle/toggle.component.ts b/libs/ui/src/lib/toggle/toggle.component.ts new file mode 100644 index 000000000..be460f7fa --- /dev/null +++ b/libs/ui/src/lib/toggle/toggle.component.ts @@ -0,0 +1,38 @@ +import { ToggleOption } from '@ghostfolio/common/interfaces'; + +import { CommonModule } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnChanges, + Output +} from '@angular/core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { MatRadioModule } from '@angular/material/radio'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CommonModule, MatRadioModule, ReactiveFormsModule], + selector: 'gf-toggle', + styleUrls: ['./toggle.component.scss'], + templateUrl: './toggle.component.html' +}) +export class GfToggleComponent implements OnChanges { + @Input() defaultValue: string; + @Input() isLoading: boolean; + @Input() options: ToggleOption[] = []; + + @Output() valueChange = new EventEmitter>(); + + public optionFormControl = new FormControl(undefined); + + public ngOnChanges() { + this.optionFormControl.setValue(this.defaultValue); + } + + public onValueChange() { + this.valueChange.emit({ value: this.optionFormControl.value }); + } +} diff --git a/libs/ui/src/lib/top-holdings/top-holdings.component.html b/libs/ui/src/lib/top-holdings/top-holdings.component.html index d42d742b2..7a2a84126 100644 --- a/libs/ui/src/lib/top-holdings/top-holdings.component.html +++ b/libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -36,7 +36,7 @@ - + Allocation % diff --git a/libs/ui/src/lib/top-holdings/top-holdings.component.ts b/libs/ui/src/lib/top-holdings/top-holdings.component.ts index 13ceb239c..b4ebf4c8c 100644 --- a/libs/ui/src/lib/top-holdings/top-holdings.component.ts +++ b/libs/ui/src/lib/top-holdings/top-holdings.component.ts @@ -2,10 +2,8 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, - HoldingWithParents, - PortfolioPosition + HoldingWithParents } from '@ghostfolio/common/interfaces'; -import { GfValueComponent } from '@ghostfolio/ui/value'; import { animate, @@ -29,10 +27,11 @@ import { import { MatButtonModule } from '@angular/material/button'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; -import { DataSource } from '@prisma/client'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; +import { GfValueComponent } from '../value/value.component'; + @Component({ animations: [ trigger('detailExpand', [ @@ -64,13 +63,6 @@ export class GfTopHoldingsComponent implements OnChanges, OnDestroy { @Input() locale = getLocale(); @Input() pageSize = Number.MAX_SAFE_INTEGER; @Input() topHoldings: HoldingWithParents[]; - @Input() positions: { - [symbol: string]: Pick & { - dataSource?: DataSource; - name: string; - value: number; - }; - } = {}; @Output() holdingClicked = new EventEmitter(); diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts new file mode 100644 index 000000000..2000b4f98 --- /dev/null +++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts @@ -0,0 +1,392 @@ +import { CommonModule } from '@angular/common'; +import '@angular/localize/init'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; + +import { GfTreemapChartComponent } from './treemap-chart.component'; + +export default { + title: 'Treemap Chart', + component: GfTreemapChartComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, NgxSkeletonLoaderModule] + }) + ], + argTypes: { + colorScheme: { + control: { + type: 'select' + }, + options: ['DARK', 'LIGHT'] + }, + cursor: { + control: { + type: 'select' + }, + options: ['', 'pointer'] + } + } +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + baseCurrency: 'USD', + colorScheme: 'LIGHT', + cursor: undefined, + dateRange: 'mtd', + holdings: [ + { + allocationInPercentage: 0.042990776363386086, + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [], + currency: 'USD', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2021-12-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 3856, + grossPerformancePercent: 0.46047289228564603, + grossPerformancePercentWithCurrencyEffect: 0.46047289228564603, + grossPerformanceWithCurrencyEffect: 3856, + holdings: [], + investment: 8374, + marketPrice: 244.6, + name: 'Apple Inc', + netPerformance: 3855, + netPerformancePercent: 0.460353475041796, + netPerformancePercentWithCurrencyEffect: 0.036440677966101696, + netPerformanceWithCurrencyEffect: 430, + quantity: 50, + sectors: [], + symbol: 'AAPL', + tags: [], + transactionCount: 1, + url: 'https://www.apple.com', + valueInBaseCurrency: 12230 + }, + { + allocationInPercentage: 0.02377401948293552, + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [], + currency: 'EUR', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2021-04-23T00:00:00.000Z'), + dividend: 192, + grossPerformance: 2226.700251889169, + grossPerformancePercent: 0.49083842309827874, + grossPerformancePercentWithCurrencyEffect: 0.29306136948826367, + grossPerformanceWithCurrencyEffect: 1532.8272791336772, + holdings: [], + investment: 4536.523929471033, + marketPrice: 322.2, + name: 'Allianz SE', + netPerformance: 2222.2921914357685, + netPerformancePercent: 0.48986674069961134, + netPerformancePercentWithCurrencyEffect: 0.034489367670592026, + netPerformanceWithCurrencyEffect: 225.48257403052068, + quantity: 20, + sectors: [], + symbol: 'ALV.DE', + tags: [], + transactionCount: 2, + url: 'https://www.allianz.com', + valueInBaseCurrency: 6763.224181360202 + }, + { + allocationInPercentage: 0.08038536990007467, + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [], + currency: 'USD', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2018-10-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 12758.05, + grossPerformancePercent: 1.2619300787837724, + grossPerformancePercentWithCurrencyEffect: 1.2619300787837724, + grossPerformanceWithCurrencyEffect: 12758.05, + holdings: [], + investment: 10109.95, + marketPrice: 228.68, + name: 'Amazon.com, Inc.', + netPerformance: 12677.26, + netPerformancePercent: 1.253938941339967, + netPerformancePercentWithCurrencyEffect: -0.037866008722316276, + netPerformanceWithCurrencyEffect: -899.99926757812, + quantity: 100, + sectors: [], + symbol: 'AMZN', + tags: [], + transactionCount: 1, + url: 'https://www.aboutamazon.com', + valueInBaseCurrency: 22868 + }, + { + allocationInPercentage: 0.19216416482928922, + assetClass: 'LIQUIDITY', + assetSubClass: 'CRYPTOCURRENCY', + countries: [], + currency: 'USD', + dataSource: 'COINGECKO', + dateOfFirstActivity: new Date('2017-08-16T00:00:00.000Z'), + dividend: 0, + grossPerformance: 52666.7898248, + grossPerformancePercent: 26.333394912400003, + grossPerformancePercentWithCurrencyEffect: 26.333394912400003, + grossPerformanceWithCurrencyEffect: 52666.7898248, + holdings: [], + investment: 1999.9999999999998, + marketPrice: 97364, + name: 'Bitcoin', + netPerformance: 52636.8898248, + netPerformancePercent: 26.3184449124, + netPerformancePercentWithCurrencyEffect: -0.04760906442310894, + netPerformanceWithCurrencyEffect: -2732.737808972287, + quantity: 0.5614682, + sectors: [], + symbol: 'bitcoin', + tags: [], + transactionCount: 1, + url: null, + valueInBaseCurrency: 54666.7898248 + }, + { + allocationInPercentage: 0.007378652850073097, + assetClass: 'FIXED_INCOME', + assetSubClass: 'BOND', + countries: [], + currency: 'EUR', + dataSource: 'MANUAL', + dateOfFirstActivity: new Date('2021-02-01T00:00:00.000Z'), + dividend: 11.45, + grossPerformance: 0, + grossPerformancePercent: 0, + grossPerformancePercentWithCurrencyEffect: -0.1247202380342517, + grossPerformanceWithCurrencyEffect: -258.2576430160448, + holdings: [], + investment: 2099.0764063811926, + marketPrice: 1, + name: 'Bondora Go & Grow', + netPerformance: 0, + netPerformancePercent: 0, + netPerformancePercentWithCurrencyEffect: 0.009445843828715519, + netPerformanceWithCurrencyEffect: 19.6420125363184, + quantity: 2000, + sectors: [], + symbol: 'BONDORA_GO_AND_GROW', + tags: [], + transactionCount: 5, + url: null, + valueInBaseCurrency: 2099.0764063811926 + }, + { + allocationInPercentage: 0.07787531695543741, + assetClass: 'EQUITY', + assetSubClass: 'ETF', + countries: [], + currency: 'CHF', + dataSource: 'MANUAL', + dateOfFirstActivity: new Date('2021-04-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 4550.843985045582, + grossPerformancePercent: 0.3631417324494093, + grossPerformancePercentWithCurrencyEffect: 0.42037247857285137, + grossPerformanceWithCurrencyEffect: 5107.057936556927, + holdings: [], + investment: 17603.097090932337, + marketPrice: 188.22, + name: 'frankly Extreme 95 Index', + netPerformance: 4550.843985045582, + netPerformancePercent: 0.3631417324494093, + netPerformancePercentWithCurrencyEffect: 0.026190604904358043, + netPerformanceWithCurrencyEffect: 565.4165171873152, + quantity: 105.87328656807, + sectors: [], + symbol: 'FRANKLY95P', + tags: [], + transactionCount: 6, + url: 'https://www.frankly.ch', + valueInBaseCurrency: 22153.941075977917 + }, + { + allocationInPercentage: 0.04307127421937313, + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [], + currency: 'USD', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2023-01-03T00:00:00.000Z'), + dividend: 0, + grossPerformance: 5065.5, + grossPerformancePercent: 0.7047750229568411, + grossPerformancePercentWithCurrencyEffect: 0.7047750229568411, + grossPerformanceWithCurrencyEffect: 5065.5, + holdings: [], + investment: 7187.4, + marketPrice: 408.43, + name: 'Microsoft Corporation', + netPerformance: 5065.5, + netPerformancePercent: 0.7047750229568411, + netPerformancePercentWithCurrencyEffect: -0.015973588391056275, + netPerformanceWithCurrencyEffect: -198.899926757814, + quantity: 30, + sectors: [], + symbol: 'MSFT', + tags: [], + transactionCount: 1, + url: 'https://www.microsoft.com', + valueInBaseCurrency: 12252.9 + }, + { + allocationInPercentage: 0.18762679306394897, + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [], + currency: 'USD', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2017-01-03T00:00:00.000Z'), + dividend: 0, + grossPerformance: 51227.500000005, + grossPerformancePercent: 23.843379101756675, + grossPerformancePercentWithCurrencyEffect: 23.843379101756675, + grossPerformanceWithCurrencyEffect: 51227.500000005, + holdings: [], + investment: 2148.499999995, + marketPrice: 355.84, + name: 'Tesla, Inc.', + netPerformance: 51197.500000005, + netPerformancePercent: 23.829415871596066, + netPerformancePercentWithCurrencyEffect: -0.12051410125545206, + netPerformanceWithCurrencyEffect: -7314.00091552734, + quantity: 150, + sectors: [], + symbol: 'TSLA', + tags: [], + transactionCount: 1, + url: 'https://www.tesla.com', + valueInBaseCurrency: 53376 + }, + { + allocationInPercentage: 0.053051250766657634, + assetClass: 'EQUITY', + assetSubClass: 'ETF', + countries: [], + currency: 'USD', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2019-03-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 6845.8, + grossPerformancePercent: 1.0164758094605268, + grossPerformancePercentWithCurrencyEffect: 1.0164758094605268, + grossPerformanceWithCurrencyEffect: 6845.8, + holdings: [], + investment: 8246.2, + marketPrice: 301.84, + name: 'Vanguard Total Stock Market Index Fund ETF Shares', + netPerformance: 6746.3, + netPerformancePercent: 1.0017018833976383, + netPerformancePercentWithCurrencyEffect: 0.01085061564051406, + netPerformanceWithCurrencyEffect: 161.99969482422, + quantity: 50, + sectors: [], + symbol: 'VTI', + tags: [], + transactionCount: 5, + url: 'https://www.vanguard.com', + valueInBaseCurrency: 15092 + }, + { + allocationInPercentage: 0.0836576192450555, + assetClass: 'EQUITY', + assetSubClass: 'ETF', + countries: [], + currency: 'CHF', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2018-03-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 6462.42356864925, + grossPerformancePercent: 0.5463044783973836, + grossPerformancePercentWithCurrencyEffect: 0.6282343505275325, + grossPerformanceWithCurrencyEffect: 7121.935580698947, + holdings: [], + investment: 17336.464702612564, + marketPrice: 129.74, + name: 'Vanguard FTSE All-World UCITS ETF', + netPerformance: 6373.040578098944, + netPerformancePercent: 0.5387484388540966, + netPerformancePercentWithCurrencyEffect: 0.008409682389650015, + netPerformanceWithCurrencyEffect: 198.47200506226807, + quantity: 165, + sectors: [], + symbol: 'VWRL.SW', + tags: [], + transactionCount: 5, + url: 'https://www.vanguard.com', + valueInBaseCurrency: 23798.888271261814 + }, + { + allocationInPercentage: 0.03265192235898284, + assetClass: 'EQUITY', + assetSubClass: 'ETF', + countries: [], + currency: 'EUR', + dataSource: 'YAHOO', + dateOfFirstActivity: new Date('2021-08-19T00:00:00.000Z'), + dividend: 0, + grossPerformance: 3112.7991183879094, + grossPerformancePercent: 0.5040147846036197, + grossPerformancePercentWithCurrencyEffect: 0.3516875105542396, + grossPerformanceWithCurrencyEffect: 2416.799201046856, + holdings: [], + investment: 6176.007556675063, + marketPrice: 118.005, + name: 'Xtrackers MSCI World UCITS ETF 1C', + netPerformance: 3081.4179261125105, + netPerformancePercent: 0.4989336392216841, + netPerformancePercentWithCurrencyEffect: 0.006460676966633529, + netPerformanceWithCurrencyEffect: 59.626750161726044, + quantity: 75, + sectors: [], + symbol: 'XDWD.DE', + tags: [], + transactionCount: 1, + url: null, + valueInBaseCurrency: 9288.806675062973 + }, + { + allocationInPercentage: 0.17537283996478595, + assetClass: 'LIQUIDITY', + assetSubClass: 'CASH', + countries: [], + currency: 'USD', + dataSource: 'MANUAL', + dateOfFirstActivity: new Date('2021-04-01T00:00:00.000Z'), + dividend: 0, + grossPerformance: 0, + grossPerformancePercent: 0, + grossPerformancePercentWithCurrencyEffect: 0, + grossPerformanceWithCurrencyEffect: 0, + holdings: [], + investment: 49890, + marketPrice: 0, + name: 'USD', + netPerformance: 0, + netPerformancePercent: 0, + netPerformancePercentWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, + quantity: 0, + sectors: [], + symbol: 'USD', + tags: [], + transactionCount: 0, + valueInBaseCurrency: 49890 + } + ], + locale: 'en-US' + } +}; diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts index 11ee026f5..4e06d49cc 100644 --- a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts +++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -29,6 +29,7 @@ import { ChartConfiguration } from 'chart.js'; import { LinearScale } from 'chart.js'; import { Chart, Tooltip } from 'chart.js'; import { TreemapController, TreemapElement } from 'chartjs-chart-treemap'; +import { isUUID } from 'class-validator'; import { differenceInDays, max } from 'date-fns'; import { orderBy } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @@ -196,21 +197,21 @@ export class GfTreemapChartComponent min: Math.min(...negativeNetPerformancePercents) }; - const data: ChartConfiguration['data'] = { + const data: ChartConfiguration<'treemap'>['data'] = { datasets: [ { - backgroundColor: (ctx) => { + backgroundColor: (context) => { let annualizedNetPerformancePercent = getAnnualizedPerformancePercent({ daysInMarket: differenceInDays( endDate, max([ - ctx.raw._data.dateOfFirstActivity ?? new Date(0), + context.raw._data.dateOfFirstActivity ?? new Date(0), startDate ]) ), netPerformancePercentage: new Big( - ctx.raw._data.netPerformancePercentWithCurrencyEffect + context.raw._data.netPerformancePercentWithCurrencyEffect ) }).toNumber(); @@ -230,18 +231,18 @@ export class GfTreemapChartComponent key: 'allocationInPercentage', labels: { align: 'left', - color: (ctx) => { + color: (context) => { let annualizedNetPerformancePercent = getAnnualizedPerformancePercent({ daysInMarket: differenceInDays( endDate, max([ - ctx.raw._data.dateOfFirstActivity ?? new Date(0), + context.raw._data.dateOfFirstActivity ?? new Date(0), startDate ]) ), netPerformancePercentage: new Big( - ctx.raw._data.netPerformancePercentWithCurrencyEffect + context.raw._data.netPerformancePercentWithCurrencyEffect ) }).toNumber(); @@ -259,11 +260,11 @@ export class GfTreemapChartComponent }, display: true, font: [{ size: 16 }, { lineHeight: 1.5, size: 14 }], - formatter: (ctx) => { + formatter: ({ raw }) => { // Round to 4 decimal places let netPerformancePercentWithCurrencyEffect = Math.round( - ctx.raw._data.netPerformancePercentWithCurrencyEffect * 10000 + raw._data.netPerformancePercentWithCurrencyEffect * 10000 ) / 10000; if (Math.abs(netPerformancePercentWithCurrencyEffect) === 0) { @@ -272,8 +273,11 @@ export class GfTreemapChartComponent ); } + const name = raw._data.name; + const symbol = raw._data.symbol; + return [ - ctx.raw._data.symbol, + isUUID(symbol) ? (name ?? symbol) : symbol, `${netPerformancePercentWithCurrencyEffect > 0 ? '+' : ''}${(netPerformancePercentWithCurrencyEffect * 100).toFixed(2)}%` ]; }, @@ -341,25 +345,41 @@ export class GfTreemapChartComponent locale: this.locale }), callbacks: { - label: (context) => { - const name = context.raw._data.name; - const symbol = context.raw._data.symbol; + label: ({ raw }) => { + const allocationInPercentage = `${((raw._data.allocationInPercentage as number) * 100).toFixed(2)}%`; + const name = raw._data.name; + const sign = + raw._data.netPerformancePercentWithCurrencyEffect > 0 ? '+' : ''; + const symbol = raw._data.symbol; + + const netPerformanceInPercentageWithSign = `${sign}${(raw._data.netPerformancePercentWithCurrencyEffect * 100).toFixed(2)}%`; - if (context.raw._data.valueInBaseCurrency !== null) { - const value = context.raw._data.valueInBaseCurrency as number; + if (raw._data.valueInBaseCurrency !== null) { + const value = raw._data.valueInBaseCurrency as number; return [ - `${name ?? symbol}`, + `${name ?? symbol} (${allocationInPercentage})`, `${value.toLocaleString(this.locale, { maximumFractionDigits: 2, minimumFractionDigits: 2 - })} ${this.baseCurrency}` + })} ${this.baseCurrency}`, + '', + $localize`Change` + ' (' + $localize`Performance` + ')', + `${sign}${raw._data.netPerformanceWithCurrencyEffect.toLocaleString( + this.locale, + { + maximumFractionDigits: 2, + minimumFractionDigits: 2 + } + )} ${this.baseCurrency} (${netPerformanceInPercentageWithSign})` ]; } else { - const percentage = - (context.raw._data.allocationInPercentage as number) * 100; - - return [`${name ?? symbol}`, `${percentage.toFixed(2)}%`]; + return [ + `${name ?? symbol} (${allocationInPercentage})`, + '', + $localize`Performance`, + netPerformanceInPercentageWithSign + ]; } }, title: () => { diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.component.stories.ts b/libs/ui/src/lib/trend-indicator/trend-indicator.component.stories.ts index 0d8438706..1db9e2995 100644 --- a/libs/ui/src/lib/trend-indicator/trend-indicator.component.stories.ts +++ b/libs/ui/src/lib/trend-indicator/trend-indicator.component.stories.ts @@ -1,50 +1,53 @@ -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { TrendIndicatorComponent } from './trend-indicator.component'; +import { GfTrendIndicatorComponent } from './trend-indicator.component'; export default { title: 'Trend Indicator', - component: TrendIndicatorComponent, + component: GfTrendIndicatorComponent, decorators: [ moduleMetadata({ imports: [NgxSkeletonLoaderModule] }) ] -} as Meta; +} as Meta; -const Template: Story = ( - args: TrendIndicatorComponent -) => ({ - props: args -}); +type Story = StoryObj; -export const Loading = Template.bind({}); -Loading.args = { - isLoading: true +export const Loading: Story = { + args: { + isLoading: true + } }; -export const Default = Template.bind({}); -Default.args = {}; +export const Default: Story = { + args: {} +}; -export const Delayed = Template.bind({}); -Delayed.args = { - marketState: 'delayed', - range: '1d' +export const Delayed: Story = { + args: { + dateRange: '1d', + marketState: 'delayed' + } }; -export const Down = Template.bind({}); -Down.args = { - value: -1 +export const Down: Story = { + args: { + value: -1 + } }; -export const Up = Template.bind({}); -Up.args = { - value: 1 +export const Up: Story = { + args: { + value: 1 + } }; -export const MarketClosed = Template.bind({}); -MarketClosed.args = { - marketState: 'closed', - range: '1d' +export const MarketClosed: Story = { + args: { + dateRange: '1d', + marketState: 'closed' + } }; diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts index e44c41aa9..1e49b4a6c 100644 --- a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts +++ b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts @@ -1,17 +1,25 @@ import { DateRange, MarketState } from '@ghostfolio/common/types'; -import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + arrowDownCircleOutline, + arrowForwardCircleOutline, + arrowUpCircleOutline, + pauseCircleOutline, + timeOutline +} from 'ionicons/icons'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, NgxSkeletonLoaderModule], + imports: [IonIcon, NgxSkeletonLoaderModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-trend-indicator', styleUrls: ['./trend-indicator.component.scss'], @@ -23,4 +31,14 @@ export class GfTrendIndicatorComponent { @Input() marketState: MarketState = 'open'; @Input() size: 'large' | 'medium' | 'small' = 'small'; @Input() value = 0; + + public constructor() { + addIcons({ + arrowDownCircleOutline, + arrowForwardCircleOutline, + arrowUpCircleOutline, + pauseCircleOutline, + timeOutline + }); + } } diff --git a/libs/ui/src/lib/value/value.component.html b/libs/ui/src/lib/value/value.component.html index a691c54e8..1f61f30e5 100644 --- a/libs/ui/src/lib/value/value.component.html +++ b/libs/ui/src/lib/value/value.component.html @@ -1,54 +1,66 @@ -
    - -
    +@if (icon) { +
    + +
    +}
    - + @if (value || value === 0 || value === null) {
    - - -
    +
    -
    -
    -
    -
    - @if (value === null) { - *****% - } @else { - {{ formattedValue }}% + @if (isNumber || value === null) { + @if (colorizeSign && !useAbsoluteValue) { + @if (+value > 0) { +
    +
    } -
    -
    - @if (value === null) { - ***** + @if (+value < 0) { +
    -
    + } + } + @if (isPercent) { +
    + @if (value === null) { + *****% + } @else { + {{ formattedValue }}% + } +
    + } @else { +
    + @if (value === null) { + ***** + } @else { + {{ formattedValue }} + } +
    + } + @if (unit) { + @if (size === 'medium') { + + {{ unit }} + } @else { - {{ formattedValue }} +
    + {{ unit }} +
    } -
    - - {{ unit }} - -
    - {{ unit }} -
    -
    - + } + } + @if (isString) {
    + @if (value === undefined) { + + } - -
    + @if (size === 'large') { +
    - {{ subLabel }} + @if (subLabel) { + {{ subLabel }} + }
    - + } @else { + - + }
    diff --git a/libs/ui/src/lib/value/value.component.stories.ts b/libs/ui/src/lib/value/value.component.stories.ts index fc3e202ea..ff9f5a259 100644 --- a/libs/ui/src/lib/value/value.component.stories.ts +++ b/libs/ui/src/lib/value/value.component.stories.ts @@ -1,71 +1,77 @@ -import { Meta, Story, moduleMetadata } from '@storybook/angular'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { ValueComponent } from './value.component'; +import { GfValueComponent } from './value.component'; export default { title: 'Value', - component: ValueComponent, + component: GfValueComponent, decorators: [ moduleMetadata({ imports: [NgxSkeletonLoaderModule] }) ] -} as Meta; +} as Meta; -const Template: Story = (args: ValueComponent) => ({ - props: args -}); +type Story = StoryObj; -export const Loading = Template.bind({}); -Loading.args = { - value: undefined +export const Loading: Story = { + args: { + value: undefined + } }; -export const Currency = Template.bind({}); -Currency.args = { - isCurrency: true, - locale: 'en-US', - unit: 'USD', - value: 7 +export const Currency: Story = { + args: { + isCurrency: true, + locale: 'en-US', + unit: 'USD', + value: 7 + } }; -export const Label = Template.bind({}); -Label.args = { - locale: 'en-US', - value: 7.25 +export const Label: Story = { + args: { + locale: 'en-US', + value: 7.25 + } }; -export const PerformancePositive = Template.bind({}); -PerformancePositive.args = { - locale: 'en-US', - colorizeSign: true, - isPercent: true, - value: 0.0136810853673890378 +export const PerformancePositive: Story = { + args: { + colorizeSign: true, + isPercent: true, + locale: 'en-US', + value: 0.0136810853673890378 + }, + name: 'Performance (positive)' }; -PerformancePositive.storyName = 'Performance (positive)'; -export const PerformanceNegative = Template.bind({}); -PerformanceNegative.args = { - locale: 'en-US', - colorizeSign: true, - isPercent: true, - value: -0.0136810853673890378 +export const PerformanceNegative: Story = { + args: { + colorizeSign: true, + isPercent: true, + locale: 'en-US', + value: -0.0136810853673890378 + }, + name: 'Performance (negative)' }; -PerformanceNegative.storyName = 'Performance (negative)'; -export const PerformanceCloseToZero = Template.bind({}); -PerformanceCloseToZero.args = { - locale: 'en-US', - colorizeSign: true, - isPercent: true, - value: -2.388915360475e-8 +export const PerformanceCloseToZero: Story = { + args: { + colorizeSign: true, + isPercent: true, + locale: 'en-US', + value: -2.388915360475e-8 + }, + name: 'Performance (negative zero)' }; -PerformanceCloseToZero.storyName = 'Performance (negative zero)'; -export const Precision = Template.bind({}); -Precision.args = { - locale: 'en-US', - precision: 3, - value: 7.2534802394809285309 +export const Precision: Story = { + args: { + locale: 'en-US', + precision: 3, + value: 7.2534802394809285309 + } }; diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index d93c5fbcb..55672bacf 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -8,12 +8,13 @@ import { Input, OnChanges } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; import { isNumber } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, NgxSkeletonLoaderModule], + imports: [CommonModule, IonIcon, NgxSkeletonLoaderModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-value', styleUrls: ['./value.component.scss'], @@ -47,7 +48,7 @@ export class GfValueComponent implements OnChanges { if (isNumber(this.value)) { this.isNumber = true; this.isString = false; - this.absoluteValue = Math.abs(this.value as number); + this.absoluteValue = Math.abs(this.value); if (this.colorizeSign) { if (this.isCurrency) { diff --git a/nx.json b/nx.json index e39b5dd23..9b6540fdb 100644 --- a/nx.json +++ b/nx.json @@ -10,8 +10,61 @@ "linter": "eslint", "unitTestRunner": "jest" }, - "@nx/angular:component": {}, - "@nx/nest": {} + "@nx/angular:component": { + "type": "component" + }, + "@nx/nest": {}, + "@schematics/angular:component": { + "type": "component" + }, + "@nx/angular:directive": { + "type": "directive" + }, + "@schematics/angular:directive": { + "type": "directive" + }, + "@nx/angular:service": { + "type": "service" + }, + "@schematics/angular:service": { + "type": "service" + }, + "@nx/angular:scam": { + "type": "component" + }, + "@nx/angular:scam-directive": { + "type": "directive" + }, + "@nx/angular:guard": { + "typeSeparator": "." + }, + "@schematics/angular:guard": { + "typeSeparator": "." + }, + "@nx/angular:interceptor": { + "typeSeparator": "." + }, + "@schematics/angular:interceptor": { + "typeSeparator": "." + }, + "@nx/angular:module": { + "typeSeparator": "." + }, + "@schematics/angular:module": { + "typeSeparator": "." + }, + "@nx/angular:pipe": { + "typeSeparator": "." + }, + "@schematics/angular:pipe": { + "typeSeparator": "." + }, + "@nx/angular:resolver": { + "typeSeparator": "." + }, + "@schematics/angular:resolver": { + "typeSeparator": "." + } }, "$schema": "./node_modules/nx/schemas/nx-schema.json", "targetDefaults": { @@ -63,6 +116,7 @@ "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", "!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)", "!{projectRoot}/.storybook/**/*", + "!{projectRoot}/eslint.config.cjs", "!{projectRoot}/jest.config.[jt]s", "!{projectRoot}/src/test-setup.[jt]s", "!{projectRoot}/tsconfig.storybook.json", @@ -71,6 +125,5 @@ ] }, "parallel": 1, - "defaultBase": "origin/main", - "useLegacyCache": true + "defaultBase": "origin/main" } diff --git a/package-lock.json b/package-lock.json index 305bcb27c..992c5fa56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,178 +1,441 @@ { "name": "ghostfolio", - "version": "2.132.0", + "version": "2.186.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.132.0", + "version": "2.186.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { - "@angular/animations": "19.0.5", - "@angular/cdk": "19.0.4", - "@angular/common": "19.0.5", - "@angular/compiler": "19.0.5", - "@angular/core": "19.0.5", - "@angular/forms": "19.0.5", - "@angular/material": "19.0.4", - "@angular/platform-browser": "19.0.5", - "@angular/platform-browser-dynamic": "19.0.5", - "@angular/router": "19.0.5", - "@angular/service-worker": "19.0.5", + "@angular/animations": "20.1.3", + "@angular/cdk": "20.1.3", + "@angular/common": "20.1.3", + "@angular/compiler": "20.1.3", + "@angular/core": "20.1.3", + "@angular/forms": "20.1.3", + "@angular/material": "20.1.3", + "@angular/platform-browser": "20.1.3", + "@angular/platform-browser-dynamic": "20.1.3", + "@angular/router": "20.1.3", + "@angular/service-worker": "20.1.3", "@codewithdan/observable-store": "2.2.15", + "@date-fns/utc": "2.1.0", "@dfinity/agent": "0.15.7", "@dfinity/auth-client": "0.15.7", "@dfinity/candid": "0.15.7", "@dfinity/identity": "0.15.7", "@dfinity/principal": "0.15.7", "@dinero.js/currencies": "2.0.0-alpha.8", - "@internationalized/number": "3.6.0", - "@nestjs/bull": "10.0.1", - "@nestjs/cache-manager": "2.2.2", - "@nestjs/common": "10.1.3", - "@nestjs/config": "3.0.0", - "@nestjs/core": "10.1.3", - "@nestjs/event-emitter": "2.0.4", - "@nestjs/jwt": "10.1.0", - "@nestjs/passport": "10.0.3", - "@nestjs/platform-express": "10.1.3", - "@nestjs/schedule": "3.0.2", - "@nestjs/serve-static": "4.0.0", - "@prisma/client": "6.1.0", - "@simplewebauthn/browser": "9.0.1", - "@simplewebauthn/server": "9.0.3", - "@stripe/stripe-js": "5.4.0", + "@internationalized/number": "3.6.3", + "@ionic/angular": "8.6.3", + "@keyv/redis": "4.4.0", + "@nestjs/bull": "11.0.2", + "@nestjs/cache-manager": "3.0.1", + "@nestjs/common": "11.1.3", + "@nestjs/config": "4.0.2", + "@nestjs/core": "11.1.3", + "@nestjs/event-emitter": "3.0.1", + "@nestjs/jwt": "11.0.0", + "@nestjs/passport": "11.0.5", + "@nestjs/platform-express": "11.1.3", + "@nestjs/schedule": "6.0.0", + "@nestjs/serve-static": "5.0.3", + "@openrouter/ai-sdk-provider": "0.7.2", + "@prisma/client": "6.12.0", + "@simplewebauthn/browser": "13.1.0", + "@simplewebauthn/server": "13.1.1", + "@stripe/stripe-js": "7.6.1", + "ai": "4.3.16", "alphavantage": "2.2.0", - "big.js": "6.2.2", - "bootstrap": "4.6.0", - "bull": "4.16.2", - "cache-manager": "5.7.6", - "cache-manager-redis-yet": "5.1.4", - "chart.js": "4.2.0", + "big.js": "7.0.1", + "bootstrap": "4.6.2", + "bull": "4.16.5", + "chart.js": "4.4.9", "chartjs-adapter-date-fns": "3.0.0", - "chartjs-chart-treemap": "2.3.1", - "chartjs-plugin-annotation": "2.1.2", + "chartjs-chart-treemap": "3.1.0", + "chartjs-plugin-annotation": "3.1.0", "chartjs-plugin-datalabels": "2.2.0", "cheerio": "1.0.0", "class-transformer": "0.5.1", - "class-validator": "0.14.1", - "color": "4.2.3", - "countries-and-timezones": "3.7.2", + "class-validator": "0.14.2", + "color": "5.0.0", + "countries-and-timezones": "3.8.0", "countries-list": "3.1.1", - "countup.js": "2.8.0", - "date-fns": "3.6.0", - "envalid": "7.3.1", + "countup.js": "2.8.2", + "date-fns": "4.1.0", + "envalid": "8.0.0", + "fuse.js": "7.1.0", "google-spreadsheet": "3.2.0", - "got": "11.8.6", "helmet": "7.0.0", "http-status-codes": "2.3.0", - "ionicons": "7.4.0", + "ionicons": "8.0.10", "jsonpath": "1.1.1", "lodash": "4.17.21", "marked": "15.0.4", "ms": "3.0.0-canary.1", - "ng-extract-i18n-merge": "2.13.1", - "ngx-device-detector": "9.0.0", - "ngx-markdown": "19.0.0", - "ngx-skeleton-loader": "9.0.0", - "ngx-stripe": "19.0.0", + "ng-extract-i18n-merge": "3.0.0", + "ngx-device-detector": "10.0.2", + "ngx-markdown": "20.0.0", + "ngx-skeleton-loader": "11.2.1", + "ngx-stripe": "20.7.0", "open-color": "1.9.1", "papaparse": "5.3.1", "passport": "0.7.0", "passport-google-oauth20": "2.0.0", "passport-headerapikey": "1.2.2", "passport-jwt": "4.0.1", - "reflect-metadata": "0.1.13", - "rxjs": "7.5.6", - "stripe": "17.3.0", - "svgmap": "2.6.0", - "twitter-api-v2": "1.14.2", - "uuid": "11.0.2", - "yahoo-finance2": "2.11.3", - "zone.js": "0.15.0" + "reflect-metadata": "0.2.2", + "rxjs": "7.8.1", + "stripe": "18.3.0", + "svgmap": "2.12.2", + "twitter-api-v2": "1.23.0", + "uuid": "11.1.0", + "yahoo-finance2": "3.4.1", + "zone.js": "0.15.1" }, "devDependencies": { - "@angular-devkit/build-angular": "19.0.6", - "@angular-devkit/core": "19.0.6", - "@angular-devkit/schematics": "19.0.6", - "@angular-eslint/eslint-plugin": "19.0.2", - "@angular-eslint/eslint-plugin-template": "19.0.2", - "@angular-eslint/template-parser": "19.0.2", - "@angular/cli": "19.0.6", - "@angular/compiler-cli": "19.0.5", - "@angular/language-service": "19.0.5", - "@angular/localize": "19.0.5", - "@angular/pwa": "19.0.6", - "@nestjs/schematics": "10.0.1", - "@nestjs/testing": "10.1.3", - "@nx/angular": "20.3.0", - "@nx/cypress": "20.3.0", - "@nx/eslint-plugin": "20.3.0", - "@nx/jest": "20.3.0", - "@nx/js": "20.3.0", - "@nx/module-federation": "20.3.0", - "@nx/nest": "20.3.0", - "@nx/node": "20.3.0", - "@nx/storybook": "20.3.0", - "@nx/web": "20.3.0", - "@nx/workspace": "20.3.0", - "@schematics/angular": "19.0.6", - "@simplewebauthn/types": "9.0.1", - "@storybook/addon-essentials": "8.4.7", - "@storybook/addon-interactions": "8.4.7", - "@storybook/angular": "8.4.7", - "@storybook/core-server": "8.4.7", - "@trivago/prettier-plugin-sort-imports": "4.3.0", + "@angular-devkit/build-angular": "20.1.3", + "@angular-devkit/core": "20.1.3", + "@angular-devkit/schematics": "20.1.3", + "@angular-eslint/eslint-plugin": "20.1.1", + "@angular-eslint/eslint-plugin-template": "20.1.1", + "@angular-eslint/template-parser": "20.1.1", + "@angular/cli": "20.1.3", + "@angular/compiler-cli": "20.1.3", + "@angular/language-service": "20.1.3", + "@angular/localize": "20.1.3", + "@angular/pwa": "20.1.3", + "@eslint/eslintrc": "3.3.1", + "@eslint/js": "9.24.0", + "@nestjs/schematics": "11.0.5", + "@nestjs/testing": "11.1.3", + "@nx/angular": "21.3.9", + "@nx/cypress": "21.3.9", + "@nx/eslint-plugin": "21.3.9", + "@nx/jest": "21.3.9", + "@nx/js": "21.3.9", + "@nx/module-federation": "21.3.9", + "@nx/nest": "21.3.9", + "@nx/node": "21.3.9", + "@nx/storybook": "21.3.9", + "@nx/web": "21.3.9", + "@nx/workspace": "21.3.9", + "@schematics/angular": "20.1.3", + "@storybook/addon-docs": "9.0.17", + "@storybook/angular": "9.0.17", + "@trivago/prettier-plugin-sort-imports": "5.2.2", "@types/big.js": "6.2.2", - "@types/cache-manager": "4.0.6", - "@types/color": "3.0.6", "@types/google-spreadsheet": "3.1.5", "@types/jest": "29.5.13", - "@types/lodash": "4.17.7", - "@types/node": "20.14.10", + "@types/lodash": "4.17.17", + "@types/node": "22.15.17", "@types/papaparse": "5.3.7", "@types/passport-google-oauth20": "2.0.16", - "@typescript-eslint/eslint-plugin": "6.21.0", - "@typescript-eslint/parser": "6.21.0", + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", "codelyzer": "6.0.1", "cypress": "6.2.1", - "eslint": "8.57.0", - "eslint-config-prettier": "9.1.0", - "eslint-plugin-cypress": "2.15.1", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-storybook": "0.6.15", + "eslint": "9.24.0", + "eslint-config-prettier": "10.1.1", + "eslint-plugin-cypress": "4.2.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-storybook": "9.0.17", "husky": "9.1.7", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "jest-preset-angular": "14.4.2", - "nx": "20.3.0", - "prettier": "3.4.2", + "jest-preset-angular": "14.6.0", + "nx": "21.3.9", + "prettier": "3.6.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.1.0", + "prisma": "6.12.0", "react": "18.2.0", "react-dom": "18.2.0", - "replace-in-file": "7.0.1", + "replace-in-file": "8.3.0", "shx": "0.3.4", - "storybook": "8.4.7", - "ts-jest": "29.1.0", + "storybook": "9.0.17", + "ts-jest": "29.4.0", "ts-node": "10.9.2", - "tslib": "2.6.0", - "typescript": "5.6.3", + "tslib": "2.8.1", + "typescript": "5.8.3", "webpack-bundle-analyzer": "4.10.2" }, "engines": { - "node": ">=20" + "node": ">=22" } }, "node_modules/@adobe/css-tools": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz", - "integrity": "sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz", + "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==", "dev": true, "license": "MIT" }, + "node_modules/@ai-sdk/provider": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", + "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", + "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "nanoid": "^3.3.8", + "secure-json-parse": "^2.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, + "node_modules/@ai-sdk/react": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.12.tgz", + "integrity": "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/ui-utils": "1.2.11", + "swr": "^2.2.5", + "throttleit": "2.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ai-sdk/ui-utils": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz", + "integrity": "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "@ai-sdk/provider-utils": "2.2.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.32.0.tgz", + "integrity": "sha512-HG/6Eib6DnJYm/B2ijWFXr4txca/YOuA4K7AsEU0JBrOZSB+RU7oeDyNBPi3c0v0UDDqlkBqM3vBU/auwZlglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.32.0.tgz", + "integrity": "sha512-8Y9MLU72WFQOW3HArYv16+Wvm6eGmsqbxxM1qxtm0hvSASJbxCm+zQAZe5stqysTlcWo4BJ82KEH1PfgHbJAmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.32.0.tgz", + "integrity": "sha512-w8L+rgyXMCPBKmEdOT+RfgMrF0mT6HK60vPYWLz8DBs/P7yFdGo7urn99XCJvVLMSKXrIbZ2FMZ/i50nZTXnuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.32.0.tgz", + "integrity": "sha512-AdWfynhUeX7jz/LTiFU3wwzJembTbdLkQIOLs4n7PyBuxZ3jz4azV1CWbIP8AjUOFmul6uXbmYza+KqyS5CzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.32.0.tgz", + "integrity": "sha512-bTupJY4xzGZYI4cEQcPlSjjIEzMvv80h7zXGrXY1Y0KC/n/SLiMv84v7Uy+B6AG1Kiy9FQm2ADChBLo1uEhGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.32.0.tgz", + "integrity": "sha512-if+YTJw1G3nDKL2omSBjQltCHUQzbaHADkcPQrGFnIGhVyHU3Dzq4g46uEv8mrL5sxL8FjiS9LvekeUlL2NRqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.32.0.tgz", + "integrity": "sha512-kmK5nVkKb4DSUgwbveMKe4X3xHdMsPsOVJeEzBvFJ+oS7CkBPmpfHAEq+CcmiPJs20YMv6yVtUT9yPWL5WgAhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.32.0.tgz", + "integrity": "sha512-PZTqjJbx+fmPuT2ud1n4vYDSF1yrT//vOGI9HNYKNA0PM0xGUBWigf5gRivHsXa3oBnUlTyHV9j7Kqx5BHbVHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.32.0.tgz", + "integrity": "sha512-kYYoOGjvNQAmHDS1v5sBj+0uEL9RzYqH/TAdq8wmcV+/22weKt/fjh+6LfiqkS1SCZFYYrwGnirrUhUM36lBIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.32.0.tgz", + "integrity": "sha512-jyIBLdskjPAL7T1g57UMfUNx+PzvYbxKslwRUKBrBA6sNEsYCFdxJAtZSLUMmw6MC98RDt4ksmEl5zVMT5bsuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.32.0.tgz", + "integrity": "sha512-eDp14z92Gt6JlFgiexImcWWH+Lk07s/FtxcoDaGrE4UVBgpwqOO6AfQM6dXh1pvHxlDFbMJihHc/vj3gBhPjqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.32.0.tgz", + "integrity": "sha512-rnWVglh/K75hnaLbwSc2t7gCkbq1ldbPgeIKDUiEJxZ4mlguFgcltWjzpDQ/t1LQgxk9HdIFcQfM17Hid3aQ6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.32.0.tgz", + "integrity": "sha512-LbzQ04+VLkzXY4LuOzgyjqEv/46Gwrk55PldaglMJ4i4eDXSRXGKkwJpXFwsoU+c1HMQlHIyjJBhrfsfdyRmyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -187,119 +450,127 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1900.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.6.tgz", - "integrity": "sha512-w11bAXQnNWBawTJfQPjvaTRrzrqsOUm9tK9WNvaia/xjiRFpmO0CfmKtn3axNSEJM8jb/czaNQrgTwG+TGc/8g==", + "version": "0.2001.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2001.3.tgz", + "integrity": "sha512-jcPpm0AKYmQD8UnQ5Sz2iEKRjzWq90kkKMLia9CCqW6u48aLqdPrWkCUUwNhtr6fbejyBKNbsy6pUn6P4f8ExQ==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.6", - "rxjs": "7.8.1" + "@angular-devkit/core": "20.1.3", + "rxjs": "7.8.2" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular-devkit/architect/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@angular-devkit/build-angular": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.0.6.tgz", - "integrity": "sha512-dWTAsE6BSI8z0xglQdYBdqTBwg1Q+RWE3OrmlGs+520Dcoq/F0Z41Y1F3MiuHuQPdDAIQr88iB0APkIRW4clMg==", + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-20.1.3.tgz", + "integrity": "sha512-Fa5RRUsGeqmFv3lwibVruCEXyzVkHyjUQbzR0jceVrzWgSgL929IG6xC1JSv6m7xJmaALNxTM+6zGAZf9X/JLw==", + "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1900.6", - "@angular-devkit/build-webpack": "0.1900.6", - "@angular-devkit/core": "19.0.6", - "@angular/build": "19.0.6", - "@babel/core": "7.26.0", - "@babel/generator": "7.26.2", - "@babel/helper-annotate-as-pure": "7.25.9", + "@angular-devkit/architect": "0.2001.3", + "@angular-devkit/build-webpack": "0.2001.3", + "@angular-devkit/core": "20.1.3", + "@angular/build": "20.1.3", + "@babel/core": "7.27.7", + "@babel/generator": "7.27.5", + "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.25.9", - "@babel/plugin-transform-async-to-generator": "7.25.9", - "@babel/plugin-transform-runtime": "7.25.9", - "@babel/preset-env": "7.26.0", - "@babel/runtime": "7.26.0", + "@babel/plugin-transform-async-generator-functions": "7.27.1", + "@babel/plugin-transform-async-to-generator": "7.27.1", + "@babel/plugin-transform-runtime": "7.27.4", + "@babel/preset-env": "7.27.2", + "@babel/runtime": "7.27.6", "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "19.0.6", - "@vitejs/plugin-basic-ssl": "1.1.0", + "@ngtools/webpack": "20.1.3", "ansi-colors": "4.1.3", - "autoprefixer": "10.4.20", - "babel-loader": "9.2.1", + "autoprefixer": "10.4.21", + "babel-loader": "10.0.0", "browserslist": "^4.21.5", - "copy-webpack-plugin": "12.0.2", + "copy-webpack-plugin": "13.0.0", "css-loader": "7.1.2", - "esbuild-wasm": "0.24.0", - "fast-glob": "3.3.2", - "http-proxy-middleware": "3.0.3", + "esbuild-wasm": "0.25.5", + "fast-glob": "3.3.3", + "http-proxy-middleware": "3.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", - "less": "4.2.0", - "less-loader": "12.2.0", + "less": "4.3.0", + "less-loader": "12.3.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", "mini-css-extract-plugin": "2.9.2", - "open": "10.1.0", - "ora": "5.4.1", + "open": "10.1.2", + "ora": "8.2.0", "picomatch": "4.0.2", - "piscina": "4.7.0", - "postcss": "8.4.49", + "piscina": "5.1.2", + "postcss": "8.5.6", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", - "rxjs": "7.8.1", - "sass": "1.80.7", - "sass-loader": "16.0.3", - "semver": "7.6.3", + "rxjs": "7.8.2", + "sass": "1.89.2", + "sass-loader": "16.0.5", + "semver": "7.7.2", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "terser": "5.36.0", + "terser": "5.43.1", "tree-kill": "1.2.2", "tslib": "2.8.1", - "webpack": "5.96.1", + "webpack": "5.99.9", "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.1.0", + "webpack-dev-server": "5.2.2", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.24.0" + "esbuild": "0.25.5" }, "peerDependencies": { - "@angular/compiler-cli": "^19.0.0", - "@angular/localize": "^19.0.0", - "@angular/platform-server": "^19.0.0", - "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.0.6", - "@web/test-runner": "^0.19.0", + "@angular/compiler-cli": "^20.0.0", + "@angular/core": "^20.0.0", + "@angular/localize": "^20.0.0", + "@angular/platform-browser": "^20.0.0", + "@angular/platform-server": "^20.0.0", + "@angular/service-worker": "^20.0.0", + "@angular/ssr": "^20.1.3", + "@web/test-runner": "^0.20.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "karma": "^6.3.0", - "ng-packagr": "^19.0.0", + "ng-packagr": "^20.0.0", "protractor": "^7.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.5 <5.7" + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "typescript": ">=5.8 <5.9" }, "peerDependenciesMeta": { + "@angular/core": { + "optional": true + }, "@angular/localize": { "optional": true }, + "@angular/platform-browser": { + "optional": true + }, "@angular/platform-server": { "optional": true }, @@ -335,17 +606,28 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/build-webpack": { - "version": "0.1900.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1900.6.tgz", - "integrity": "sha512-WehtVrbBow4fc7hsaUKb+BZ6MDE5lO98/tgv7GR5PkRdGKnyLA0pW1AfPLJJQDgcaKjneramMhDFNc1eGSX0mQ==", + "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.2001.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.2001.3.tgz", + "integrity": "sha512-65WFWui+VSlJ+cxdkvVCqQGM2Sj+d8Dn6yrlNxqSwuFJWDg1e6Tcoz2VGWCx5ZoC62PFFruoDvpjPXiukhcB2w==", + "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1900.6", - "rxjs": "7.8.1" + "@angular-devkit/architect": "0.2001.3", + "rxjs": "7.8.2" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -354,2466 +636,2211 @@ "webpack-dev-server": "^5.0.2" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", - "license": "MIT", + "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" + "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", + "node_modules/@angular-devkit/core": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.1.3.tgz", + "integrity": "sha512-23neiDOsq9cprozgBbnWo2nRTE4xYMjcAN59QcS4yYPccDkxbr3AazFHhlTSZWLp63hhTlT+B2AA47W7cUqhUQ==", "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.2", + "source-map": "0.7.4" + }, "engines": { - "node": ">=14.17.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", - "cpu": [ - "arm" - ], + "node_modules/@angular-devkit/schematics": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.1.3.tgz", + "integrity": "sha512-VPwCeKsJE6FEwjIWoUL221Iqh/0Lbml/c+xjISIMXf58qinFlQj1k/5LNLlVrn56QLSHUpxoXIsVek/ME3x6/A==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@angular-devkit/core": "20.1.3", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "8.2.0", + "rxjs": "7.8.2" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", - "cpu": [ - "x64" - ], + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-20.1.1.tgz", + "integrity": "sha512-hEWh/upyTj2bhyRmbNnGtlOXhBSEHwLg8/9YYhwmiNApQwKcvcg7lkstZMEVrKievNHZT6Wh4dWZvjRjMqLNSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-20.1.1.tgz", + "integrity": "sha512-h+D6T35UGIuG0keYPH7dc6OTdfTVJ8GoIhCIpoAmVGhdIdfXIISvDvvX/QPiZtTcefik3vEZEGRiI/Nzc5xImw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "20.1.1", + "@angular-eslint/utils": "20.1.1", + "ts-api-utils": "^2.1.0" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", - "cpu": [ - "arm64" - ], + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-20.1.1.tgz", + "integrity": "sha512-dRqfxYvgOC4DZqvRTmxoIUMeIqTzcIkRcMVEuP8qvR10KHAWDkV7xT4f7BAee9deI/lzoAk3tk5wkQg6POQo7Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "20.1.1", + "@angular-eslint/utils": "20.1.1", + "aria-query": "5.3.2", + "axobject-query": "4.1.0" + }, + "peerDependencies": { + "@angular-eslint/template-parser": "20.1.1", + "@typescript-eslint/types": "^7.11.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", - "cpu": [ - "x64" - ], + "node_modules/@angular-eslint/template-parser": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-20.1.1.tgz", + "integrity": "sha512-giIMYORf8P8MbBxh6EUfiR/7Y+omxJtK2C7a8lYTtLSOIGO0D8c8hXx9hTlPcdupVX+xZXDuZ85c9JDen+JSSA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "20.1.1", + "eslint-scope": "^8.0.2" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", - "cpu": [ - "arm64" - ], + "node_modules/@angular-eslint/utils": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-20.1.1.tgz", + "integrity": "sha512-hqbzGqa/0Ua90r4TMn4oZVnLuwIF6dqEfH7SlstB224h/7+nKoi67aHkmUq7VItWXpDDe+f1opeR01GKS9fNog==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "20.1.1" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", - "cpu": [ - "x64" - ], + "node_modules/@angular/animations": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.1.3.tgz", + "integrity": "sha512-3mkWhcHw2CbfvvjfJYMWjXbTtNHAtZDiVuaqQX4r9i0rPbQ7DqoM1zSgC6XWainWqxnfCHZIZFoI6PKEBVKSrg==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@angular/common": "20.1.3", + "@angular/core": "20.1.3" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", - "cpu": [ - "arm" - ], + "node_modules/@angular/build": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.1.3.tgz", + "integrity": "sha512-sH0G3CUjJryGIM70mKIx28S5rJO2XPoyGClKuS5RE+LW+dZQMGeE2mX0A4Vll2mBESXuPnAURvmCdRyvlRkOeQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.2001.3", + "@babel/core": "7.27.7", + "@babel/helper-annotate-as-pure": "7.27.3", + "@babel/helper-split-export-declaration": "7.24.7", + "@inquirer/confirm": "5.1.13", + "@vitejs/plugin-basic-ssl": "2.1.0", + "beasties": "0.3.4", + "browserslist": "^4.23.0", + "esbuild": "0.25.5", + "https-proxy-agent": "7.0.6", + "istanbul-lib-instrument": "6.0.3", + "jsonc-parser": "3.3.1", + "listr2": "8.3.3", + "magic-string": "0.30.17", + "mrmime": "2.0.1", + "parse5-html-rewriting-stream": "7.1.0", + "picomatch": "4.0.2", + "piscina": "5.1.2", + "rollup": "4.44.1", + "sass": "1.89.2", + "semver": "7.7.2", + "source-map-support": "0.5.21", + "tinyglobby": "0.2.14", + "vite": "7.0.6", + "watchpack": "2.4.4" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "lmdb": "3.4.1" + }, + "peerDependencies": { + "@angular/compiler": "^20.0.0", + "@angular/compiler-cli": "^20.0.0", + "@angular/core": "^20.0.0", + "@angular/localize": "^20.0.0", + "@angular/platform-browser": "^20.0.0", + "@angular/platform-server": "^20.0.0", + "@angular/service-worker": "^20.0.0", + "@angular/ssr": "^20.1.3", + "karma": "^6.4.0", + "less": "^4.2.0", + "ng-packagr": "^20.0.0", + "postcss": "^8.4.0", + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "tslib": "^2.3.0", + "typescript": ">=5.8 <5.9", + "vitest": "^3.1.1" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + }, + "@angular/localize": { + "optional": true + }, + "@angular/platform-browser": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "@angular/ssr": { + "optional": true + }, + "karma": { + "optional": true + }, + "less": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tailwindcss": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", - "cpu": [ - "arm64" - ], + "node_modules/@angular/cdk": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.1.3.tgz", + "integrity": "sha512-TO/OBOPWIDJe+0g4S+ye6hewnWOhgWGa4iygvAlmQ77nyqhioHT60puyaDZRATxKh9k6KVmg9cPAk1lYbOFvaA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "parse5": "^8.0.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^20.0.0 || ^21.0.0", + "@angular/core": "^20.0.0 || ^21.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", - "cpu": [ - "ia32" - ], + "node_modules/@angular/cli": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.1.3.tgz", + "integrity": "sha512-4wY6SXovCXW+jQeSHdvAz0pDtVnRaOeIT6gpcXcxpa8gx/G088XCzJ3haDJYVxmprT4QvbW2UeWzNKtShZ40bw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@angular-devkit/architect": "0.2001.3", + "@angular-devkit/core": "20.1.3", + "@angular-devkit/schematics": "20.1.3", + "@inquirer/prompts": "7.6.0", + "@listr2/prompt-adapter-inquirer": "2.0.22", + "@modelcontextprotocol/sdk": "1.13.3", + "@schematics/angular": "20.1.3", + "@yarnpkg/lockfile": "1.1.0", + "algoliasearch": "5.32.0", + "ini": "5.0.0", + "jsonc-parser": "3.3.1", + "listr2": "8.3.3", + "npm-package-arg": "12.0.2", + "npm-pick-manifest": "10.0.0", + "pacote": "21.0.0", + "resolve": "1.22.10", + "semver": "7.7.2", + "yargs": "18.0.0", + "zod": "3.25.75" + }, + "bin": { + "ng": "bin/ng.js" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", - "cpu": [ - "loong64" - ], + "node_modules/@angular/cli/node_modules/zod": { + "version": "3.25.75", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.75.tgz", + "integrity": "sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", - "cpu": [ - "mips64el" - ], + "node_modules/@angular/common": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.1.3.tgz", + "integrity": "sha512-h2eQfbx6kYw69xpEHtwZ3XbtWinGa6f8sXj7k9di1/xVAxqtbf+9OcBhYYY++oR1QqDeRghNYNblNNt0H9zKzQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@angular/core": "20.1.3", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@angular/compiler": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.1.3.tgz", + "integrity": "sha512-NGMFLymImIdvjLSoH+pasgtJxKynDHX9COBU6T5LP7qi5kf6eR829Zrf7650R3K+uERqwz5PTLg8Kwa4aY7I9w==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", - "cpu": [ - "riscv64" - ], + "node_modules/@angular/compiler-cli": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.1.3.tgz", + "integrity": "sha512-NT7+vtwABtvVj2NLL7KvRzSsa5hgro23AvkAvg6A5sdfWzYDRXovI0YILlTIx1oEA8rupTPu/39gStW5k8XZqg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/core": "7.28.0", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^4.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.2.0", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^18.0.0" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@angular/compiler": "20.1.3", + "typescript": ">=5.8 <5.9" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", - "cpu": [ - "s390x" - ], + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", - "cpu": [ - "x64" - ], + "node_modules/@angular/compiler-cli/node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", - "cpu": [ - "arm64" - ], + "node_modules/@angular/core": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.1.3.tgz", + "integrity": "sha512-haQypZGbKKsClDbR0I4eK+PmKGaZ8b/9QDwNYzInaEqHrTX/rkFXu0L0ejTTznElutQuMM6OPh6aVfnJ9nRr2g==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@angular/compiler": "20.1.3", + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.15.0" + }, + "peerDependenciesMeta": { + "@angular/compiler": { + "optional": true + }, + "zone.js": { + "optional": true + } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", - "cpu": [ - "ia32" - ], + "node_modules/@angular/forms": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.1.3.tgz", + "integrity": "sha512-q2Lbz65mqk/Xmp3qvFSZyUJRKeah3jtfSRxJlHC63utG5WdGl7gN7xRy2dydarRKToWyXqMsjoSlh1YIrUIAng==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "tslib": "^2.3.0" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@angular/common": "20.1.3", + "@angular/core": "20.1.3", + "@angular/platform-browser": "20.1.3", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", - "cpu": [ - "x64" - ], + "node_modules/@angular/language-service": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.1.3.tgz", + "integrity": "sha512-CAiA1pIHYip7hemPRvL4MGuE40M8nJ72ZB6mhVL83+a/IFJW0e58E0CXv4Y5B/vmslnvxX9xEUfH+8PplFKSuw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@ngtools/webpack": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.0.6.tgz", - "integrity": "sha512-eWrIb0tS1CK6+JvFS4GgTD4fN9TtmApKrlaj3pPQXKXKKd42361ec85fuQQXdb4G8eEEq0vyd/bn4NJllh/3vw==", + "node_modules/@angular/localize": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.1.3.tgz", + "integrity": "sha512-bG3GLVzfGXc1BE5gAG8TRZRLKFPlj24SQvNd275nNrT7dMbM5PPVdGZB7BEaTWJqRW/JPoPAex+wywU1NcN3rA==", + "devOptional": true, "license": "MIT", + "dependencies": { + "@babel/core": "7.28.0", + "@types/babel__core": "7.20.5", + "tinyglobby": "^0.2.12", + "yargs": "^18.0.0" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler-cli": "^19.0.0", - "typescript": ">=5.5 <5.7", - "webpack": "^5.54.0" + "@angular/compiler": "20.1.3", + "@angular/compiler-cli": "20.1.3" } }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@angular/localize/node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "devOptional": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@angular-devkit/build-angular/node_modules/copy-webpack-plugin": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", - "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", + "node_modules/@angular/localize/node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "devOptional": true, "license": "MIT", "dependencies": { - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.1", - "globby": "^14.0.0", - "normalize-path": "^3.0.0", - "schema-utils": "^4.2.0", - "serialize-javascript": "^6.0.2" + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/copy-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@angular/localize/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@angular/localize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/material": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.1.3.tgz", + "integrity": "sha512-W6/XJ2mih70b+PJUEAbI3mC415/SNY06nMBKcjWjRSth0jHe5/ujqIj0WkygkpDz34HEa11vV/0BgSpdS2FT5g==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "tslib": "^2.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "@angular/cdk": "20.1.3", + "@angular/common": "^20.0.0 || ^21.0.0", + "@angular/core": "^20.0.0 || ^21.0.0", + "@angular/forms": "^20.0.0 || ^21.0.0", + "@angular/platform-browser": "^20.0.0 || ^21.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/@angular/platform-browser": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.1.3.tgz", + "integrity": "sha512-58iwj2LXdvwr4DG5tAiA2vj9bm/fhBWaR5JWvn3fJEAdW8fnT2gpjpfdBJTMcqg7Qfpx0ZhFsRxH2EUGEV6mvw==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" + "tslib": "^2.3.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "ajv": "^8.8.2" + "@angular/animations": "20.1.3", + "@angular/common": "20.1.3", + "@angular/core": "20.1.3" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } } }, - "node_modules/@angular-devkit/build-angular/node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/@angular-devkit/build-angular/node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "node_modules/@angular/platform-browser-dynamic": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.1.3.tgz", + "integrity": "sha512-y8m+HNHTYfgyQ/Mtku6+NOvlrD54oaj5cTnr382MVc692r+FuBkI9jMI1oZCqNTdv9cFK6Opj5Ie6A7ZxAfGVA==", "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "tslib": "^2.3.0" }, "engines": { - "node": ">= 10.13.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "@angular/common": "20.1.3", + "@angular/compiler": "20.1.3", + "@angular/core": "20.1.3", + "@angular/platform-browser": "20.1.3" } }, - "node_modules/@angular-devkit/build-angular/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "node_modules/@angular/pwa": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-20.1.3.tgz", + "integrity": "sha512-pIA30S/s0d4iINnOoHs6ylVJcu1eNaJAzy3qOOIOyWwtIMrMmi92+yz5x/S25y/uFmuEFA/Ch08MFI5iTy6QXg==", + "dev": true, "license": "MIT", "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "@angular-devkit/schematics": "20.1.3", + "@schematics/angular": "20.1.3", + "parse5-html-rewriting-stream": "7.1.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "typescript": ">=4.9.5" + "@angular/cli": "^20.1.3" }, "peerDependenciesMeta": { - "typescript": { + "@angular/cli": { "optional": true } } }, - "node_modules/@angular-devkit/build-angular/node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "node_modules/@angular/router": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.1.3.tgz", + "integrity": "sha512-ELJyzFJ2JeJkuVpv3kte4AwGBd/zuB5H/wv4+9gcmf6exxO5xH2/PbbLDGs+rWwHkCUcoRHFVyUPqk9yuRq/XA==", "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "tslib": "^2.3.0" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "@angular/common": "20.1.3", + "@angular/core": "20.1.3", + "@angular/platform-browser": "20.1.3", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", - "hasInstallScript": true, + "node_modules/@angular/service-worker": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-20.1.3.tgz", + "integrity": "sha512-ogM83fk0s8pw7r4a/VctCvjDurYhyH9XkXExWm5oHAhc5xyyw4OR/9pNHbtSt7H1/whcHm8ecaL53Sl9zshMdA==", "license": "MIT", - "optional": true, + "dependencies": { + "tslib": "^2.3.0" + }, "bin": { - "esbuild": "bin/esbuild" + "ngsw-config": "ngsw-config.js" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@angular/core": "20.1.3", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@angular-devkit/build-angular/node_modules/http-proxy-middleware": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", - "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", + "node_modules/@antfu/utils": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", + "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.15", - "debug": "^4.3.6", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.3", - "is-plain-object": "^5.0.0", - "micromatch": "^4.0.8" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", + "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.27.7", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.7", + "@babel/types": "^7.27.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, - "node_modules/@angular-devkit/build-angular/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@angular-devkit/build-angular/node_modules/less-loader": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", - "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", + "node_modules/@babel/generator": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "license": "MIT", - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, "engines": { - "node": ">= 12.13.0" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "license": "MIT", "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">= 12.13.0" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", + "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.27.1", + "semver": "^6.3.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "webpack": "^5.0.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@babel/helper-annotate-as-pure": "^7.27.1", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" }, "peerDependencies": { - "ajv": "^8.8.2" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/postcss-loader": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", - "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "license": "MIT", "dependencies": { - "cosmiconfig": "^9.0.0", - "jiti": "^1.20.0", - "semver": "^7.5.4" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=6.9.0" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/sass-loader": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", - "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, "license": "MIT", "dependencies": { - "neo-async": "^2.6.2" + "@babel/types": "^7.27.1" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, "engines": { - "node": ">=14.16" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-devkit/core": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", - "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, "license": "MIT", "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^4.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/core/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "license": "MIT", "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" + "@babel/types": "^7.24.7" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/core/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/core/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "license": "BSD-3-Clause", + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.6.tgz", - "integrity": "sha512-R9hlHfAh1HKoIWgnYJlOEKhUezhTNl0fpUmHxG2252JSY5FLRxmYArTtJYYmbNdBbsBLNg3UHyM/GBPvJSA3NQ==", + "node_modules/@babel/helper-wrap-function": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", + "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.6", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.12", - "ora": "5.4.1", - "rxjs": "7.8.1" + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" - }, - "node_modules/@angular-devkit/schematics/node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "node_modules/@babel/helpers": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", + "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "license": "Apache-2.0", + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", - "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular-eslint/eslint-plugin": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", - "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", + "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", - "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2", - "aria-query": "5.3.2", - "axobject-query": "4.1.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@typescript-eslint/types": "^7.11.0 || ^8.0.0", - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-eslint/eslint-plugin-template/node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@angular-eslint/template-parser": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", - "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "eslint-scope": "^8.0.2" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular-eslint/template-parser/node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@angular-eslint/utils": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", - "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", + "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular/animations": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.5.tgz", - "integrity": "sha512-HCOF2CrhUvjoZWusd4nh32VOxpUrg6bV+3Z8Q36Ix3aZdni8v0qoP2rl5wGbotaPtYg5RtyDH60Z2AOPKqlrZg==", + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/core": "19.0.5" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/animations/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/build": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.0.6.tgz", - "integrity": "sha512-KEVNLgTZUF2dfpOYQn+yR2HONHUTxq/2rFVhiK9qAvrm/m+uKJNEXx7hGtbRyoqenZff4ScJq+7feITUldfX8g==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "license": "MIT", - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1900.6", - "@babel/core": "7.26.0", - "@babel/helper-annotate-as-pure": "7.25.9", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.26.0", - "@inquirer/confirm": "5.0.2", - "@vitejs/plugin-basic-ssl": "1.1.0", - "beasties": "0.1.0", - "browserslist": "^4.23.0", - "esbuild": "0.24.0", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.5", - "istanbul-lib-instrument": "6.0.3", - "listr2": "8.2.5", - "magic-string": "0.30.12", - "mrmime": "2.0.0", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.7.0", - "rollup": "4.26.0", - "sass": "1.80.7", - "semver": "7.6.3", - "vite": "5.4.11", - "watchpack": "2.4.2" - }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "optionalDependencies": { - "lmdb": "3.1.5" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/compiler": "^19.0.0", - "@angular/compiler-cli": "^19.0.0", - "@angular/localize": "^19.0.0", - "@angular/platform-server": "^19.0.0", - "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.0.6", - "less": "^4.2.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.5 <5.7" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "@angular/ssr": { - "optional": true - }, - "less": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@angular/build/node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", + "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@angular/build/node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" - } - }, - "node_modules/@angular/build/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "node": ">=6.9.0" }, - "engines": { - "node": ">= 14" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/build/node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", + "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/cdk": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.0.4.tgz", - "integrity": "sha512-P8V1n6AFFjBUJG3YRgw8DiiNDWPZVrwQ42wbwgZxd4s2TQAuNFg3YY8h/DSMVxt2sXpavrshZsoLtP9yLKZjHA==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, - "optionalDependencies": { - "parse5": "^7.1.2" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/common": "^19.0.0 || ^20.0.0", - "@angular/core": "^19.0.0 || ^20.0.0", - "rxjs": "^6.5.3 || ^7.4.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/cdk/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/cli": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.6.tgz", - "integrity": "sha512-ZEHhgRRVIdn10dbsAjB8TE9Co32hfuL9/im5Jcfa1yrn6KJefmigz6KN8Xu7FXMH5FkdqfQ11QpLBxJSPb9aww==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", + "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1900.6", - "@angular-devkit/core": "19.0.6", - "@angular-devkit/schematics": "19.0.6", - "@inquirer/prompts": "7.1.0", - "@listr2/prompt-adapter-inquirer": "2.0.18", - "@schematics/angular": "19.0.6", - "@yarnpkg/lockfile": "1.1.0", - "ini": "5.0.0", - "jsonc-parser": "3.3.1", - "listr2": "8.2.5", - "npm-package-arg": "12.0.0", - "npm-pick-manifest": "10.0.0", - "pacote": "20.0.0", - "resolve": "1.22.8", - "semver": "7.6.3", - "symbol-observable": "4.0.0", - "yargs": "17.7.2" - }, - "bin": { - "ng": "bin/ng.js" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@angular/cli/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/cli/node_modules/npm-package-arg": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.0.tgz", - "integrity": "sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", + "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "hosted-git-info": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^6.0.0" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/cli/node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/common": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.5.tgz", - "integrity": "sha512-fFK+euCj1AjBHBCpj9VnduMSeqoMRhZZHbhPYiND7tucRRJ8vwGU0sYK2KI/Ko+fsrNIXL/0O4F36jVPl09Smg==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/core": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/common/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/compiler": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.0.5.tgz", - "integrity": "sha512-S8ku5Ljp0kqX3shfmE9DVo09629jeYJSlBRGbj2Glb92dd+VQZPOz7KxqKRTwmAl7lQIV/+4Lr6G/GVTsoC4vg==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/core": "19.0.5" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/compiler-cli": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.0.5.tgz", - "integrity": "sha512-KSzuWCTZlvJsoAenxM9cjTOzNM8mrFxDBInj0KVPz7QU83amGS4rcv1pWO/QGYQcErfskcN84TAdMegaRWWCmA==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.26.0", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^4.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" - }, - "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js", - "ngcc": "bundles/ngcc/index.js" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/compiler": "19.0.5", - "typescript": ">=5.5 <5.7" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/compiler-cli/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/@angular/compiler-cli/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/compiler/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/core": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.0.5.tgz", - "integrity": "sha512-Ywc6sPO6G/Y1stfk3y/MallV/h0yzQ0vdOHRWueLrk5kD1DTdbolV4X03Cs3PuVvravgcSVE3nnuuHFuH32emQ==", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@angular/core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/forms": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.0.5.tgz", - "integrity": "sha512-OhNFkfOoguqCDq07vNBV28FFrmTM8S11Z3Cd6PQZJJF9TgAtpV5KtF7A3eXBCN92W4pmqluomPjfK7YyImzIYQ==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/forms/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/language-service": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.0.5.tgz", - "integrity": "sha512-E4WFEsCzHuF3DYe4EfOCiMGW1zWmq3UYi5XXOBNLyzWDvwU5xTfdme6ECXGawHMc2kCaWMVNL4DzYpVsUgLG0w==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", + "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/localize": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-19.0.5.tgz", - "integrity": "sha512-4Uk0cNYXZpjPvUXo5gAy0rjCcemyAVOG319q5BJyLSeCV0DJ+MTIR6ylGK3oLSXqKACpF3r3+Wa235xj7vxk3Q==", - "devOptional": true, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.26.0", - "@types/babel__core": "7.20.5", - "fast-glob": "3.3.2", - "yargs": "^17.2.1" - }, - "bin": { - "localize-extract": "tools/bundles/src/extract/cli.js", - "localize-migrate": "tools/bundles/src/migrate/cli.js", - "localize-translate": "tools/bundles/src/translate/cli.js" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/compiler": "19.0.5", - "@angular/compiler-cli": "19.0.5" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/material": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-19.0.4.tgz", - "integrity": "sha512-8WRMbN1+oRXx1ZFLni+BRz60F4FWzJPFORsQ8qAvY3sHWzyjunsYZkpbze3uiZO6bu3hiyQCU6g+k/58Qc6kkw==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/animations": "^19.0.0 || ^20.0.0", - "@angular/cdk": "19.0.4", - "@angular/common": "^19.0.0 || ^20.0.0", - "@angular/core": "^19.0.0 || ^20.0.0", - "@angular/forms": "^19.0.0 || ^20.0.0", - "@angular/platform-browser": "^19.0.0 || ^20.0.0", - "rxjs": "^6.5.3 || ^7.4.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/material/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/platform-browser": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.5.tgz", - "integrity": "sha512-41+Jo5DEil4Ifvv+UE/p1l9YJtYN+xfhx+/C9cahVgvV5D2q+givyK73d0Mnb6XOfe1q+hoV5lZ+XhQYp21//g==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/animations": "19.0.5", - "@angular/common": "19.0.5", - "@angular/core": "19.0.5" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.0.5.tgz", - "integrity": "sha512-KKFdue/uJVxkWdrntRAXkz+ycp4nD3SuGOH5pPf2svCBxieuHuFlWDi+DYVuFSEpC/ICCmlhrtzIAm44A4qzzQ==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/compiler": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/platform-browser-dynamic/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/platform-browser/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/pwa": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-19.0.6.tgz", - "integrity": "sha512-Xehq6wH4aMK5413LpuTBq/fvyJfCRU0GGcgKXigYmHLgWHolPBH356s4tSvNYvn8u9IHnl516qDkBgKJNrq5CQ==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/schematics": "19.0.6", - "@schematics/angular": "19.0.6", - "parse5-html-rewriting-stream": "7.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/cli": "^19.0.0-next.0" - }, - "peerDependenciesMeta": { - "@angular/cli": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/router": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.0.5.tgz", - "integrity": "sha512-6tNubVVj/rRyTg+OXjQxACfufvCLHAwDQtv9wqt6q/3OYSnysHTik3ho3FaFPwu7fXJ+6p9Rjzkh2VY9QMk4bw==", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", + "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/router/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@angular/service-worker": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-19.0.5.tgz", - "integrity": "sha512-qU5lgx1WJ+feCOV/EhkN9m20xFdIslpEQcSZZC+VJnEwcG6VTbofg1dRaHWZ9HAjS1uP7bFoK0HUYu4el0bHGA==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" - }, - "bin": { - "ngsw-config": "ngsw-config.js" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@angular/service-worker/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/compat-data": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", - "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", + "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", - "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", + "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", + "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.1.tgz", + "integrity": "sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2822,188 +2849,213 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", - "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz", + "integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.3" }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -3012,16 +3064,82 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", - "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", + "node_modules/@babel/preset-env": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", + "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-decorators": "^7.25.9" + "@babel/compat-data": "^7.27.2", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.27.1", + "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.40.0", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -3030,2905 +3148,2911 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "devOptional": true, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "devOptional": true, + "node_modules/@babel/preset-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "devOptional": true, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "devOptional": true, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", - "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "devOptional": true, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", "license": "MIT", + "optional": true + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.6.2.tgz", + "integrity": "sha512-vLu7SRY84CV/Dd+NUdgtidn2hS5hSMUC1vDBY0VcviTdgRYkU43vIz3vIFbmx14cX1r+mM7WjzE5Fl1fGEM0RQ==", + "devOptional": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "devOptional": true, - "license": "MIT", + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@codewithdan/observable-store": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/@codewithdan/observable-store/-/observable-store-2.2.15.tgz", + "integrity": "sha512-LVCSMZzTCvoDo5n7YDmtIIEhTmvJ8O21k36Vwu/A4kumdXQ1YVs4sKoSK3vlINZPL4AYY2MRsBVtvre4QIETFw==", + "license": "MIT", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "rxjs": ">=6.4.0 <8" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "devOptional": true, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.1.90" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "devOptional": true, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@jridgewell/trace-mapping": "0.3.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=12" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "devOptional": true, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha512-EDiBsVPWC27DDLEJCo+dpl9ODHhdrwU57ccr9tspwCdG2ni0QVkf6LF0FGbhfujcjPxnXLIwsaks4sOrwrA4Qw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=4" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer/node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cypress/listr-verbose-renderer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.8.0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "devOptional": true, + "node_modules/@cypress/listr-verbose-renderer/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "node_modules/@cypress/listr-verbose-renderer/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=0.8.0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", - "license": "MIT", + "node_modules/@cypress/request": { + "version": "2.88.12", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", + "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.10.3", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 6" } }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", - "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "node_modules/@cypress/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.25.9" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.12" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", - "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "debug": "^3.1.0", + "lodash.once": "^4.1.1" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "ms": "^2.1.1" } }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "node_modules/@cypress/xvfb/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@date-fns/utc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@date-fns/utc/-/utc-2.1.0.tgz", + "integrity": "sha512-176grgAgU2U303rD2/vcOmNg0kGPbhzckuH1TEP2al7n0AQipZIy9P15usd2TKQCG1g+E1jX/ZVQSzs4sUDwgA==", + "license": "MIT" + }, + "node_modules/@deno/shim-deno": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.18.2.tgz", + "integrity": "sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@deno/shim-deno-test": "^0.5.0", + "which": "^4.0.0" } }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "node_modules/@deno/shim-deno-test": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz", + "integrity": "sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==", + "license": "MIT" + }, + "node_modules/@deno/shim-deno/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=16" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", - "license": "MIT", + "node_modules/@deno/shim-deno/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "globals": "^11.1.0" + "isexe": "^3.1.1" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "node-which": "bin/which.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", - "license": "MIT", + "node_modules/@dfinity/agent": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.15.7.tgz", + "integrity": "sha512-w34yvlUTpPBG8nLOD0t/ao3k2xonOFq4QGvfJ1HiS/nIggdza/3xC3nLBszGrjVYWj1jqu8BLFvQXCAeWin75A==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "base64-arraybuffer": "^0.2.0", + "bignumber.js": "^9.0.0", + "borc": "^2.1.1", + "js-sha256": "0.9.0", + "simple-cbor": "^0.4.1", + "ts-node": "^10.8.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@dfinity/candid": "^0.15.7", + "@dfinity/principal": "^0.15.7" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", - "license": "MIT", + "node_modules/@dfinity/auth-client": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@dfinity/auth-client/-/auth-client-0.15.7.tgz", + "integrity": "sha512-f6cRqXayCf+7+9gNcDnAZZwJrgBYKIzfxjxeRLlpsueQeo+E/BX2yVSANxzTkCNc4U3p+ttHI1RNtasLunYTcA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "idb": "^7.0.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@dfinity/agent": "^0.15.7", + "@dfinity/identity": "^0.15.7", + "@dfinity/principal": "^0.15.7" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", - "license": "MIT", + "node_modules/@dfinity/candid": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.15.7.tgz", + "integrity": "sha512-lTcjK/xrSyT7wvUQ2pApG+yklQAwxaofQ04D1IWv0/8gKbY0eUbh8G2w6+CypJ15Hb1CH24ijUj8nWdeX/z3jg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "ts-node": "^10.8.2" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", - "license": "MIT", + "node_modules/@dfinity/identity": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-0.15.7.tgz", + "integrity": "sha512-kBAkx9wq78jSQf6T5aayLyWm8YgtOZw8bW6+OuzX6tR3hkAEa85A9TcKA7BjkmMWSIskjEDVQub4fFfKWS2vOQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "borc": "^2.1.1", + "js-sha256": "^0.9.0", + "tweetnacl": "^1.0.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@dfinity/agent": "^0.15.7", + "@dfinity/principal": "^0.15.7", + "@peculiar/webcrypto": "^1.4.0" } }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", - "license": "MIT", + "node_modules/@dfinity/principal": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.15.7.tgz", + "integrity": "sha512-6/AkYzpGEH6Jw/0+B/EeeQn+5u2GDDvRLt1kQPhIG4txQYFnOy04H3VvyrymmfAj6/CXUgrOrux6OxgYSLYVJg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "js-sha256": "^0.9.0", + "ts-node": "^10.8.2" } }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@dinero.js/currencies": { + "version": "2.0.0-alpha.8", + "resolved": "https://registry.npmjs.org/@dinero.js/currencies/-/currencies-2.0.0-alpha.8.tgz", + "integrity": "sha512-zApiqtuuPwjiM9LJA5/kNcT48VSHRiz2/mktkXjIpfxrJKzthXybUAgEenExIH6dYhLDgVmsLQZtZFOsdYl0Ag==", + "license": "MIT" }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=14.17.0" } }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", - "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "tslib": "^2.4.0" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "tslib": "^2.4.0" } }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", - "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "regenerator-transform": "^0.15.2" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", - "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "license": "MIT", + "node_modules/@eslint/config-array": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", - "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", + "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", - "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", - "license": "MIT", + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.3.tgz", - "integrity": "sha512-6+5hpdr6mETwSKjmJUdYw0EIkATiQhnELWlE3kJFBwSg/BGIVwVaVbX+gOXBCdc7Ln1RXZxyWGecIXhUfnl7oA==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", + "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", - "license": "MIT", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/preset-env": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", - "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.25.9", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.25.9", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.25.9", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.25.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.25.9", - "@babel/plugin-transform-typeof-symbol": "^7.25.9", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", - "semver": "^6.3.1" + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@hexagon/base64": { + "version": "1.1.28", + "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", + "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "license": "MIT", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", - "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-typescript": "^7.25.9" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT", + "optional": true + }, + "node_modules/@iconify/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", "license": "MIT", + "optional": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@antfu/install-pkg": "^1.0.0", + "@antfu/utils": "^8.1.0", + "@iconify/types": "^2.0.0", + "debug": "^4.4.0", + "globals": "^15.14.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.0.0", + "mlly": "^1.7.4" } }, - "node_modules/@babel/traverse": { - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "node_modules/@iconify/utils/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, + "optional": true, "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "node_modules/@inquirer/checkbox": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.0.tgz", + "integrity": "sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@braintree/sanitize-url": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", - "license": "MIT", - "optional": true - }, - "node_modules/@codewithdan/observable-store": { - "version": "2.2.15", - "resolved": "https://registry.npmjs.org/@codewithdan/observable-store/-/observable-store-2.2.15.tgz", - "integrity": "sha512-LVCSMZzTCvoDo5n7YDmtIIEhTmvJ8O21k36Vwu/A4kumdXQ1YVs4sKoSK3vlINZPL4AYY2MRsBVtvre4QIETFw==", - "license": "MIT", + "node": ">=18" + }, "peerDependencies": { - "rxjs": ">=6.4.0 <8" + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, + "node_modules/@inquirer/confirm": { + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.13.tgz", + "integrity": "sha512-EkCtvp67ICIVVzjsquUiVSd+V5HRGOGQfsqA4E4vMWhYnB7InUL0pa0TIWt1i+OfP16Gkds8CdIu6yGZwOM1Yw==", "license": "MIT", - "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.14", + "@inquirer/type": "^3.0.7" + }, "engines": { - "node": ">=0.1.90" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@inquirer/core": { + "version": "10.1.15", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", + "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@inquirer/editor": { + "version": "4.2.15", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.15.tgz", + "integrity": "sha512-wst31XT8DnGOSS4nNJDIklGKnf+8shuauVrWzgKegWUe28zfCftcWZ2vktGdzJgcylWSS2SrDnYUb6alZcwnCQ==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", - "integrity": "sha512-EDiBsVPWC27DDLEJCo+dpl9ODHhdrwU57ccr9tspwCdG2ni0QVkf6LF0FGbhfujcjPxnXLIwsaks4sOrwrA4Qw==", + "node_modules/@inquirer/expand": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", + "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^1.1.3", - "cli-cursor": "^1.0.2", - "date-fns": "^1.27.2", - "figures": "^1.7.0" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, + "node_modules/@inquirer/figures": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", + "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "node_modules/@inquirer/input": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", + "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", "dev": true, "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "node_modules/@inquirer/number": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", + "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A==", + "node_modules/@inquirer/password": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", + "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^1.0.1" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==", + "node_modules/@inquirer/prompts": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.6.0.tgz", + "integrity": "sha512-jAhL7tyMxB3Gfwn4HIJ0yuJ5pvcB5maYUcouGcgd/ub79f9MqZ+aVnBtuFf+VC2GTkCBF+R+eo7Vi63w5VZlzw==", "dev": true, "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.1.9", + "@inquirer/confirm": "^5.1.13", + "@inquirer/editor": "^4.2.14", + "@inquirer/expand": "^4.0.16", + "@inquirer/input": "^4.2.0", + "@inquirer/number": "^3.0.16", + "@inquirer/password": "^4.0.16", + "@inquirer/rawlist": "^4.1.4", + "@inquirer/search": "^3.0.16", + "@inquirer/select": "^4.2.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw==", + "node_modules/@inquirer/rawlist": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", + "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", "dev": true, "license": "MIT", "dependencies": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/@inquirer/search": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", + "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/listr-verbose-renderer/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "node_modules/@inquirer/select": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", + "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", "dev": true, "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@cypress/request": { - "version": "2.88.12", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", - "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.10.3", - "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" + "node": ">=18" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, + "node_modules/@inquirer/type": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", + "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, "engines": { - "node": ">= 0.12" - } - }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.10.5", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.5.tgz", - "integrity": "sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" + "node": ">=18" }, - "engines": { - "node": ">=0.6" + "peerDependencies": { + "@types/node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@cypress/request/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@cypress/xvfb/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@dfinity/agent": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.15.7.tgz", - "integrity": "sha512-w34yvlUTpPBG8nLOD0t/ao3k2xonOFq4QGvfJ1HiS/nIggdza/3xC3nLBszGrjVYWj1jqu8BLFvQXCAeWin75A==", + "node_modules/@internationalized/number": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.3.tgz", + "integrity": "sha512-p+Zh1sb6EfrfVaS86jlHGQ9HA66fJhV9x5LiE5vCbZtXEHAuhcmUZUdZ4WrFpUBfNalr2OkAJI5AcKEQF+Lebw==", "license": "Apache-2.0", "dependencies": { - "base64-arraybuffer": "^0.2.0", - "bignumber.js": "^9.0.0", - "borc": "^2.1.1", - "js-sha256": "0.9.0", - "simple-cbor": "^0.4.1", - "ts-node": "^10.8.2" - }, - "peerDependencies": { - "@dfinity/candid": "^0.15.7", - "@dfinity/principal": "^0.15.7" + "@swc/helpers": "^0.5.0" } }, - "node_modules/@dfinity/auth-client": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@dfinity/auth-client/-/auth-client-0.15.7.tgz", - "integrity": "sha512-f6cRqXayCf+7+9gNcDnAZZwJrgBYKIzfxjxeRLlpsueQeo+E/BX2yVSANxzTkCNc4U3p+ttHI1RNtasLunYTcA==", - "license": "Apache-2.0", + "node_modules/@ionic/angular": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.6.3.tgz", + "integrity": "sha512-Uw8eAcvqVw8mtGqX8kvUGNywSXjXZ3gdERuWC4hUSc63bS1Q+yo/319JLu+yENxOObtAu2dS5FYiqUZ07T8Brg==", + "license": "MIT", "dependencies": { - "idb": "^7.0.2" + "@ionic/core": "8.6.3", + "ionicons": "^7.0.0", + "jsonc-parser": "^3.0.0", + "tslib": "^2.3.0" }, "peerDependencies": { - "@dfinity/agent": "^0.15.7", - "@dfinity/identity": "^0.15.7", - "@dfinity/principal": "^0.15.7" + "@angular/core": ">=16.0.0", + "@angular/forms": ">=16.0.0", + "@angular/router": ">=16.0.0", + "rxjs": ">=7.5.0", + "zone.js": ">=0.13.0" } }, - "node_modules/@dfinity/candid": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.15.7.tgz", - "integrity": "sha512-lTcjK/xrSyT7wvUQ2pApG+yklQAwxaofQ04D1IWv0/8gKbY0eUbh8G2w6+CypJ15Hb1CH24ijUj8nWdeX/z3jg==", - "license": "Apache-2.0", + "node_modules/@ionic/angular/node_modules/ionicons": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz", + "integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==", + "license": "MIT", "dependencies": { - "ts-node": "^10.8.2" + "@stencil/core": "^4.0.3" } }, - "node_modules/@dfinity/identity": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-0.15.7.tgz", - "integrity": "sha512-kBAkx9wq78jSQf6T5aayLyWm8YgtOZw8bW6+OuzX6tR3hkAEa85A9TcKA7BjkmMWSIskjEDVQub4fFfKWS2vOQ==", - "license": "Apache-2.0", + "node_modules/@ionic/core": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.6.3.tgz", + "integrity": "sha512-N/mkw+sPecLEoO1lrnKDS0uZgl6PWSyFprCkkqoK1nHlfBkgFiHm5M9rvWlnGaFC/5xrhNGHdUtYHDFM+F8gRw==", + "license": "MIT", "dependencies": { - "borc": "^2.1.1", - "js-sha256": "^0.9.0", - "tweetnacl": "^1.0.1" - }, - "peerDependencies": { - "@dfinity/agent": "^0.15.7", - "@dfinity/principal": "^0.15.7", - "@peculiar/webcrypto": "^1.4.0" + "@stencil/core": "4.33.1", + "ionicons": "^7.2.2", + "tslib": "^2.1.0" } }, - "node_modules/@dfinity/identity/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/@dfinity/principal": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.15.7.tgz", - "integrity": "sha512-6/AkYzpGEH6Jw/0+B/EeeQn+5u2GDDvRLt1kQPhIG4txQYFnOy04H3VvyrymmfAj6/CXUgrOrux6OxgYSLYVJg==", - "license": "Apache-2.0", + "node_modules/@ionic/core/node_modules/ionicons": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz", + "integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==", + "license": "MIT", "dependencies": { - "js-sha256": "^0.9.0", - "ts-node": "^10.8.2" + "@stencil/core": "^4.0.3" } }, - "node_modules/@dinero.js/currencies": { - "version": "2.0.0-alpha.8", - "resolved": "https://registry.npmjs.org/@dinero.js/currencies/-/currencies-2.0.0-alpha.8.tgz", - "integrity": "sha512-zApiqtuuPwjiM9LJA5/kNcT48VSHRiz2/mktkXjIpfxrJKzthXybUAgEenExIH6dYhLDgVmsLQZtZFOsdYl0Ag==", + "node_modules/@ioredis/commands": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.0.tgz", + "integrity": "sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==", "license": "MIT" }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": "20 || >=22" } }, - "node_modules/@emnapi/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz", - "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==", + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", "dev": true, "license": "MIT", "dependencies": { - "@emnapi/wasi-threads": "1.0.1", - "tslib": "^2.4.0" + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" } }, - "node_modules/@emnapi/core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "tslib": "^2.4.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@emnapi/runtime/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@emnapi/wasi-threads/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", - "cpu": [ - "arm" - ], + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", - "cpu": [ - "arm64" - ], + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", - "cpu": [ - "x64" - ], + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", - "cpu": [ - "arm64" - ], + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", - "cpu": [ - "arm64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", - "cpu": [ - "arm" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", - "cpu": [ - "arm64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", - "cpu": [ - "ia32" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", - "cpu": [ - "loong64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", - "cpu": [ - "mips64el" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", - "cpu": [ - "ppc64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", - "cpu": [ - "riscv64" - ], + "node_modules/@jest/console": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.5.tgz", + "integrity": "sha512-xY6b0XiL0Nav3ReresUarwl2oIz1gTnxGbGpho9/rbUWsLH0f1OD/VT84xs8c7VmH7MChnLb0pag6PhZhAdDiA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", - "cpu": [ - "s390x" - ], + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/core/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/core/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core/node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/core/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", - "cpu": [ - "ia32" - ], + "node_modules/@jest/core/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "node_modules/@jest/core/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "node_modules/@jest/core/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@jest/core/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@jest/core/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@jest/core/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=8" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@jest/core/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "type-fest": "^0.20.2" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@jest/core/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/@jest/core/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@hexagon/base64": { - "version": "1.1.28", - "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", - "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==", - "license": "MIT" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "license": "Apache-2.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=8" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "node_modules/@jest/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT" }, - "node_modules/@inquirer/checkbox": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.4.tgz", - "integrity": "sha512-fYAKCAcGNMdfjL6hZTRUwkIByQ8EIZCXKrIQZH7XjADnN/xvRUhj8UdBbpC4zoUzvChhkSC/zRKaP/tDs3dZpg==", + "node_modules/@jest/core/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/figures": "^1.0.9", - "@inquirer/type": "^3.0.2", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=18" + "node": "*" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@inquirer/confirm": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", - "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", - "license": "MIT", + "node_modules/@jest/core/node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@inquirer/core": "^10.1.0", - "@inquirer/type": "^3.0.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": ">=10" } }, - "node_modules/@inquirer/core": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.2.tgz", - "integrity": "sha512-bHd96F3ezHg1mf/J0Rb4CV8ndCN0v28kUlrHqP7+ECm1C/A+paB7Xh2lbMk6x+kweQC+rZOxM/YeKikzxco8bQ==", + "node_modules/@jest/core/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.9", - "@inquirer/type": "^3.0.2", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/core/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", + "node_modules/@jest/core/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@jest/core/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/editor": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.1.tgz", - "integrity": "sha512-xn9aDaiP6nFa432i68JCaL302FyL6y/6EG97nAtfIPnWZ+mWPgCMLGc4XZ2QQMsZtu9q3Jd5AzBPjXh10aX9kA==", + "node_modules/@jest/core/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2", - "external-editor": "^3.1.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/expand": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.4.tgz", - "integrity": "sha512-GYocr+BPyxKPxQ4UZyNMqZFSGKScSUc0Vk17II3J+0bDcgGsQm0KYQNooN1Q5iBfXsy3x/VWmHGh20QnzsaHwg==", + "node_modules/@jest/core/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2", - "yoctocolors-cjs": "^2.1.2" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "peerDependencies": { - "@types/node": ">=18" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.9.tgz", - "integrity": "sha512-BXvGj0ehzrngHTPTDqUoDT3NXL8U0RxUk2zJm2A66RhCEIWdtU1v6GuUqNAgArW4PQ9CinqIWyHdQgdwOj06zQ==", + "node_modules/@jest/core/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/input": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.1.tgz", - "integrity": "sha512-nAXAHQndZcXB+7CyjIW3XuQZZHbQQ0q8LX6miY6bqAWwDzNa9JUioDBYrFmOUNIsuF08o1WT/m2gbBXvBhYVxg==", + "node_modules/@jest/core/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/number": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.4.tgz", - "integrity": "sha512-DX7a6IXRPU0j8kr2ovf+QaaDiIf+zEKaZVzCWdLOTk7XigqSXvoh4cul7x68xp54WTQrgSnW7P1WBJDbyY3GhA==", + "node_modules/@jest/core/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2" - }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/password": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.4.tgz", - "integrity": "sha512-wiliQOWdjM8FnBmdIHtQV2Ca3S1+tMBUerhyjkRCv1g+4jSvEweGu9GCcvVEgKDhTBT15nrxvk5/bVrGUqSs1w==", + "node_modules/@jest/core/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2", - "ansi-escapes": "^4.3.2" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/prompts": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.1.0.tgz", - "integrity": "sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA==", + "node_modules/@jest/core/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.0.2", - "@inquirer/confirm": "^5.0.2", - "@inquirer/editor": "^4.1.0", - "@inquirer/expand": "^4.0.2", - "@inquirer/input": "^4.0.2", - "@inquirer/number": "^3.0.2", - "@inquirer/password": "^4.0.2", - "@inquirer/rawlist": "^4.0.2", - "@inquirer/search": "^3.0.2", - "@inquirer/select": "^4.0.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/prompts/node_modules/@inquirer/confirm": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.1.tgz", - "integrity": "sha512-vVLSbGci+IKQvDOtzpPTCOiEJCNidHcAq9JYVoWTW0svb5FiwSLotkM+JXNXejfjnzVYV9n0DTBythl9+XgTxg==", + "node_modules/@jest/core/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@inquirer/rawlist": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.4.tgz", - "integrity": "sha512-IsVN2EZdNHsmFdKWx9HaXb8T/s3FlR/U1QPt9dwbSyPtjFbMTlW9CRFvnn0bm/QIsrMRD2oMZqrQpSWPQVbXXg==", + "node_modules/@jest/core/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/type": "^3.0.2", - "yoctocolors-cjs": "^2.1.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@inquirer/search": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.4.tgz", - "integrity": "sha512-tSkJk2SDmC2MEdTIjknXWmCnmPr5owTs9/xjfa14ol1Oh95n6xW7SYn5fiPk4/vrJPys0ggSWiISdPze4LTa7A==", + "node_modules/@jest/core/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/figures": "^1.0.9", - "@inquirer/type": "^3.0.2", - "yoctocolors-cjs": "^2.1.2" - }, "engines": { - "node": ">=18" + "node": ">=8.6" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@inquirer/select": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.4.tgz", - "integrity": "sha512-ZzYLuLoUzTIW9EJm++jBpRiTshGqS3Q1o5qOEQqgzaBlmdsjQr6pA4TUNkwu6OBYgM2mIRbCz6mUhFDfl/GF+w==", + "node_modules/@jest/core/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/core/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@jest/core/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/core/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", "dependencies": { - "@inquirer/core": "^10.1.2", - "@inquirer/figures": "^1.0.9", - "@inquirer/type": "^3.0.2", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@inquirer/type": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.2.tgz", - "integrity": "sha512-ZhQ4TvhwHZF+lGhQ2O/rsjo80XoZR5/5qhOY3t6FJuX5XBg5Be8YzYTvaUGJnc12AUGI2nr4QSUE4PhKSigx7g==", + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@internationalized/number": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.0.tgz", - "integrity": "sha512-PtrRcJVy7nw++wn4W2OuePQQfTqDzfusSuY1QTtui4wa7r+rGVtR75pO8CyKvHvzyQYi3Q1uO5sY0AsB4e65Bw==", - "license": "Apache-2.0", + "node_modules/@jest/environment": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.5.tgz", + "integrity": "sha512-aRX7WoaWx1oaOkDQvCWImVQ8XNtdv5sEWgk4gxR6NXb7WBUnL5sRak4WRzIQRZ1VTWPvV4VI4mgGjNL9TeKMYA==", + "dev": true, + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.5.0" + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "devOptional": true, - "license": "ISC", + "node_modules/@jest/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-6udac8KKrtTtC+AXZ2iUN/R7dp7Ydry+Fo6FPFnDG54wjVMnb6vW/XNlf7Xj8UDjAE3aAVAsR4KFyKk3TCXmTA==", + "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "expect": "30.0.5", + "jest-snapshot": "30.0.5" }, "engines": { - "node": ">=12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "devOptional": true, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "jest-get-type": "^29.6.3" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "devOptional": true, + "node_modules/@jest/expect/node_modules/@jest/expect-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", + "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@jest/get-type": "30.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "devOptional": true, + "node_modules/@jest/expect/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "devOptional": true, + "node_modules/@jest/expect/node_modules/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "devOptional": true, + "node_modules/@jest/expect/node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "node_modules/@jest/expect/node_modules/jest-matcher-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", + "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^7.0.4" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.5", + "pretty-format": "30.0.5" }, "engines": { - "node": ">=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "devOptional": true, - "license": "ISC", + "node_modules/@jest/expect/node_modules/jest-snapshot": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", + "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", + "dev": true, + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", + "semver": "^7.7.2", + "synckit": "^0.11.8" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "devOptional": true, + "node_modules/@jest/expect/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@jest/expect/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "devOptional": true, + "node_modules/@jest/fake-timers": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.5.tgz", + "integrity": "sha512-ZO5DHfNV+kgEAeP3gK3XlpJLL4U3Sz6ebl/n68Uwt64qFFs5bv4bfEEjyRGK5uM0C90ewooNgFuKMdkbEoMEXw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", + "@jest/types": "30.0.5", + "@sinonjs/fake-timers": "^13.0.0", "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/console/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/@jest/get-type": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", + "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/console/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/core": { + "node_modules/@jest/globals": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/@jest/core/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@jest/core/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/environment": { + "node_modules/@jest/globals/node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", @@ -5940,28 +6064,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@jest/environment/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/expect": { + "node_modules/@jest/globals/node_modules/@jest/expect": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "expect": "^29.7.0", @@ -5971,24 +6078,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { + "node_modules/@jest/globals/node_modules/@jest/fake-timers": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -6002,415 +6096,352 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/fake-timers/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@jest/fake-timers/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "devOptional": true, + "node_modules/@jest/globals/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "devOptional": true, + "node_modules/@jest/globals/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/@jest/reporters/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", + "node_modules/@jest/globals/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/globals/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "undici-types": "~6.20.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@jest/reporters/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "devOptional": true, + "node_modules/@jest/globals/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "devOptional": true, + "node_modules/@jest/globals/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/test-result": { + "node_modules/@jest/globals/node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", + "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/test-sequencer": { + "node_modules/@jest/globals/node_modules/jest-mock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform": { + "node_modules/@jest/globals/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", + "@types/node": "*", "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", + "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "devOptional": true, + "node_modules/@jest/globals/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@jest/types/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@types/node": "*", + "jest-regex-util": "30.0.1" }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jest/reporters": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.5.tgz", + "integrity": "sha512-mafft7VBX4jzED1FwGC1o/9QUM2xebzavImZMeqnsklgcyxBto8mV4HzNSzUrryJ+8R9MFOM3HgYuDradWR+4g==", + "dev": true, "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@jest/snapshot-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.5.tgz", + "integrity": "sha512-XcCQ5qWHLvi29UUrowgDFvV4t7ETxX91CbDczMnoqXPOIcZOxyNdSjm6kV5XMc8+HkxfRegU/MUmnTbJRzGrUQ==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@kurkle/color": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", - "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", - "license": "MIT" - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "license": "MIT" - }, - "node_modules/@levischuck/tiny-cbor": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.2.tgz", - "integrity": "sha512-f5CnPw997Y2GQ8FAvtuVVC19FX8mwNNC+1XJcIi16n/LTJifKO6QBgGLgN3YEmqtGMk17SKSuoWES3imJVxAVw==", - "license": "MIT" - }, - "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.18.tgz", - "integrity": "sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q==", + "node_modules/@jest/snapshot-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/type": "^1.5.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=10" }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { - "mute-stream": "^1.0.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.1.5.tgz", - "integrity": "sha512-ue5PSOzHMCIYrfvPP/MRS6hsKKLzqqhcdAvJCO8uFlDdj598EhgnacuOTuqA6uBK5rgiZXfDWyb7DVZSiBKxBA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", - "license": "MIT", - "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@module-federation/bridge-react-webpack-plugin": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.7.6.tgz", - "integrity": "sha512-eD1JZDQ+h5WLdA58MmAE1DzLwvFaGJeeam3Tswc/sEUb4QGT86X4Fme+dMTBRYRoAq/tRYql3DlVTFhdmrUVzg==", + "node_modules/@jest/test-result": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.5.tgz", + "integrity": "sha512-wPyztnK0gbDMQAJZ43tdMro+qblDHH1Ru/ylzUo21TBKqt88ZqnKKK2m30LKmLLoKtR2lxdpCC/P3g1vfKcawQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "0.7.6", - "@types/semver": "7.5.8", - "semver": "7.6.3" + "@jest/console": "30.0.5", + "@jest/types": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@module-federation/data-prefetch": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.7.6.tgz", - "integrity": "sha512-AMpfnuIAK/Y5M682BUsnc13ARCEKhEvb0tXF4S+l7jfL08oE9gyo+G/nk0LIzZBO2mLDz5g2AydAERanM6gswQ==", + "node_modules/@jest/test-sequencer": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.5.tgz", + "integrity": "sha512-Aea/G1egWoIIozmDD7PBXUOxkekXl7ueGzrsGGi1SbeKgQqCYCIf+wfbflEbf2LiPxL8j2JZGLyrzZagjvW4YQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.7.6", - "@module-federation/sdk": "0.7.6", - "fs-extra": "9.1.0" + "@jest/test-result": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "slash": "^3.0.0" }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@module-federation/dts-plugin": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.7.6.tgz", - "integrity": "sha512-K8T8+Ip+fCQkTOxAQbAW47drphN36+WcvcOusn/fsIT+1exdhyvqxSCj8V7MLCtjA9kGDi0jHIGN6MN4p2cV0Q==", + "node_modules/@jest/transform": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.5.tgz", + "integrity": "sha512-Vk8amLQCmuZyy6GbBht1Jfo9RSdBtg7Lks+B0PecnjI8J+PCLQPGh7uI8Q/2wwpW2gLdiAfiHNsmekKlywULqg==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.7.6", - "@module-federation/managers": "0.7.6", - "@module-federation/sdk": "0.7.6", - "@module-federation/third-party-dts-extractor": "0.7.6", - "adm-zip": "^0.5.10", - "ansi-colors": "^4.1.3", - "axios": "^1.7.4", - "chalk": "3.0.0", - "fs-extra": "9.1.0", - "isomorphic-ws": "5.0.0", - "koa": "2.15.3", - "lodash.clonedeepwith": "4.5.0", - "log4js": "6.9.1", - "node-schedule": "2.1.1", - "rambda": "^9.1.0", - "ws": "8.18.0" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" + "@babel/core": "^7.27.4", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" }, - "peerDependenciesMeta": { - "vue-tsc": { - "optional": true - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@module-federation/dts-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -6418,46 +6449,42 @@ "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@module-federation/error-codes": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.7.6.tgz", - "integrity": "sha512-XVzX/sRFj1h5JvOOVMoFppxq0t1t3o/AlEICHgWX+dybIwJgz9g4gihZOWVZfz5/xsKGcUwdH5X7Z2nkuYhJEw==", + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, - "node_modules/@module-federation/managers": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.7.6.tgz", - "integrity": "sha512-NW0LJ6TL13oN004D9e50EalcGZyTYHHgyaeKOc90Omb/HMeHxjyhHx7wl1TLRwVN2E5Rk+IO0JrwgrdlNMfAzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@module-federation/sdk": "0.7.6", - "find-pkg": "2.0.0", - "fs-extra": "9.1.0" - } - }, - "node_modules/@module-federation/manifest": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.7.6.tgz", - "integrity": "sha512-xBrFwLjDMUjKRnp+P4X29ZNyhgXSsp+SfrBxVsKJpEESOHalDoNClbo6gXvZAvkBZyo9sY3SJhAwduDwNkg04w==", + "node_modules/@jest/types": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", + "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/dts-plugin": "0.7.6", - "@module-federation/managers": "0.7.6", - "@module-federation/sdk": "0.7.6", - "chalk": "3.0.0", - "find-pkg": "2.0.0" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@module-federation/manifest/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -6465,113 +6492,200 @@ "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@module-federation/rspack": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.7.6.tgz", - "integrity": "sha512-alfX85C+2AQLXGrtpa08ImwhHIGwFIkJ/6i/XhxpYL5iFu0mC0xRIJPJUw0tiBWdFpP4p+Ykij3hP3FqfvaiKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.7.6", - "@module-federation/dts-plugin": "0.7.6", - "@module-federation/managers": "0.7.6", - "@module-federation/manifest": "0.7.6", - "@module-federation/runtime-tools": "0.7.6", - "@module-federation/sdk": "0.7.6" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" + "node": ">=10" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@module-federation/runtime": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.7.6.tgz", - "integrity": "sha512-TEEDbGwaohZ2dMa+Sk/Igq8XpcyfjqJfbL20mdAZeifSFVZYRSCaTd/xIXP7pEw8+5BaCMc4YfCf/XcjFAUrVA==", - "dev": true, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.7.6", - "@module-federation/sdk": "0.7.6" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@module-federation/runtime-tools": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.7.6.tgz", - "integrity": "sha512-SvokF6gn2sNrTEPG51H0LrowHnf3iNfznO2PzKpxAhZOBdb1pm0wJPwWSMHYrjMdDpjr7bzaqAywnkHdA6lqeQ==", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", + "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "devOptional": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.7.6", - "@module-federation/webpack-bundler-runtime": "0.7.6" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@module-federation/sdk": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.7.6.tgz", - "integrity": "sha512-MFE+RtsHnutZOCp2eKpa3A/yzZ8tOPmjX7QRdVnB2qqR9JA2SH3ZP5+cYq76tzFQZvU1BCWAQVNMvqGOW2yVZQ==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "license": "MIT", "dependencies": { - "isomorphic-rslog": "0.0.6" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@module-federation/third-party-dts-extractor": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.7.6.tgz", - "integrity": "sha512-JME76/rgr41AKXG6kUTQXdQJiMCypN3qHOgPv4VuIag10UdLo/0gdeN6PYronvYmvPOQMfYev80GcEwl4l531A==", + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.4.0.tgz", + "integrity": "sha512-Akn8XZqN3xO9YGcgvIiTauBBXTP92QSvw6EcGha+p5nm7brhbwvev5gw4fi+ouLGrBpfPpb72+S5pxl4mkMIGQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.8.0.tgz", + "integrity": "sha512-HeR0JQNEdBozt+FrfyM5T0X3R+fIN0D+BRDkxPP5o41fTWzHfeZEqtK16aTW8haU+h+SG7XYq9PP5kobvOmkSA==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@keyv/redis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@keyv/redis/-/redis-4.4.0.tgz", + "integrity": "sha512-n/KEj3S7crVkoykggqsMUtcjNGvjagGPlJYgO/r6m9hhGZfhp1txJElHxcdJ1ANi/LJoBuOSILj15g6HD2ucqQ==", "license": "MIT", "dependencies": { - "find-pkg": "2.0.0", - "fs-extra": "9.1.0", - "resolve": "1.22.8" + "@redis/client": "^1.6.0", + "cluster-key-slot": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.3.3" } }, - "node_modules/@module-federation/third-party-dts-extractor/node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/@keyv/serialize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.0.tgz", + "integrity": "sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==", + "license": "MIT", + "peer": true + }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@levischuck/tiny-cbor": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz", + "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==", + "license": "MIT" + }, + "node_modules/@listr2/prompt-adapter-inquirer": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.22.tgz", + "integrity": "sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@inquirer/type": "^1.5.5" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@inquirer/prompts": ">= 3 < 8" } }, - "node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.7.6.tgz", - "integrity": "sha512-kB9hQ0BfwNAcQWGskDEOxYP2z2bB/1ABXKr8MDomCFl2mbW3vvfYMQrb8UhJmJvE3rbGI/iXhJUdgBLNREnjUg==", + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", + "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.7.6", - "@module-federation/sdk": "0.7.6" + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.1.tgz", + "integrity": "sha512-kKeP5PaY3bFrrF6GY5aDd96iuh1eoS+5CHJ+7hIP629KIEwzGNwbIzBmEX9TAhRJOivSRDTHCIsbu//+NsYKkg==", "cpu": [ "arm64" ], @@ -6581,7895 +6695,12768 @@ "darwin" ] }, - "node_modules/@napi-rs/nice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz", - "integrity": "sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ==", + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.1.tgz", + "integrity": "sha512-9CMB3seTyHs3EOVWdKiB8IIEDBJ3Gq00Tqyi0V7DS3HL90BjM/AkbZGuhzXwPrfeFazR24SKaRrUQF74f+CmWw==", + "cpu": [ + "x64" + ], "license": "MIT", "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.0.1", - "@napi-rs/nice-android-arm64": "1.0.1", - "@napi-rs/nice-darwin-arm64": "1.0.1", - "@napi-rs/nice-darwin-x64": "1.0.1", - "@napi-rs/nice-freebsd-x64": "1.0.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.0.1", - "@napi-rs/nice-linux-arm64-gnu": "1.0.1", - "@napi-rs/nice-linux-arm64-musl": "1.0.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.0.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.0.1", - "@napi-rs/nice-linux-s390x-gnu": "1.0.1", - "@napi-rs/nice-linux-x64-gnu": "1.0.1", - "@napi-rs/nice-linux-x64-musl": "1.0.1", - "@napi-rs/nice-win32-arm64-msvc": "1.0.1", - "@napi-rs/nice-win32-ia32-msvc": "1.0.1", - "@napi-rs/nice-win32-x64-msvc": "1.0.1" - } + "os": [ + "darwin" + ] }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.1.tgz", - "integrity": "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA==", + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.1.tgz", + "integrity": "sha512-1Mi69vU0akHgCI7tF6YbimPaNEKJiBm/p5A+aM8egr0joj27cQmCCOm2mZQ+Ht2BqmCfZaIgQnMg4gFYNMlpCA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.1.tgz", + "integrity": "sha512-d0vuXOdoKjHHJYZ/CRWopnkOiUpev+bgBBW+1tXtWsYWUj8uxl9ZmTBEmsL5mjUlpQDrlYiJSrhOU1hg5QWBSw==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.1.tgz", + "integrity": "sha512-00RbEpvfnyPodlICiGFuiOmyvWaL9nzCRSqZz82BVFsGTiSQnnF0gpD1C8tO6OvtptELbtRuM7BS9f97LcowZw==", + "cpu": [ + "x64" ], - "engines": { - "node": ">= 10" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", - "dev": true, + "node_modules/@lmdb/lmdb-win32-arm64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.1.tgz", + "integrity": "sha512-4h8tm3i1ODf+28UyqQZLP7c2jmRM26AyEEyYp994B4GiBdGvGAsYUu3oiHANYK9xFpvLuFzyGeqFm1kdNC0D1A==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@nestjs/bull": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.0.1.tgz", - "integrity": "sha512-1GcJ8BkHDgQdBMZ7SqAqgUHiFnISXmpGvewFeTc8wf87JLk2PweiKv9j9/KQKU+NI237pCe82XB0bXzTnsdxSw==", + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.1.tgz", + "integrity": "sha512-HqqKIhTbq6piJhkJpTTf3w1m/CgrmwXRAL9R9j7Ru5xdZSeO7Mg4AWiBC9B00uXR+LvVZKtUyRMVZfhmIZztmQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@nestjs/bull-shared": "^10.0.1", - "tslib": "2.6.0" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "bull": "^3.3 || ^4.0.0" + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/@nestjs/bull-shared": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.3.tgz", - "integrity": "sha512-XcgAjNOgq6b5DVCytxhR5BKiwWo7hsusVeyE7sfFnlXRHeEtIuC2hYWBr/ZAtvL/RH0/O0tqtq0rVl972nbhJw==", + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "2.8.1" + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@nestjs/bull-shared/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@nestjs/cache-manager": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-2.2.2.tgz", - "integrity": "sha512-+n7rpU1QABeW2WV17Dl1vZCG3vWjJU1MaamWgZvbGxYE9EeCM0lVLfw3z7acgDTNwOy+K68xuQPoIMxD0bhjlA==", + "node_modules/@mermaid-js/parser": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.2.tgz", + "integrity": "sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==", "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "cache-manager": "<=5", - "rxjs": "^7.0.0" + "optional": true, + "dependencies": { + "langium": "3.3.1" } }, - "node_modules/@nestjs/common": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.1.3.tgz", - "integrity": "sha512-xSyXBwgcmiFwQqek1Urw/AL3pRPq9bp/tpgfTxmnJg3gP6XNUbx1fDr0de50irXgZYzFKfVFo9ptC3b2du5YKA==", + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.13.3.tgz", + "integrity": "sha512-bGwA78F/U5G2jrnsdRkPY3IwIwZeWUEfb5o764b79lb0rJmMT76TLwKhdNZOWakOQtedYefwIR4emisEMvInKA==", + "dev": true, "license": "MIT", "dependencies": { - "iterare": "1.2.1", - "tslib": "2.6.1", - "uid": "2.0.2" + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "license": "0BSD" + "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" }, - "node_modules/@nestjs/config": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.0.0.tgz", - "integrity": "sha512-fzASk1Uv6AjdE6uA1na8zpqRCXAhRpcfgpCVv3SAKlgJ3VR3bEjcI4G17WHLgLBsmPzI1ofdkSI451WLD1F1Rw==", + "node_modules/@modern-js/node-bundle-require": { + "version": "2.68.2", + "resolved": "https://registry.npmjs.org/@modern-js/node-bundle-require/-/node-bundle-require-2.68.2.tgz", + "integrity": "sha512-MWk/pYx7KOsp+A/rN0as2ji/Ba8x0m129aqZ3Lj6T6CCTWdz0E/IsamPdTmF9Jnb6whQoBKtWSaLTCQlmCoY0Q==", + "dev": true, "license": "MIT", "dependencies": { - "dotenv": "16.1.4", - "dotenv-expand": "10.0.0", - "lodash": "4.17.21", - "uuid": "9.0.0" + "@modern-js/utils": "2.68.2", + "@swc/helpers": "^0.5.17", + "esbuild": "0.25.5" + } + }, + "node_modules/@modern-js/utils": { + "version": "2.68.2", + "resolved": "https://registry.npmjs.org/@modern-js/utils/-/utils-2.68.2.tgz", + "integrity": "sha512-revom/i/EhKfI0STNLo/AUbv7gY0JY0Ni2gO6P/Z4cTyZZRgd5j90678YB2DGn+LtmSrEWtUphyDH5Jn1RKjgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@swc/helpers": "^0.5.17", + "caniuse-lite": "^1.0.30001520", + "lodash": "^4.17.21", + "rslog": "^1.1.0" + } + }, + "node_modules/@module-federation/bridge-react-webpack-plugin": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.17.1.tgz", + "integrity": "sha512-lv06kqarQJtXnOZ5Kd7SIH2mAi+O3cwqS5/EiSlXDNU5hBsqsInFMeHpj8nY0wwNzeYv4o7t/F1QFQkaqAVEwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/sdk": "0.17.1", + "@types/semver": "7.5.8", + "semver": "7.6.3" + } + }, + "node_modules/@module-federation/bridge-react-webpack-plugin/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13" + "engines": { + "node": ">=10" } }, - "node_modules/@nestjs/config/node_modules/dotenv": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", - "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", - "license": "BSD-2-Clause", + "node_modules/@module-federation/cli": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/cli/-/cli-0.17.1.tgz", + "integrity": "sha512-jXA/ZutIfEyk0va8Q0ufJcZoG/w5kyJj4xvV4/LXAfcAOv/aKR/Mp51YrAIDAyEJN8i05y+dLMzLRfhewFK4GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@modern-js/node-bundle-require": "2.68.2", + "@module-federation/dts-plugin": "0.17.1", + "@module-federation/sdk": "0.17.1", + "chalk": "3.0.0", + "commander": "11.1.0" + }, + "bin": { + "mf": "bin/mf.js" + }, "engines": { - "node": ">=12" + "node": ">=16.0.0" + } + }, + "node_modules/@module-federation/data-prefetch": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.17.1.tgz", + "integrity": "sha512-kRS9LWbK/agC2ybO2Y2Xj3JfoyyBxOxwpxwftl1KnuWBPafV6dpvKxn5ig3im5OWHsYLd/W8W4XyGsSQdVoyIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.17.1", + "@module-federation/sdk": "0.17.1", + "fs-extra": "9.1.0" }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/@nestjs/config/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "node_modules/@module-federation/dts-plugin": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.17.1.tgz", + "integrity": "sha512-cRvHorIlVBUfh2UCQySZ7026CyzCJqQxwFzF4E1kp+mmIGxRpr4wLZA8GshThYvwN6dkeHINuKuzFmErhtFhAQ==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "@module-federation/error-codes": "0.17.1", + "@module-federation/managers": "0.17.1", + "@module-federation/sdk": "0.17.1", + "@module-federation/third-party-dts-extractor": "0.17.1", + "adm-zip": "^0.5.10", + "ansi-colors": "^4.1.3", + "axios": "^1.8.2", + "chalk": "3.0.0", + "fs-extra": "9.1.0", + "isomorphic-ws": "5.0.0", + "koa": "2.16.1", + "lodash.clonedeepwith": "4.5.0", + "log4js": "6.9.1", + "node-schedule": "2.1.1", + "rambda": "^9.1.0", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } } }, - "node_modules/@nestjs/core": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.1.3.tgz", - "integrity": "sha512-VzK54TuacC3Vmq3b5xTyMVTlDNJeKbjpKfV9fNqm4TbIBm8ZPo3FC0osJAbAK4XwbVvv2Flq1yA3CutasupVjw==", - "hasInstallScript": true, + "node_modules/@module-federation/enhanced": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.17.1.tgz", + "integrity": "sha512-YEdHA/rXlydI+ecmsidM0imAhAgyN+fSCOWRJtm72Kx10J6kS2tN1/Zah/hf9C9Msj9OOl0w22aOo7/Sy0qRqg==", + "dev": true, "license": "MIT", "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.6.1", - "uid": "2.0.2" + "@module-federation/bridge-react-webpack-plugin": "0.17.1", + "@module-federation/cli": "0.17.1", + "@module-federation/data-prefetch": "0.17.1", + "@module-federation/dts-plugin": "0.17.1", + "@module-federation/error-codes": "0.17.1", + "@module-federation/inject-external-runtime-core-plugin": "0.17.1", + "@module-federation/managers": "0.17.1", + "@module-federation/manifest": "0.17.1", + "@module-federation/rspack": "0.17.1", + "@module-federation/runtime-tools": "0.17.1", + "@module-federation/sdk": "0.17.1", + "btoa": "^1.2.1", + "schema-utils": "^4.3.0", + "upath": "2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "bin": { + "mf": "bin/mf.js" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24", + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "@nestjs/microservices": { + "typescript": { "optional": true }, - "@nestjs/platform-express": { + "vue-tsc": { "optional": true }, - "@nestjs/websockets": { + "webpack": { "optional": true } } }, - "node_modules/@nestjs/core/node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", + "node_modules/@module-federation/error-codes": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.17.1.tgz", + "integrity": "sha512-n6Elm4qKSjwAPxLUGtwnl7qt4y1dxB8OpSgVvXBIzqI9p27a3ZXshLPLnumlpPg1Qudaj8sLnSnFtt9yGpt5yQ==", + "dev": true, "license": "MIT" }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "license": "0BSD" - }, - "node_modules/@nestjs/event-emitter": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.0.4.tgz", - "integrity": "sha512-quMiw8yOwoSul0pp3mOonGz8EyXWHSBTqBy8B0TbYYgpnG1Ix2wGUnuTksLWaaBiiOTDhciaZ41Y5fJZsSJE1Q==", + "node_modules/@module-federation/inject-external-runtime-core-plugin": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/inject-external-runtime-core-plugin/-/inject-external-runtime-core-plugin-0.17.1.tgz", + "integrity": "sha512-Wqi6VvPHK5LKkLPhXgabulHygQKDJxreWs+LyrA5/LFGXHwD/7cM+V/xHriVJIbU+5HeKBT7y0Jyfe6uW1p/dQ==", + "dev": true, "license": "MIT", - "dependencies": { - "eventemitter2": "6.4.9" - }, "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + "@module-federation/runtime-tools": "0.17.1" } }, - "node_modules/@nestjs/jwt": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.1.0.tgz", - "integrity": "sha512-iLwCGS25ybUxGS7i5j/Mwuyzvp/WxJftHlm8aLEBv5GV92apz6L1QVjxLdZrqXbzo++C8gdJauhzil8qitY+6w==", + "node_modules/@module-federation/managers": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.17.1.tgz", + "integrity": "sha512-jMWD3w1j7n47EUNr44DXjvuEDQU4BjS7fanPN+1tTwUzuCYEnkaQKXDalv583VDKm4vP8s1TaJVIyjz+uTWiMQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/jsonwebtoken": "9.0.2", - "jsonwebtoken": "9.0.0" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" + "@module-federation/sdk": "0.17.1", + "find-pkg": "2.0.0", + "fs-extra": "9.1.0" } }, - "node_modules/@nestjs/passport": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", - "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", + "node_modules/@module-federation/manifest": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.17.1.tgz", + "integrity": "sha512-0EM6hAB9E++MHDKBsFA8HmIUKHUjxVGZZTIaQNdmeCBNvL1KMp2eDuqrPaurlcrtrqpD7C7xwjmbIyYp5Us1xw==", + "dev": true, "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" + "dependencies": { + "@module-federation/dts-plugin": "0.17.1", + "@module-federation/managers": "0.17.1", + "@module-federation/sdk": "0.17.1", + "chalk": "3.0.0", + "find-pkg": "2.0.0" } }, - "node_modules/@nestjs/platform-express": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.1.3.tgz", - "integrity": "sha512-RSf7ooCrxiWJlWl3CLfpaYmAf3U0tRsN7pJakujWdvzVJU2EzVZTLcy1MtnSg/HBm9/Rvg98VI5QI6oOhOpt+A==", + "node_modules/@module-federation/node": { + "version": "2.7.10", + "resolved": "https://registry.npmjs.org/@module-federation/node/-/node-2.7.10.tgz", + "integrity": "sha512-Gyzeqzz54uy05QH7WIF+SdJbecC+B47EIPHi/WxnkAJSGMxFFckFrwpKqLCn45fXl06GDV25E9w5mGnZy5O0Pg==", + "dev": true, "license": "MIT", "dependencies": { - "body-parser": "1.20.2", - "cors": "2.8.5", - "express": "4.18.2", - "multer": "1.4.4-lts.1", - "tslib": "2.6.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "@module-federation/enhanced": "0.17.1", + "@module-federation/runtime": "0.17.1", + "@module-federation/sdk": "0.17.1", + "btoa": "1.2.1", + "encoding": "^0.1.13", + "node-fetch": "2.7.0" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0" + "react": "^16||^17||^18||^19", + "react-dom": "^16||^17||^18||^19", + "webpack": "^5.40.0" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, - "node_modules/@nestjs/platform-express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "node_modules/@module-federation/rspack": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.17.1.tgz", + "integrity": "sha512-TMLaMcQjRTjVPzOi5USFDkf3Js3vHIlQm1wgzbe4Ok70vW9gHUQ+7LHFDWTt5byKoHeZJbzEr4c5zJCo6WBTKA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "@module-federation/bridge-react-webpack-plugin": "0.17.1", + "@module-federation/dts-plugin": "0.17.1", + "@module-federation/inject-external-runtime-core-plugin": "0.17.1", + "@module-federation/managers": "0.17.1", + "@module-federation/manifest": "0.17.1", + "@module-federation/runtime-tools": "0.17.1", + "@module-federation/sdk": "0.17.1", + "btoa": "1.2.1" + }, + "peerDependencies": { + "@rspack/core": ">=0.7", + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } } }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@module-federation/runtime": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.17.1.tgz", + "integrity": "sha512-vKEN32MvUbpeuB/s6UXfkHDZ9N5jFyDDJnj83UTJ8n4N1jHIJu9VZ6Yi4/Ac8cfdvU8UIK9bIbfVXWbUYZUDsw==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "@module-federation/error-codes": "0.17.1", + "@module-federation/runtime-core": "0.17.1", + "@module-federation/sdk": "0.17.1" } }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "node_modules/@module-federation/runtime-core": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.17.1.tgz", + "integrity": "sha512-LCtIFuKgWPQ3E+13OyrVpuTPOWBMI/Ggwsq1Q874YeT8Px28b8tJRCj09DjyRFyhpSPyV/uG80T6iXPAUoLIfQ==", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "@module-federation/error-codes": "0.17.1", + "@module-federation/sdk": "0.17.1" } }, - "node_modules/@nestjs/platform-express/node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "node_modules/@module-federation/runtime-tools": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.17.1.tgz", + "integrity": "sha512-4kr6zTFFwGywJx6whBtxsc84V+COAuuBpEdEbPZN//YLXhNB0iz2IGsy9r9wDl+06h84bD+3dQ05l9euRLgXzQ==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "@module-federation/runtime": "0.17.1", + "@module-federation/webpack-bundler-runtime": "0.17.1" } }, - "node_modules/@nestjs/platform-express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } + "node_modules/@module-federation/sdk": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.17.1.tgz", + "integrity": "sha512-nlUcN6UTEi+3HWF+k8wPy7gH0yUOmCT+xNatihkIVR9REAnr7BUvHFGlPJmx7WEbLPL46+zJUbtQHvLzXwFhng==", + "dev": true, + "license": "MIT" }, - "node_modules/@nestjs/platform-express/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/@module-federation/third-party-dts-extractor": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.17.1.tgz", + "integrity": "sha512-hGvy1Tqathc34G4Tx7WJgpK0203oDFA/qSPIhPpsWg27em3fCWozLczVsq+lOxxCM6llDRgC1kt/EpWeqEK/ng==", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "find-pkg": "2.0.0", + "fs-extra": "9.1.0", + "resolve": "1.22.8" } }, - "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/@module-federation/third-party-dts-extractor/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">= 0.8" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@nestjs/platform-express/node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.17.1.tgz", + "integrity": "sha512-Swspdgf4PzcbvS9SNKFlBzfq8h/Qxwqjq/xRSqw1pqAZWondZQzwTTqPXhgrg0bFlz7qWjBS/6a8KuH/gRvGaQ==", + "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" + "@module-federation/runtime": "0.17.1", + "@module-federation/sdk": "0.17.1" } }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "license": "0BSD" - }, - "node_modules/@nestjs/schedule": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-3.0.2.tgz", - "integrity": "sha512-INhpzkyquosLbVrXx4v+rfAnomwBTgKQvs7e9BZ2LSZdWQOqCQD2PmvWDiu8c4wdJIH6wcWQh98w5KxIcKuVBA==", + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "cron": "2.4.0", - "uuid": "9.0.0" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.12" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@nestjs/schedule/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@nestjs/schematics": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.0.1.tgz", - "integrity": "sha512-buxpYtSwOmWyf0nUJWJCkCkYITwbOfIEKHTnGS7sDbcfaajrOFXb5pPAGD2E1CUb3C1+NkQIURPKzs0IouZTQg==", - "dev": true, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@angular-devkit/core": "16.1.0", - "@angular-devkit/schematics": "16.1.0", - "comment-json": "4.2.3", - "jsonc-parser": "3.2.0", - "pluralize": "8.0.0" - }, - "peerDependencies": { - "typescript": ">=4.8.2" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.0.tgz", - "integrity": "sha512-mrWpuDvttmhrCGcLc68RIXKtTzUhkBTsE5ZZFZNO1+FSC+vO/ZpyCpPd6C+6coM68NfXYjHlms5XF6KbxeGn/Q==", - "dev": true, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.1.0.tgz", - "integrity": "sha512-LM35PH9DT3eQRSZgrkk2bx1ZQjjVh8BCByTlr37/c+FnF9mNbeBsa1YkxrlsN/CwO+045OwEwRHnkM9Zcx0U/A==", - "dev": true, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@angular-devkit/core": "16.1.0", - "jsonc-parser": "3.2.0", - "magic-string": "0.30.0", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@nestjs/schematics/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@nestjs/schematics/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, + "node_modules/@napi-rs/nice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.4.tgz", + "integrity": "sha512-Sqih1YARrmMoHlXGgI9JrrgkzxcaaEso0AH+Y7j8NHonUs+xe4iDsgC3IBIDNdzEewbNpccNN6hip+b5vmyRLw==", "license": "MIT", "optional": true, - "peer": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, "engines": { - "node": ">= 8.10.0" + "node": ">= 10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@nestjs/schematics/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", + "@napi-rs/nice-android-arm-eabi": "1.0.4", + "@napi-rs/nice-android-arm64": "1.0.4", + "@napi-rs/nice-darwin-arm64": "1.0.4", + "@napi-rs/nice-darwin-x64": "1.0.4", + "@napi-rs/nice-freebsd-x64": "1.0.4", + "@napi-rs/nice-linux-arm-gnueabihf": "1.0.4", + "@napi-rs/nice-linux-arm64-gnu": "1.0.4", + "@napi-rs/nice-linux-arm64-musl": "1.0.4", + "@napi-rs/nice-linux-ppc64-gnu": "1.0.4", + "@napi-rs/nice-linux-riscv64-gnu": "1.0.4", + "@napi-rs/nice-linux-s390x-gnu": "1.0.4", + "@napi-rs/nice-linux-x64-gnu": "1.0.4", + "@napi-rs/nice-linux-x64-musl": "1.0.4", + "@napi-rs/nice-win32-arm64-msvc": "1.0.4", + "@napi-rs/nice-win32-ia32-msvc": "1.0.4", + "@napi-rs/nice-win32-x64-msvc": "1.0.4" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.0.4.tgz", + "integrity": "sha512-OZFMYUkih4g6HCKTjqJHhMUlgvPiDuSLZPbPBWHLjKmFTv74COzRlq/gwHtmEVaR39mJQ6ZyttDl2HNMUbLVoA==", + "cpu": [ + "arm" + ], + "license": "MIT", "optional": true, - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, + "os": [ + "android" + ], "engines": { - "node": ">= 6" + "node": ">= 10" } }, - "node_modules/@nestjs/schematics/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.0.4.tgz", + "integrity": "sha512-k8u7cjeA64vQWXZcRrPbmwjH8K09CBnNaPnI9L1D5N6iMPL3XYQzLcN6WwQonfcqCDv5OCY3IqX89goPTV4KMw==", + "cpu": [ + "arm64" + ], "license": "MIT", "optional": true, - "peer": true, + "os": [ + "android" + ], "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">= 10" } }, - "node_modules/@nestjs/schematics/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-GsLdQvUcuVzoyzmtjsThnpaVEizAqH5yPHgnsBmq3JdVoVZHELFo7PuJEdfOH1DOHi2mPwB9sCJEstAYf3XCJA==", + "cpu": [ + "arm64" + ], "license": "MIT", "optional": true, - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" - }, + "os": [ + "darwin" + ], "engines": { - "node": ">=8.10.0" + "node": ">= 10" } }, - "node_modules/@nestjs/schematics/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.0.4.tgz", + "integrity": "sha512-1y3gyT3e5zUY5SxRl3QDtJiWVsbkmhtUHIYwdWWIQ3Ia+byd/IHIEpqAxOGW1nhhnIKfTCuxBadHQb+yZASVoA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@nestjs/schematics/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.0.4.tgz", + "integrity": "sha512-06oXzESPRdXUuzS8n2hGwhM2HACnDfl3bfUaSqLGImM8TA33pzDXgGL0e3If8CcFWT98aHows5Lk7xnqYNGFeA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/@nestjs/serve-static": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-4.0.0.tgz", - "integrity": "sha512-8cTrNV2ngdHIjiLNsXePnw0+KY1ThrZGz/WeyAG5gIvmZNDbnZBOrPoYlKL+MOzlXlQStxR5jKLYmn+nJeoncQ==", + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.0.4.tgz", + "integrity": "sha512-CgklZ6g8WL4+EgVVkxkEvvsi2DSLf9QIloxWO0fvQyQBp6VguUSX3eHLeRpqwW8cRm2Hv/Q1+PduNk7VK37VZw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "path-to-regexp": "0.2.5" - }, - "peerDependencies": { - "@fastify/static": "^6.5.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "express": "^4.18.1", - "fastify": "^4.7.0" - }, - "peerDependenciesMeta": { - "@fastify/static": { - "optional": true - }, - "express": { - "optional": true - }, - "fastify": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@nestjs/serve-static/node_modules/path-to-regexp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.2.5.tgz", - "integrity": "sha512-l6qtdDPIkmAmzEO6egquYDfqQGPMRNGjYtrU13HAXb3YSRrt7HSb1sJY0pKp6o2bAa86tSB6iwaW2JbthPKr7Q==", - "license": "MIT" + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.0.4.tgz", + "integrity": "sha512-wdAJ7lgjhAlsANUCv0zi6msRwq+D4KDgU+GCCHssSxWmAERZa2KZXO0H2xdmoJ/0i03i6YfK/sWaZgUAyuW2oQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@nestjs/testing": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.1.3.tgz", - "integrity": "sha512-zMrO9xLPYnKtC6q1diWubuMshIp0v2aGHa58jcIfZaAlJlU/6RKsgCOiFQ42aFzxUEBRWF0LBF0aiwt04LKMyQ==", - "dev": true, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.0.4.tgz", + "integrity": "sha512-4b1KYG+sriufhFrpUS9uNOEYYJqSfcbnwGx6uGX7JjrH8tELG90cOpCawz5THNIwlS3DhLgnCOcn0+4p6z26QA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "tslib": "2.6.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@nestjs/testing/node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "dev": true, - "license": "0BSD" + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.0.4.tgz", + "integrity": "sha512-iaf3vMRgr23oe1PUaKpxaH3DS0IMN0+N9iEiWVwYPm/U15vZFYdqVegGfN2PzrZLUl5lc8ZxbmEKDfuqslhAMA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.0.4.tgz", + "integrity": "sha512-UXoREY6Yw6rHrGuTwQgBxpfjK34t6mTjibE9/cXbefL9AuUCJ9gEgwNKZiONuR5QGswChqo9cnthjdKkYyAdDg==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.0.4.tgz", + "integrity": "sha512-eFbgYCRPmsqbYPAlLYU5hYTNbogmIDUvknilehHsFhCH1+0/kN87lP+XaLT0Yeq4V/rpwChSd9vlz4muzFArtw==", + "cpu": [ + "s390x" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.0.4.tgz", + "integrity": "sha512-4T3E6uTCwWT6IPnwuPcWVz3oHxvEp/qbrCxZhsgzwTUBEwu78EGNXGdHfKJQt3soth89MLqZJw+Zzvnhrsg1mQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/@npmcli/agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", - "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.0.4.tgz", + "integrity": "sha512-NtbBkAeyBPLvCBkWtwkKXkNSn677eaT0cX3tygq+2qVv71TmHgX4gkX6o9BXjlPzdgPGwrUudavCYPT9tzkEqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 10" } }, - "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.0.4.tgz", + "integrity": "sha512-vubOe3i+YtSJGEk/++73y+TIxbuVHi+W8ZzrRm2eETCjCRwNlgbfToQZ85dSA+4iBB/NJRGNp+O4hfdbbttZWA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 14" + "node": ">= 10" } }, - "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.0.4.tgz", + "integrity": "sha512-BMOVrUDZeg1RNRKVlh4eyLv5djAAVLiSddfpuuQ47EFjBcklg0NUeKMFKNrKQR4UnSn4HAiACLD7YK7koskwmg==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 14" + "node": ">= 10" } }, - "node_modules/@npmcli/fs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", - "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.0.4.tgz", + "integrity": "sha512-kCNk6HcRZquhw/whwh4rHsdPyOSCQCgnVDVik+Y9cuSVTDy3frpiCJTScJqPPS872h4JgZKkr/+CwcwttNEo9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 10" } }, - "node_modules/@npmcli/git": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-6.0.1.tgz", - "integrity": "sha512-BBWMMxeQzalmKadyimwb2/VVQyJB01PH0HhVSNLHNBDZN/M/h/02P6f8fxedIiFhpMj11SO9Ep5tKTBE7zL2nw==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.1.tgz", + "integrity": "sha512-KVlQ/jgywZpixGCKMNwxStmmbYEMyokZpCf2YuIChhfJA2uqfAKNEM8INz7zzTo55iEXfBhIIs3VqYyqzDLj8g==", "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, "dependencies": { - "@npmcli/promise-spawn": "^8.0.0", - "ini": "^5.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^10.0.0", - "proc-log": "^5.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@npmcli/installed-package-contents": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", - "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/bull": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-11.0.2.tgz", + "integrity": "sha512-RjyP9JZUuLmMhmq1TMNIZqolkAd14az1jyXMMVki+C9dYvaMjWzBSwcZAtKs9Pk15Rm7qN1xn3R11aMV2Xv4gg==", + "license": "MIT", "dependencies": { - "npm-bundled": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" + "@nestjs/bull-shared": "^11.0.2", + "tslib": "2.8.1" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-4.0.0.tgz", - "integrity": "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", + "bull": "^3.3 || ^4.0.0" } }, - "node_modules/@npmcli/package-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-6.1.0.tgz", - "integrity": "sha512-t6G+6ZInT4X+tqj2i+wlLIeCKnKOTuz9/VFYDtj+TGTur5q7sp/OYrQA19LdBbWfXDOi0Y4jtedV6xtB8zQ9ug==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/bull-shared": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.3.tgz", + "integrity": "sha512-CaHniPkLAxis6fAB1DB8WZELQv8VPCLedbj7iP0VQ1pz74i6NSzG9mBg6tOomXq/WW4la4P4OMGEQ48UAJh20A==", + "license": "MIT", "dependencies": { - "@npmcli/git": "^6.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "normalize-package-data": "^7.0.0", - "proc-log": "^5.0.0", - "semver": "^7.5.3" + "tslib": "2.8.1" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" } }, - "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/cache-manager": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.1.tgz", + "integrity": "sha512-4UxTnR0fsmKL5YDalU2eLFVnL+OBebWUpX+hEduKGncrVKH4PPNoiRn1kXyOCjmzb0UvWgqubpssNouc8e0MCw==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", + "cache-manager": ">=6", + "keyv": ">=5", + "rxjs": "^7.8.1" + } + }, + "node_modules/@nestjs/common": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.3.tgz", + "integrity": "sha512-ogEK+GriWodIwCw6buQ1rpcH4Kx+G7YQ9EwuPySI3rS05pSdtQ++UhucjusSI9apNidv+QURBztJkRecwwJQXg==", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "file-type": "21.0.0", + "iterare": "1.2.1", + "load-esm": "1.0.2", + "tslib": "2.8.1", + "uid": "2.0.2" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": ">=0.4.1", + "class-validator": ">=0.13.2", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", - "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", - "dev": true, + "node_modules/@nestjs/config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.2.tgz", + "integrity": "sha512-McMW6EXtpc8+CwTUwFdg6h7dYcBUpH5iUILCclAsa+MbCEvC9ZKu4dCHRlJqALuhjLw97pbQu62l4+wRwGeZqA==", "license": "MIT", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "dependencies": { + "dotenv": "16.4.7", + "dotenv-expand": "12.0.1", + "lodash": "4.17.21" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "rxjs": "^7.1.0" } }, - "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/core": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.3.tgz", + "integrity": "sha512-5lTni0TCh8x7bXETRD57pQFnKnEg1T6M+VLE7wAmyQRIecKQU+2inRGZD+A4v2DC1I04eA0WffP0GKLxjOKlzw==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@nuxt/opencollective": "0.4.1", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1", + "uid": "2.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 20" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, - "node_modules/@npmcli/promise-spawn": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.2.tgz", - "integrity": "sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/event-emitter": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-3.0.1.tgz", + "integrity": "sha512-0Ln/x+7xkU6AJFOcQI9tIhUMXVF7D5itiaQGOyJbXtlAfAIt8gzDdJm+Im7cFzKoWkiW5nCXCPh6GSvdQd/3Dw==", + "license": "MIT", "dependencies": { - "which": "^5.0.0" + "eventemitter2": "6.4.9" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@npmcli/redact": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-3.0.0.tgz", - "integrity": "sha512-/1uFzjVcfzqrgCeGW7+SZ4hv0qLWmKXVzFahZGJ6QuJBj6Myt9s17+JL86i76NV9YSnJRcGXJYQbAU0rn1YTCQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" } }, - "node_modules/@npmcli/run-script": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-9.0.2.tgz", - "integrity": "sha512-cJXiUlycdizQwvqE1iaAb4VRUM3RX09/8q46zjvy+ct9GhfZRWd7jXYVc1tn/CfRlGPVkX/u4sstRlepsm7hfw==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/jwt": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.0.tgz", + "integrity": "sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==", + "license": "MIT", "dependencies": { - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "node-gyp": "^11.0.0", - "proc-log": "^5.0.0", - "which": "^5.0.0" + "@types/jsonwebtoken": "9.0.7", + "jsonwebtoken": "9.0.2" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "node_modules/@nestjs/passport": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz", + "integrity": "sha512-ulQX6mbjlws92PIM15Naes4F4p2JoxGnIJuUsdXQPT+Oo2sqQmENEZXM7eYuimocfHnKlcfZOuyzbA33LwUlOQ==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "passport": "^0.5.0 || ^0.6.0 || ^0.7.0" + } + }, + "node_modules/@nestjs/platform-express": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.3.tgz", + "integrity": "sha512-hEDNMlaPiBO72fxxX/CuRQL3MEhKRc/sIYGVoXjrnw6hTxZdezvvM6A95UaLsYknfmcZZa/CdG1SMBZOu9agHQ==", "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" + "cors": "2.8.5", + "express": "5.1.0", + "multer": "2.0.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1" }, - "bin": { - "opencollective": "bin/opencollective.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" } }, - "node_modules/@nx/angular": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-20.3.0.tgz", - "integrity": "sha512-QdgHkOza4f3brmyepHoMvpMKFyPXTGvp5R4zImq0hkwX4UguZyKgSEQV5ldOPsDxe9HOAgypXZnGo/CfQAdhmQ==", - "dev": true, + "node_modules/@nestjs/schedule": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-6.0.0.tgz", + "integrity": "sha512-aQySMw6tw2nhitELXd3EiRacQRgzUKD9mFcUZVOJ7jPLqIBvXOyvRWLsK9SdurGA+jjziAlMef7iB5ZEFFoQpw==", "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/eslint": "20.3.0", - "@nx/js": "20.3.0", - "@nx/module-federation": "20.3.0", - "@nx/web": "20.3.0", - "@nx/webpack": "20.3.0", - "@nx/workspace": "20.3.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "@typescript-eslint/type-utils": "^8.0.0", - "chalk": "^4.1.0", - "magic-string": "~0.30.2", - "minimatch": "9.0.3", - "piscina": "^4.4.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "webpack-merge": "^5.8.0" + "cron": "4.3.0" }, "peerDependencies": { - "@angular-devkit/build-angular": ">= 17.0.0 < 20.0.0", - "@angular-devkit/core": ">= 17.0.0 < 20.0.0", - "@angular-devkit/schematics": ">= 17.0.0 < 20.0.0", - "@schematics/angular": ">= 17.0.0 < 20.0.0", - "rxjs": "^6.5.3 || ^7.5.0" + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" } }, - "node_modules/@nx/angular/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "node_modules/@nestjs/schematics": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-11.0.5.tgz", + "integrity": "sha512-T50SCNyqCZ/fDssaOD7meBKLZ87ebRLaJqZTJPvJKjlib1VYhMOCwXYsr7bjMPmuPgiQHOwvppz77xN/m6GM7A==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@angular-devkit/core": "19.2.6", + "@angular-devkit/schematics": "19.2.6", + "comment-json": "4.2.5", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.8.2" } }, - "node_modules/@nx/angular/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.6.tgz", + "integrity": "sha512-WFgiYhrDMq83UNaGRAneIM7CYYdBozD+yYA9BjoU8AgBLKtrvn6S8ZcjKAk5heoHtY/u8pEb0mwDTz9gxFmJZQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/@nx/angular/node_modules/piscina": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.8.0.tgz", - "integrity": "sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==", + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.6.tgz", + "integrity": "sha512-YTAxNnT++5eflx19OUHmOWu597/TbTel+QARiZCv1xQw99+X8DCKKOUXtqBRd53CAHlREDI33Rn/JLY3NYgMLQ==", "dev": true, "license": "MIT", - "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" + "dependencies": { + "@angular-devkit/core": "19.2.6", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@nx/angular/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@nx/angular/node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "node_modules/@nestjs/schematics/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nx/cypress": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-20.3.0.tgz", - "integrity": "sha512-Fi4HOhz8JYPLrnmFDxgVK1lNTBb6ZZC0EiibFxqCeFdPOQFJx36VyzMNIdfGHI50TCBUsSzK5eWD/8NHSBuFUg==", + "node_modules/@nestjs/schematics/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/eslint": "20.3.0", - "@nx/js": "20.3.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "detect-port": "^1.5.1", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "cypress": ">= 3 < 14" + "restore-cursor": "^3.1.0" }, - "peerDependenciesMeta": { - "cypress": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/@nx/cypress/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nestjs/schematics/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "0BSD" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/@nx/devkit": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.3.0.tgz", - "integrity": "sha512-u9oRd2F33DLNWPbzpYGW7xuMEYUAOwO9DLP9nGYpxbZXy6Z4AdoKeqhN+KBTyg8+DyQGuKUSEXcWriDyLLgcHw==", + "node_modules/@nestjs/schematics/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "license": "MIT", "dependencies": { - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, - "peerDependencies": { - "nx": ">= 19 <= 21" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/devkit/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@nestjs/schematics/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/@nx/devkit/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nestjs/schematics/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "0BSD" + "license": "ISC" }, - "node_modules/@nx/eslint": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.3.0.tgz", - "integrity": "sha512-QhApF0HAcMm0tc7kXna4XuFUuO3oroWvGmvzGqBSa3GyuXbAz1VJ1RFWYkyQzjAsltaBcMUFCA+ORUM+PN1sWA==", - "dev": true, + "node_modules/@nestjs/serve-static": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-5.0.3.tgz", + "integrity": "sha512-0jFjTlSVSLrI+mot8lfm+h2laXtKzCvgsVStv9T1ZBZTDwS26gM5czIhIESmWAod0PfrbCDFiu9C1MglObL8VA==", "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.6.2" + "path-to-regexp": "8.2.0" }, "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "@fastify/static": "^8.0.4", + "@nestjs/common": "^11.0.2", + "@nestjs/core": "^11.0.2", + "express": "^5.0.1", + "fastify": "^5.2.1" }, "peerDependenciesMeta": { - "@zkochan/js-yaml": { + "@fastify/static": { + "optional": true + }, + "express": { + "optional": true + }, + "fastify": { "optional": true } } }, - "node_modules/@nx/eslint-plugin": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-20.3.0.tgz", - "integrity": "sha512-U9DvbR7quyfnWk8ZCJlwKbIInZ5gd4be93X5gii966vM81n3lbWLc7y4avU4r3732X2pnpFGJqBgP8ov8JE/fw==", + "node_modules/@nestjs/testing": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.3.tgz", + "integrity": "sha512-CeXG6/eEqgFIkPkmU00y18Dd3DLOIDFhPItzJK1SWckKo6IhcnfoRJzGx75bmuvUMjb51j6An96S/+MJ2ty9jA==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "@typescript-eslint/type-utils": "^8.0.0", - "@typescript-eslint/utils": "^8.0.0", - "chalk": "^4.1.0", - "confusing-browser-globals": "^1.0.9", - "globals": "^15.9.0", - "jsonc-eslint-parser": "^2.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0" + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", - "eslint-config-prettier": "^9.0.0" + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { "optional": true } } }, - "node_modules/@nx/eslint-plugin/node_modules/globals": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", - "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "node_modules/@ngtools/webpack": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.1.3.tgz", + "integrity": "sha512-u4Qy9ycBPlFE6cwNx4S1o7tetC0YvbF3lb7hNfb7e7qT45ZWngnvW+tMSU8JAgpx1M4xZPgOq+Gbeo5QPaW2cA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@angular/compiler-cli": "^20.0.0", + "typescript": ">=5.8 <5.9", + "webpack": "^5.54.0" } }, - "node_modules/@nx/eslint-plugin/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "0BSD" + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@nx/eslint/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "0BSD" + "license": "MIT", + "engines": { + "node": ">= 8" + } }, - "node_modules/@nx/jest": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.3.0.tgz", - "integrity": "sha512-szkmlq8Zgx1J04yq34HfbC1jGrELVXcJTfo76SnFonL9crnbBsLS2mPrvCe431Zm9Xs1PYNvxZLeIbxf6bVXcQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "2.0.3", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@nx/jest/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/jest/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@nx/js": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.3.0.tgz", - "integrity": "sha512-hnO1jzJUvO7+bBsC2uaUElpX9gpMiSA3wdt34V8nnPcIBWtdMrjKX7yRFSwZKimeNauesiX0uorTJf+z28R2bg==", + "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nx/devkit": "20.3.0", - "@nx/workspace": "20.3.0", - "@zkochan/js-yaml": "0.0.7", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "tinyglobby": "^0.2.10", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } + "engines": { + "node": ">= 14" } }, - "node_modules/@nx/js/node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } + "license": "ISC" }, - "node_modules/@nx/js/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "node_modules/@npmcli/fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" + "semver": "^7.3.5" }, "engines": { - "node": ">=8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "node_modules/@npmcli/git": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-6.0.3.tgz", + "integrity": "sha512-GUYESQlxZRAdhs3UhbB6pVRNUELQOHXwK9ruDkwmCv2aZ5y0SApQzUJCg02p3A7Ue2J5hxvlk1YI53c00NmRyQ==", "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^10.0.1" + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "isexe": "^3.1.1" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "bin": { + "node-which": "bin/which.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "node_modules/@npmcli/installed-package-contents": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", "dev": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/ora": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", - "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "node_modules/@npmcli/node-gyp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==", "dev": true, - "license": "MIT", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-6.2.0.tgz", + "integrity": "sha512-rCNLSB/JzNvot0SEyXqWZ7tX2B5dD2a1br2Dp0vSYVo5jh8Z0EZ7lS9TsZ1UtziddB1UfNUaMCc538/HztnJGA==", + "dev": true, + "license": "ISC", "dependencies": { - "bl": "^4.0.3", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "@npmcli/git": "^6.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "proc-log": "^5.0.0", + "semver": "^7.5.3", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "node_modules/@npmcli/promise-spawn": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.2.tgz", + "integrity": "sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==", "dev": true, "license": "ISC", + "dependencies": { + "which": "^5.0.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "license": "ISC", + "engines": { + "node": ">=16" } }, - "node_modules/@nx/js/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "isexe": "^3.1.1" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "node-which": "bin/which.js" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/js/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@npmcli/redact": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-3.2.2.tgz", + "integrity": "sha512-7VmYAmk4csGv08QzrDKScdzn11jHPFGyqJW39FyPgPuAp3zIaUmuCo1yxw9aGs+NEJuTGQ9Gwqpt93vtJubucg==", "dev": true, - "license": "0BSD" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, - "node_modules/@nx/js/node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "node_modules/@npmcli/run-script": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-9.1.0.tgz", + "integrity": "sha512-aoNSbxtkePXUlbZB+anS1LqsJdctG5n3UVhfU47+CDdwMi6uNTBMF9gPcQRnqghQd2FGzcwwIFBruFMxjhBewg==", "dev": true, "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "node-gyp": "^11.0.0", + "proc-log": "^5.0.0", + "which": "^5.0.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/module-federation": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/module-federation/-/module-federation-20.3.0.tgz", - "integrity": "sha512-txb3Gs9BkxnCo0Xo0EYqs8dRyScue4p6AcIxHHaTne469JS1qKzr0rGSpkL3j6KH5PAjfDpp8XZHtQg4Yd3TsQ==", + "node_modules/@npmcli/run-script/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@module-federation/enhanced": "0.7.6", - "@module-federation/node": "2.6.11", - "@module-federation/sdk": "0.7.6", - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "@nx/web": "20.3.0", - "@rspack/core": "^1.1.5", - "express": "^4.19.2", - "http-proxy-middleware": "^3.0.3", - "picocolors": "^1.1.0", - "tslib": "^2.3.0", - "webpack": "5.88.0" + "license": "ISC", + "engines": { + "node": ">=16" } }, - "node_modules/@nx/module-federation/node_modules/@module-federation/enhanced": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.7.6.tgz", - "integrity": "sha512-ivTVuRKhew/25fiblAW22RybYzyacQsvnQG3y9zSNsYbwcj+0u7THWMmsK8vNKxDUpjxuQulCK07BEycDjoB5Q==", + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.7.6", - "@module-federation/data-prefetch": "0.7.6", - "@module-federation/dts-plugin": "0.7.6", - "@module-federation/managers": "0.7.6", - "@module-federation/manifest": "0.7.6", - "@module-federation/rspack": "0.7.6", - "@module-federation/runtime-tools": "0.7.6", - "@module-federation/sdk": "0.7.6", - "btoa": "^1.2.1", - "upath": "2.0.1" + "isexe": "^3.1.1" }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24", - "webpack": "^5.0.0" + "bin": { + "node-which": "bin/which.js" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nx/module-federation/node_modules/@module-federation/node": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@module-federation/node/-/node-2.6.11.tgz", - "integrity": "sha512-ytCNML9Q9dQ7Xi/pTYp4Y+yP/YUiFyyCa8BEKnSt5Ipiqtu4QMxj46EkOIgvLv0nSlK+xOVgAzqtXLI89SfhCg==", - "dev": true, + "node_modules/@nuxt/opencollective": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", + "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", "license": "MIT", "dependencies": { - "@module-federation/enhanced": "0.7.6", - "@module-federation/runtime": "0.7.6", - "@module-federation/sdk": "0.7.6", - "@module-federation/utilities": "3.1.29", - "btoa": "1.2.1", - "encoding": "^0.1.13", - "node-fetch": "2.7.0" + "consola": "^3.2.3" }, - "peerDependencies": { - "react": "^16||^17||^18", - "react-dom": "^16||^17||^18", - "webpack": "^5.40.0" + "bin": { + "opencollective": "bin/opencollective.js" }, - "peerDependenciesMeta": { - "next": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "engines": { + "node": "^14.18.0 || >=16.10.0", + "npm": ">=5.10.0" } }, - "node_modules/@nx/module-federation/node_modules/@module-federation/utilities": { - "version": "3.1.29", - "resolved": "https://registry.npmjs.org/@module-federation/utilities/-/utilities-3.1.29.tgz", - "integrity": "sha512-yhHOgm3mkZBvQzT4HoBJAVhGIa7Nfhpd4Zdc11g0vYEMapU6lfN5HHipUFdj6bLUzHhDyrY6CaF3syqTuabAfQ==", + "node_modules/@nx/angular": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-21.3.9.tgz", + "integrity": "sha512-QZ3aRvNLGCl/s2IV5hqklw5T00tAzPuIbCh5VUg5Fqk3dirHuZq2DXMCMzm0KB8rBnVKS8zx4I5je1zYROAb8g==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "0.7.6" + "@nx/devkit": "21.3.9", + "@nx/eslint": "21.3.9", + "@nx/js": "21.3.9", + "@nx/module-federation": "21.3.9", + "@nx/rspack": "21.3.9", + "@nx/web": "21.3.9", + "@nx/webpack": "21.3.9", + "@nx/workspace": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "@typescript-eslint/type-utils": "^8.0.0", + "enquirer": "~2.3.6", + "magic-string": "~0.30.2", + "picocolors": "^1.1.0", + "picomatch": "4.0.2", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "webpack-merge": "^5.8.0" }, "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18", - "webpack": "^5.40.0" + "@angular-devkit/build-angular": ">= 18.0.0 < 21.0.0", + "@angular-devkit/core": ">= 18.0.0 < 21.0.0", + "@angular-devkit/schematics": ">= 18.0.0 < 21.0.0", + "@angular/build": ">= 18.0.0 < 21.0.0", + "@schematics/angular": ">= 18.0.0 < 21.0.0", + "ng-packagr": ">= 18.0.0 < 21.0.0", + "rxjs": "^6.5.3 || ^7.5.0" }, "peerDependenciesMeta": { - "next": { + "@angular-devkit/build-angular": { "optional": true }, - "react": { + "@angular/build": { "optional": true }, - "react-dom": { + "ng-packagr": { "optional": true } } }, - "node_modules/@nx/module-federation/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@nx/angular/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@nx/module-federation/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/@nx/cypress": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-21.3.9.tgz", + "integrity": "sha512-d0o/Yy3urzxFde6IHjUsvBoA0PVFgitiZNF8xlkeliJjuC3NTyrqzJdKYagwnJ8UZXftiQ/1kh4c74wVAPO/wg==", "dev": true, "license": "MIT", + "dependencies": { + "@nx/devkit": "21.3.9", + "@nx/eslint": "21.3.9", + "@nx/js": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "detect-port": "^1.5.1", + "semver": "^7.6.3", + "tree-kill": "1.2.2", + "tslib": "^2.3.0" + }, "peerDependencies": { - "ajv": "^6.9.1" + "cypress": ">= 3 < 15" + }, + "peerDependenciesMeta": { + "cypress": { + "optional": true + } } }, - "node_modules/@nx/module-federation/node_modules/http-proxy-middleware": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", - "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", + "node_modules/@nx/devkit": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-21.3.9.tgz", + "integrity": "sha512-Z9Lz8VsDKy8Eb6PBqpdd3YZ6pJcCA/Hjt/8Li1VSsO2CyMfGFpm2pnCtdEc9wvBuIogEMisF4yVnMujKW1dHHw==", "dev": true, "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.15", - "debug": "^4.3.6", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.3", - "is-plain-object": "^5.0.0", - "micromatch": "^4.0.8" + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "nx": "21.3.9" } }, - "node_modules/@nx/module-federation/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/@nx/devkit/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "node_modules/@nx/module-federation/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/@nx/devkit/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/module-federation/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@nx/module-federation/node_modules/webpack": { - "version": "5.88.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.0.tgz", - "integrity": "sha512-O3jDhG5e44qIBSi/P6KpcCcH7HD+nYIHVBhdWFxcLOcIGN8zGo5nqF3BjyNCxIh4p1vFdNnreZv2h2KkoAw3lw==", + "node_modules/@nx/eslint": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-21.3.9.tgz", + "integrity": "sha512-R1C4zNJmbkSU3BpQ7Jbz6yg9RgdTrkUmrldWe/BH9D1tmiA8lMOVMm9rLthixQFIqf9V8sSoye/4SmWgImVekA==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.8.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" }, "peerDependenciesMeta": { - "webpack-cli": { + "@zkochan/js-yaml": { "optional": true } } }, - "node_modules/@nx/nest": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-20.3.0.tgz", - "integrity": "sha512-z7yjlS0Z0TNxEUU+pVkIRCFkrtRnvKjmOwIzj4DfHR8/SoF+0x06IPo+ZFHFOLe/DDjZuNOqjqzOQmQY1VhINw==", + "node_modules/@nx/eslint-plugin": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-21.3.9.tgz", + "integrity": "sha512-2Btr+njq8owkJERAsVnJhAJMZgSjvAkFcpD3k2pmhPXg59YuvJElEqndmRKrWo8239CjaxPDVcBm0C/JnlEiXw==", "dev": true, "license": "MIT", "dependencies": { - "@nestjs/schematics": "^9.1.0", - "@nx/devkit": "20.3.0", - "@nx/eslint": "20.3.0", - "@nx/js": "20.3.0", - "@nx/node": "20.3.0", + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "@typescript-eslint/type-utils": "^8.0.0", + "@typescript-eslint/utils": "^8.0.0", + "chalk": "^4.1.0", + "confusing-browser-globals": "^1.0.9", + "globals": "^15.9.0", + "jsonc-eslint-parser": "^2.1.0", + "semver": "^7.5.3", "tslib": "^2.3.0" - } - }, - "node_modules/@nx/nest/node_modules/@angular-devkit/core": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", - "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" }, "peerDependencies": { - "chokidar": "^3.5.2" + "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", + "eslint-config-prettier": "^10.0.0" }, "peerDependenciesMeta": { - "chokidar": { + "eslint-config-prettier": { "optional": true } } }, - "node_modules/@nx/nest/node_modules/@angular-devkit/schematics": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", - "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", + "node_modules/@nx/eslint-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "16.0.1", - "jsonc-parser": "3.2.0", - "magic-string": "0.30.0", - "ora": "5.4.1", - "rxjs": "7.8.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nx/nest/node_modules/@nestjs/schematics": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", - "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", + "node_modules/@nx/eslint-plugin/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", - "dependencies": { - "@angular-devkit/core": "16.0.1", - "@angular-devkit/schematics": "16.0.1", - "jsonc-parser": "3.2.0", - "pluralize": "8.0.0" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "typescript": ">=4.3.5" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/nest/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@nx/jest": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-21.3.9.tgz", + "integrity": "sha512-RLqXUDXabuUzpcupqCx+BNBuj7z+d6695DakCqmNj8Xbni4tm/00+kP2vI1ZnbXkd5OumDBYl52P1lqbhxx4lQ==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@jest/reporters": "^30.0.2", + "@jest/test-result": "^30.0.2", + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "identity-obj-proxy": "3.0.0", + "jest-config": "^30.0.2", + "jest-resolve": "^30.0.2", + "jest-util": "^30.0.2", + "minimatch": "9.0.3", + "picocolors": "^1.1.0", + "resolve.exports": "2.0.3", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@nx/nest/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@nx/jest/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "balanced-match": "^1.0.0" } }, - "node_modules/@nx/nest/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@nx/jest/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "license": "ISC", - "optional": true, - "peer": true, "dependencies": { - "is-glob": "^4.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 6" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/nest/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/@nx/js": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-21.3.9.tgz", + "integrity": "sha512-F9xpGgi9e0LQjqmdugPdfxqvCkgtm7dXsTAoidy7okPdWiwZZuzNUzRmxAWEEViAdENWOVG8s0KKb/fmJsZ6DQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nx/devkit": "21.3.9", + "@nx/workspace": "21.3.9", + "@zkochan/js-yaml": "0.0.7", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "picocolors": "^1.1.0", + "picomatch": "4.0.2", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "tinyglobby": "^0.2.12", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^6.0.5" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/js/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nx/nest/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/@nx/js/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "picomatch": "^2.2.1" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=8" } }, - "node_modules/@nx/nest/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "node_modules/@nx/js/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "tslib": "^2.1.0" + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@nx/nest/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@nx/js/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@nx/nest/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nx/js/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true, - "license": "0BSD" + "license": "MIT" }, - "node_modules/@nx/node": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-20.3.0.tgz", - "integrity": "sha512-6tHufkw92acIdcdLGARUJOTpjx7x4+Bu+rmM8rnugkZ4aGj62/IdI32rNBjSltYKcSo38HJyCSzmp0REdXsrbg==", + "node_modules/@nx/js/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/@nx/js/node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "dev": true, + "license": "ISC", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/eslint": "20.3.0", - "@nx/jest": "20.3.0", - "@nx/js": "20.3.0", - "tslib": "^2.3.0" + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@nx/node/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nx/js/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", "dev": true, - "license": "0BSD" + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.3.0.tgz", - "integrity": "sha512-9PqSe1Sh7qNqA4GL0cZH0t3S0EZzb2Xn14XY9au7yf0+eoxyag1oETjjULrxLeUmSoXW2hDxzNtoqKFE9zF07Q==", - "cpu": [ - "arm64" - ], + "node_modules/@nx/js/node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "ISC", "engines": { - "node": ">= 10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@nx/storybook": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/storybook/-/storybook-20.3.0.tgz", - "integrity": "sha512-H1ngnqg9JIwh1UB/PfPMHZS0L6YQbCPPL7gXr1NUcjbkXX2D+sZiBvqFwjIi0eglSM+1US7fy6/n2j3pwfQVQA==", + "node_modules/@nx/js/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", "dependencies": { - "@nx/cypress": "20.3.0", - "@nx/devkit": "20.3.0", - "@nx/eslint": "20.3.0", - "@nx/js": "20.3.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "semver": "^7.5.3", - "tslib": "^2.3.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@nx/storybook/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nx/js/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "0BSD" + "license": "ISC" }, - "node_modules/@nx/web": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-20.3.0.tgz", - "integrity": "sha512-MKmXI9uAX+fdLY0GfF/3rH4EXrEjyLI6FSt3kUuF1/UzAUUUqww6owoM+9EaC1mRcCYDd0nwN7piblVz/wIVLw==", + "node_modules/@nx/js/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@nx/js/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "detect-port": "^1.5.1", - "http-server": "^14.1.0", - "picocolors": "^1.1.0", - "tslib": "^2.3.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/@nx/web/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nx/js/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "license": "0BSD" + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, - "node_modules/@nx/webpack": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-20.3.0.tgz", - "integrity": "sha512-KW04Ge8cQtv5RmezWV6bsIptLwXNhq5d6Ew3GigL5h6BKYPEmyMes5yMSUsNqNGC1SPI5nNPwzRkTxW18b+jnA==", + "node_modules/@nx/module-federation": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/module-federation/-/module-federation-21.3.9.tgz", + "integrity": "sha512-GfJWSZVDBTNdrQlXVfnOM7FvYjwLp6gXjRTtzD+AuKgdTOeGl8raFJsfB5CInCqtkeiHW6J03EWKB1dU2Dp2JQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.23.2", - "@nx/devkit": "20.3.0", - "@nx/js": "20.3.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "ajv": "^8.12.0", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "browserslist": "^4.21.4", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^5.0.0", - "fork-ts-checker-webpack-plugin": "7.2.13", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", + "@module-federation/enhanced": "^0.17.0", + "@module-federation/node": "^2.7.9", + "@module-federation/sdk": "^0.17.0", + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "@nx/web": "21.3.9", + "@rspack/core": "^1.3.8", + "express": "^4.21.2", + "http-proxy-middleware": "^3.0.3", "picocolors": "^1.1.0", - "postcss": "^8.4.38", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^7.8.0", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^5.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.64.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "tsconfig-paths-webpack-plugin": "4.0.0", "tslib": "^2.3.0", - "webpack": "^5.80.0", - "webpack-dev-server": "^5.0.4", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" + "webpack": "^5.88.0" } }, - "node_modules/@nx/webpack/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@nx/module-federation/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">= 6" + "node": ">= 0.6" } }, - "node_modules/@nx/webpack/node_modules/less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "node_modules/@nx/module-federation/node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@nx/webpack/node_modules/less-loader": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", - "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "node_modules/@nx/module-federation/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "license": "MIT", "dependencies": { - "klona": "^2.0.4" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" + "node": ">= 0.6" } }, - "node_modules/@nx/webpack/node_modules/parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "node_modules/@nx/module-federation/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nx/module-federation/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true, "license": "MIT" }, - "node_modules/@nx/webpack/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/@nx/module-federation/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@nx/module-federation/node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, "engines": { - "node": ">=8.6" + "node": ">= 0.10.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@nx/webpack/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/@nx/module-federation/node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.8" } }, - "node_modules/@nx/webpack/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "node_modules/@nx/module-federation/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/@nx/webpack/node_modules/sass": { - "version": "1.83.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.0.tgz", - "integrity": "sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw==", + "node_modules/@nx/module-federation/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "node": ">=0.10.0" } }, - "node_modules/@nx/webpack/node_modules/sass-loader": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", - "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "node_modules/@nx/module-federation/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nx/module-federation/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/module-federation/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/module-federation/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nx/module-federation/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/module-federation/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" + "side-channel": "^1.0.6" }, "engines": { - "node": ">= 12.13.0" + "node": ">=0.6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@nx/webpack/node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ==", + "node_modules/@nx/module-federation/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^4.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.8" } }, - "node_modules/@nx/webpack/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.0.tgz", - "integrity": "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==", + "node_modules/@nx/module-federation/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", - "graceful-fs": "^4.2.6", - "http-proxy-middleware": "^2.0.7", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.4.2", - "ws": "^8.18.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "node": ">= 0.8.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@nx/module-federation/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">= 0.8" } }, - "node_modules/@nx/workspace": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.3.0.tgz", - "integrity": "sha512-z8NSAo5SiLEMPuwasDvLdCCtaTGdINh1cSZMCom8HeLbT8F7risbR0IlHVqVrKj9FPKqrAIsH+4knVb4dHHCnQ==", + "node_modules/@nx/module-federation/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "20.3.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "20.3.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } + "license": "MIT" }, - "node_modules/@nx/workspace/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/@nx/module-federation/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, - "license": "0BSD" - }, - "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", - "hasInstallScript": true, "license": "MIT", - "optional": true, "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "node": ">= 0.8.0" } }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", - "cpu": [ - "arm64" - ], + "node_modules/@nx/module-federation/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 0.8" } }, - "node_modules/@peculiar/asn1-android": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.3.15.tgz", - "integrity": "sha512-8U2TIj59cRlSXTX2d0mzUKP7whfWGFMzTeC3qPgAbccXFrPNZLaDhpNEdG5U2QZ/tBv/IHlCJ8s+KYXpJeop6w==", + "node_modules/@nx/module-federation/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@peculiar/asn1-android/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@peculiar/asn1-ecc": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.15.tgz", - "integrity": "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==", + "node_modules/@nx/nest": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-21.3.9.tgz", + "integrity": "sha512-aPWBG5oVlxlZJ/SpL1t5CR2rhcl1GhLI25LVsWprh4YEy/Yf++P4ck/4AEic61qwj2dQnsKWafzx2uPUz8iZ+Q==", + "dev": true, "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" + "@nestjs/schematics": "^11.0.0", + "@nx/devkit": "21.3.9", + "@nx/eslint": "21.3.9", + "@nx/js": "21.3.9", + "@nx/node": "21.3.9", + "tslib": "^2.3.0" } }, - "node_modules/@peculiar/asn1-ecc/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@peculiar/asn1-rsa": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.15.tgz", - "integrity": "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==", + "node_modules/@nx/node": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-21.3.9.tgz", + "integrity": "sha512-Gmj3pybFv5MlRkq5e9iLx+OAPRS36eJZy694hCr8FEqEsaIzIROSP/5rKqWg17/LnCD8o/IRgARXwch27ImZiA==", + "dev": true, "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "@peculiar/asn1-x509": "^2.3.15", - "asn1js": "^3.0.5", - "tslib": "^2.8.1" + "@nx/devkit": "21.3.9", + "@nx/eslint": "21.3.9", + "@nx/jest": "21.3.9", + "@nx/js": "21.3.9", + "kill-port": "^1.6.1", + "tcp-port-used": "^1.0.2", + "tslib": "^2.3.0" } }, - "node_modules/@peculiar/asn1-rsa/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz", - "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", + "node_modules/@nx/nx-darwin-arm64": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-21.3.9.tgz", + "integrity": "sha512-VJ90g79qnr7AXVn/trP8D5LphVb/zavqoZ8PVLkouiSHccPKTFrIVP5UGTDktBS6G7anzERM79xpAEU5RpzCpg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-schema/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@peculiar/asn1-x509": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.15.tgz", - "integrity": "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==", + "node_modules/@nx/nx-darwin-x64": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-21.3.9.tgz", + "integrity": "sha512-S/CO76zHBRnzWfSqCx0mflhx6nx3NFbL77Ufz0bJKo5JqxhZLQuCnzwTmth2psXMG4hyiQbXWChOL4SiLk6I+Q==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.15", - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@peculiar/asn1-x509/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/@nx/nx-freebsd-x64": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-21.3.9.tgz", + "integrity": "sha512-U8znPCa3ib9EU2njSxG/HRFp6ilQB4nRvgV/bw0jZGB95OU/oF5shY10DYjrLHLNtwRhJDK5oKfsr33QJjtH3w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-21.3.9.tgz", + "integrity": "sha512-oa+Gc0JU/feiSWTs9v9Jcd9NIVz18LZS6E8Ogqa6kc1e6CUxSxlqWbXLseBRzYsjU4M+PbzeOWuXiYICOySlWg==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@peculiar/webcrypto": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", - "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-21.3.9.tgz", + "integrity": "sha512-DNIxMJWHYSCfLJ+pQbXJNdDwheWth4gyTLIZjSXa7pTjszceucv8aF06CFBtkZ9fUCYN64tPS9B/WKFi2DjkoQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.8.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@peculiar/webcrypto/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-21.3.9.tgz", + "integrity": "sha512-7OOrKD2IiS5YEhcQOUCrwkPTv3UjCIAO6yIZrJLYaT8AYeaIZiqZ9oCZYTUBgPbFT0P5oS8Hp2HAEFC/M+uhbw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "esquery": "^1.4.0" - }, - "peerDependencies": { - "typescript": "^3 || ^4 || ^5" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-21.3.9.tgz", + "integrity": "sha512-p3OWdUOYtfBqfcJPY+wMRWR44/4wDeaGd+LpXRdW5hWa6H5elncKkMLmRj4AmQpCRSRfoqWFuyfJfzy4wiEprA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", "optional": true, - "engines": { - "node": ">=14" - } + "os": [ + "linux" + ] }, - "node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "node_modules/@nx/nx-linux-x64-musl": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-21.3.9.tgz", + "integrity": "sha512-WmRYmtmgIpJamy/4QHjVB3gdiMnFCGmV778aFGO/MorEgWQdqqz7q+8Pem9jWnjMYHo7Y+Mlm6ydcvM/HsXXUw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/@prisma/client": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.1.0.tgz", - "integrity": "sha512-AbQYc5+EJKm1Ydfq3KxwcGiy7wIbm4/QbjCKWWoNROtvy7d6a3gmAGkKjK0iUCzh+rHV8xDhD5Cge8ke/kiy5Q==", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/debug": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.1.0.tgz", - "integrity": "sha512-0himsvcM4DGBTtvXkd2Tggv6sl2JyUYLzEGXXleFY+7Kp6rZeSS3hiTW9mwtUlXrwYbJP6pwlVNB7jYElrjWUg==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.1.0.tgz", - "integrity": "sha512-GnYJbCiep3Vyr1P/415ReYrgJUjP79fBNc1wCo7NP6Eia0CzL2Ot9vK7Infczv3oK7JLrCcawOSAxFxNFsAERQ==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.1.0", - "@prisma/engines-version": "6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959", - "@prisma/fetch-engine": "6.1.0", - "@prisma/get-platform": "6.1.0" - } - }, - "node_modules/@prisma/engines-version": { - "version": "6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959.tgz", - "integrity": "sha512-PdJqmYM2Fd8K0weOOtQThWylwjsDlTig+8Pcg47/jszMuLL9iLIaygC3cjWJLda69siRW4STlCTMSgOjZzvKPQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.1.0.tgz", - "integrity": "sha512-asdFi7TvPlEZ8CzSZ/+Du5wZ27q6OJbRSXh+S8ISZguu+S9KtS/gP7NeXceZyb1Jv1SM1S5YfiCv+STDsG6rrg==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.1.0", - "@prisma/engines-version": "6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959", - "@prisma/get-platform": "6.1.0" - } - }, - "node_modules/@prisma/get-platform": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.1.0.tgz", - "integrity": "sha512-ia8bNjboBoHkmKGGaWtqtlgQOhCi7+f85aOkPJKgNwWvYrT6l78KgojLekE8zMhVk0R9lWcifV0Pf8l3/15V0Q==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.1.0" - } - }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", - "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/graph": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz", - "integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==", + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-21.3.9.tgz", + "integrity": "sha512-IbeNxE1ShbNZ80JKzRCr+yIKlQoD+bfek4Pmehw3qlewjQ1DcbjZIEgg99G6ZYAzpKUNMewKrLGCW+P7Hb7Uaw==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ] }, - "node_modules/@rspack/binding": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.1.8.tgz", - "integrity": "sha512-+/JzXx1HctfgPj+XtsCTbRkxiaOfAXGZZLEvs7jgp04WgWRSZ5u97WRCePNPvy+sCfOEH/2zw2ZK36Z7oQRGhQ==", - "devOptional": true, - "license": "MIT", - "optionalDependencies": { - "@rspack/binding-darwin-arm64": "1.1.8", - "@rspack/binding-darwin-x64": "1.1.8", - "@rspack/binding-linux-arm64-gnu": "1.1.8", - "@rspack/binding-linux-arm64-musl": "1.1.8", - "@rspack/binding-linux-x64-gnu": "1.1.8", - "@rspack/binding-linux-x64-musl": "1.1.8", - "@rspack/binding-win32-arm64-msvc": "1.1.8", - "@rspack/binding-win32-ia32-msvc": "1.1.8", - "@rspack/binding-win32-x64-msvc": "1.1.8" - } - }, - "node_modules/@rspack/binding-darwin-arm64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.1.8.tgz", - "integrity": "sha512-I7avr471ghQ3LAqKm2fuXuJPLgQ9gffn5Q4nHi8rsukuZUtiLDPfYzK1QuupEp2JXRWM1gG5lIbSUOht3cD6Ug==", + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-21.3.9.tgz", + "integrity": "sha512-xr85m3xGVwfeLbGxliGNXG6jlyTGMy/vE5tbLk6yyzg+wUdoAZzdRvhpZZqfT9QkUZxI8SASahFen3SiQt5VWw==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ] }, - "node_modules/@rspack/core": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.1.8.tgz", - "integrity": "sha512-pcZtcj5iXLCuw9oElTYC47bp/RQADm/MMEb3djHdwJuSlFWfWPQi5QFgJ/lJAxIW9UNHnTFrYtytycfjpuoEcA==", - "devOptional": true, + "node_modules/@nx/rspack": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/rspack/-/rspack-21.3.9.tgz", + "integrity": "sha512-H4HMjQLVZGrMfmkkZJRmM3X9VBEzqljMAUoNPKJt7jF6H/ydMXb4pp4BDI/jbLnaeeATCKlc0WAXmrPmHMUdcA==", + "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime-tools": "0.5.1", - "@rspack/binding": "1.1.8", - "@rspack/lite-tapable": "1.0.1", - "caniuse-lite": "^1.0.30001616" - }, - "engines": { - "node": ">=16.0.0" + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "@nx/module-federation": "21.3.9", + "@nx/web": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "@rspack/core": "^1.3.8", + "@rspack/dev-server": "^1.1.1", + "@rspack/plugin-react-refresh": "^1.0.0", + "autoprefixer": "^10.4.9", + "browserslist": "^4.21.4", + "css-loader": "^6.4.0", + "enquirer": "~2.3.6", + "express": "^4.21.2", + "http-proxy-middleware": "^3.0.3", + "less-loader": "^11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "parse5": "4.0.0", + "picocolors": "^1.1.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^8.1.1", + "sass": "^1.85.0", + "sass-embedded": "^1.83.4", + "sass-loader": "^16.0.4", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.0", + "ts-checker-rspack-plugin": "^1.1.1", + "tslib": "^2.3.0", + "webpack": "^5.80.0", + "webpack-node-externals": "^3.0.0" }, "peerDependencies": { - "@swc/helpers": ">=0.5.1" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } + "@module-federation/enhanced": "^0.17.0", + "@module-federation/node": "^2.7.9" } }, - "node_modules/@rspack/core/node_modules/@module-federation/runtime": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.5.1.tgz", - "integrity": "sha512-xgiMUWwGLWDrvZc9JibuEbXIbhXg6z2oUkemogSvQ4LKvrl/n0kbqP1Blk669mXzyWbqtSp6PpvNdwaE1aN5xQ==", - "devOptional": true, + "node_modules/@nx/rspack/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "0.5.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@rspack/core/node_modules/@module-federation/runtime-tools": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.5.1.tgz", - "integrity": "sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==", - "devOptional": true, + "node_modules/@nx/rspack/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@module-federation/runtime": "0.5.1", - "@module-federation/webpack-bundler-runtime": "0.5.1" + "engines": { + "node": "*" } }, - "node_modules/@rspack/core/node_modules/@module-federation/sdk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.5.1.tgz", - "integrity": "sha512-exvchtjNURJJkpqjQ3/opdbfeT2wPKvrbnGnyRkrwW5o3FH1LaST1tkiNviT6OXTexGaVc2DahbdniQHVtQ7pA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@rspack/core/node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.5.1.tgz", - "integrity": "sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==", - "devOptional": true, + "node_modules/@nx/rspack/node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.5.1", - "@module-federation/sdk": "0.5.1" - } - }, - "node_modules/@rspack/lite-tapable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz", - "integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==", - "devOptional": true, - "license": "MIT", + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, "engines": { - "node": ">=16.0.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@samverschueren/stream-to-observable": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", - "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", + "node_modules/@nx/rspack/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "license": "MIT", "dependencies": { - "any-observable": "^0.3.0" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">=6" - }, - "peerDependenciesMeta": { - "rxjs": { - "optional": true - }, - "zen-observable": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@schematics/angular": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.0.6.tgz", - "integrity": "sha512-HicclmbW/+mlljU7a4PzbyIWG+7tognoL5LsgMFJQUDzJXHNjRt1riL0vk57o8Pcprnz9FheeWZXO1KRhXkQuw==", + "node_modules/@nx/rspack/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, "license": "MIT", - "dependencies": { - "@angular-devkit/core": "19.0.6", - "@angular-devkit/schematics": "19.0.6", - "jsonc-parser": "3.3.1" - }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">= 0.6" } }, - "node_modules/@schematics/angular/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "node_modules/@nx/rspack/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, "license": "MIT" }, - "node_modules/@sigstore/bundle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.0.0.tgz", - "integrity": "sha512-XDUYX56iMPAn/cdgh/DTJxz5RWmqKV4pwvUAEKEWJl+HzKdCd/24wUa9JYNMlDSCb7SUHAdtksxYX779Nne/Zg==", + "node_modules/@nx/rspack/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/@sigstore/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-2.0.0.tgz", - "integrity": "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==", + "node_modules/@nx/rspack/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "license": "MIT", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz", - "integrity": "sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==", + "node_modules/@nx/rspack/node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@sigstore/sign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-3.0.0.tgz", - "integrity": "sha512-UjhDMQOkyDoktpXoc5YPJpJK6IooF2gayAr5LvXI4EL7O0vd58okgfRcxuaH+YTdhvb5aa1Q9f+WJ0c2sVuYIw==", + "node_modules/@nx/rspack/node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^14.0.1", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.8" } }, - "node_modules/@sigstore/tuf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-3.0.0.tgz", - "integrity": "sha512-9Xxy/8U5OFJu7s+OsHzI96IX/OzjF/zj0BSSaWhgJgTqtlBhQIV2xdrQI5qxLD7+CWWDepadnXAxzaZ3u9cvRw==", + "node_modules/@nx/rspack/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^3.0.1" - }, + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.6" } }, - "node_modules/@sigstore/verify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-2.0.0.tgz", - "integrity": "sha512-Ggtq2GsJuxFNUvQzLoXqRwS4ceRfLAJnrIHUDrzAD0GgnOhwujJkKkxM/s5Bako07c3WtAs/sZo5PJq7VHjeDg==", + "node_modules/@nx/rspack/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=0.10.0" } }, - "node_modules/@simplewebauthn/browser": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-9.0.1.tgz", - "integrity": "sha512-wD2WpbkaEP4170s13/HUxPcAV5y4ZXaKo1TfNklS5zDefPinIgXOpgz1kpEvobAsaLPa2KeH7AKKX/od1mrBJw==", + "node_modules/@nx/rspack/node_modules/less-loader": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz", + "integrity": "sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==", + "dev": true, "license": "MIT", - "dependencies": { - "@simplewebauthn/types": "^9.0.1" + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" } }, - "node_modules/@simplewebauthn/server": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-9.0.3.tgz", - "integrity": "sha512-FMZieoBosrVLFxCnxPFD9Enhd1U7D8nidVDT4MsHc6l4fdVcjoeHjDueeXCloO1k5O/fZg1fsSXXPKbY2XTzDA==", + "node_modules/@nx/rspack/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, "license": "MIT", "dependencies": { - "@hexagon/base64": "^1.1.27", - "@levischuck/tiny-cbor": "^0.2.2", - "@peculiar/asn1-android": "^2.3.10", - "@peculiar/asn1-ecc": "^2.3.8", - "@peculiar/asn1-rsa": "^2.3.8", - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "@simplewebauthn/types": "^9.0.1", - "cross-fetch": "^4.0.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=8.9.0" } }, - "node_modules/@simplewebauthn/server/node_modules/cross-fetch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", - "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "node_modules/@nx/rspack/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/@simplewebauthn/types": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@simplewebauthn/types/-/types-9.0.1.tgz", - "integrity": "sha512-tGSRP1QvsAvsJmnOlRQyw/mvK9gnPtjEc5fg2+m8n+QUa+D7rvrKkOYyfpy42GTs90X3RDOnqJgfHt+qO67/+w==", - "license": "MIT" + "node_modules/@nx/rspack/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "devOptional": true, + "node_modules/@nx/rspack/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, "license": "MIT" }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@nx/rspack/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">= 0.6" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "license": "MIT", + "node_modules/@nx/rspack/node_modules/parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/rspack/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/rspack/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, "engines": { - "node": ">=18" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/@nx/rspack/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", "dependencies": { - "type-detect": "4.0.8" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/@nx/rspack/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@stencil/core": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.23.0.tgz", - "integrity": "sha512-9vI8ywhoqlaDEmrcntejrZ9X76Tddv2JyWakjVpqJAdDNXgf520sYkyjzGT0p8VJfPtSaKm6pMtl5sAH1r9cFg==", + "node_modules/@nx/rspack/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, "license": "MIT", - "bin": { - "stencil": "bin/stencil" - }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.10.0" + "node": ">= 0.8" } }, - "node_modules/@storybook/addon-actions": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.7.tgz", - "integrity": "sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA==", + "node_modules/@nx/rspack/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/rspack/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "@types/uuid": "^9.0.1", - "dequal": "^2.0.2", - "polished": "^4.2.2", - "uuid": "^9.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, - "peerDependencies": { - "storybook": "^8.4.7" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@storybook/addon-actions/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@nx/rspack/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">= 0.8" } }, - "node_modules/@storybook/addon-backgrounds": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.7.tgz", - "integrity": "sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ==", + "node_modules/@nx/rspack/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, - "peerDependencies": { - "storybook": "^8.4.7" + "engines": { + "node": ">= 0.6" } }, - "node_modules/@storybook/addon-controls": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.7.tgz", - "integrity": "sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA==", + "node_modules/@nx/storybook": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/storybook/-/storybook-21.3.9.tgz", + "integrity": "sha512-TuiiRmyjJGoNJq2odt5wkNJ4z5ZjcDlzwXvy3/9djpbRpg+vrTN4ZqqGGfmX+veRobeq04IsdVRtknicnfMu6A==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "dequal": "^2.0.2", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "@nx/cypress": "21.3.9", + "@nx/devkit": "21.3.9", + "@nx/eslint": "21.3.9", + "@nx/js": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "semver": "^7.5.3", + "tslib": "^2.3.0" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": ">=7.0.0 <10.0.0" } }, - "node_modules/@storybook/addon-docs": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.7.tgz", - "integrity": "sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w==", + "node_modules/@nx/web": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-21.3.9.tgz", + "integrity": "sha512-nunIcyYr5JQRR6obb9pPBKiVq/94w+S0KebXXFs99/Z4H9Mdi0j8hVtzQ35bBg71SjHQJuRZN2lCkA5aOdlZVg==", "dev": true, "license": "MIT", "dependencies": { - "@mdx-js/react": "^3.0.0", - "@storybook/blocks": "8.4.7", - "@storybook/csf-plugin": "8.4.7", - "@storybook/react-dom-shim": "8.4.7", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "ts-dedent": "^2.0.0" + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "detect-port": "^1.5.1", + "http-server": "^14.1.0", + "picocolors": "^1.1.0", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/webpack": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-21.3.9.tgz", + "integrity": "sha512-AkUoVZ3bu2nSH6u7bQ/ZAbk4y3LfmXg9h7eakJdPR8PqETnJQC76y3AhQrTTy2njtBhybe4LUgMNELqLcgh1rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@nx/devkit": "21.3.9", + "@nx/js": "21.3.9", + "@phenomnomnominal/tsquery": "~5.0.1", + "ajv": "^8.12.0", + "autoprefixer": "^10.4.9", + "babel-loader": "^9.1.2", + "browserslist": "^4.21.4", + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.4.0", + "css-minimizer-webpack-plugin": "^5.0.0", + "fork-ts-checker-webpack-plugin": "7.2.13", + "less": "^4.1.3", + "less-loader": "^11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "mini-css-extract-plugin": "~2.4.7", + "parse5": "4.0.0", + "picocolors": "^1.1.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^6.1.1", + "rxjs": "^7.8.0", + "sass": "^1.85.0", + "sass-embedded": "^1.83.4", + "sass-loader": "^16.0.4", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.0", + "terser-webpack-plugin": "^5.3.3", + "ts-loader": "^9.3.1", + "tsconfig-paths-webpack-plugin": "4.0.0", + "tslib": "^2.3.0", + "webpack": "~5.99.0", + "webpack-dev-server": "^5.2.1", + "webpack-node-externals": "^3.0.0", + "webpack-subresource-integrity": "^5.1.0" + } + }, + "node_modules/@nx/webpack/node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "engines": { + "node": ">= 14.15.0" }, "peerDependencies": { - "storybook": "^8.4.7" + "@babel/core": "^7.12.0", + "webpack": ">=5" } }, - "node_modules/@storybook/addon-docs/node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "node_modules/@nx/webpack/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdx": "^2.0.0" + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 12.20.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" + "webpack": "^5.1.0" } }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/blocks": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.7.tgz", - "integrity": "sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA==", + "node_modules/@nx/webpack/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf": "^0.1.11", - "@storybook/icons": "^1.2.12", - "ts-dedent": "^2.0.0" + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7" + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "react": { + "@rspack/core": { "optional": true }, - "react-dom": { + "webpack": { "optional": true } } }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/icons": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.3.0.tgz", - "integrity": "sha512-Nz/UzeYQdUZUhacrPyfkiiysSjydyjgg/p0P9HxB4p/WaJUUjMAcaoaLgy3EXx61zZJ3iD36WPuDkZs5QYrA0A==", + "node_modules/@nx/webpack/node_modules/less-loader": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz", + "integrity": "sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">= 14.15.0" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/react-dom-shim": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.7.tgz", - "integrity": "sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg==", - "dev": true, - "license": "MIT", "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7" + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" } }, - "node_modules/@storybook/addon-docs/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "node_modules/@nx/webpack/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.9.0" } }, - "node_modules/@storybook/addon-docs/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "node_modules/@nx/webpack/node_modules/mini-css-extract-plugin": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", + "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "schema-utils": "^4.0.0" }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/@storybook/addon-essentials": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.7.tgz", - "integrity": "sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/addon-actions": "8.4.7", - "@storybook/addon-backgrounds": "8.4.7", - "@storybook/addon-controls": "8.4.7", - "@storybook/addon-docs": "8.4.7", - "@storybook/addon-highlight": "8.4.7", - "@storybook/addon-measure": "8.4.7", - "@storybook/addon-outline": "8.4.7", - "@storybook/addon-toolbars": "8.4.7", - "@storybook/addon-viewport": "8.4.7", - "ts-dedent": "^2.0.0" + "engines": { + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "storybook": "^8.4.7" + "webpack": "^5.0.0" } }, - "node_modules/@storybook/addon-highlight": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.7.tgz", - "integrity": "sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw==", + "node_modules/@nx/webpack/node_modules/parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/webpack/node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "storybook": "^8.4.7" + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/@storybook/addon-interactions": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.4.7.tgz", - "integrity": "sha512-fnufT3ym8ht3HHUIRVXAH47iOJW/QOb0VSM+j269gDuvyDcY03D1civCu1v+eZLGaXPKJ8vtjr0L8zKQ/4P0JQ==", + "node_modules/@nx/workspace": { + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-21.3.9.tgz", + "integrity": "sha512-JmCK3PQ2xaZo9n+XpP9A/Y5U4bmnkxwOU+aFMhopC/JpKiWJF9ltbUlryu8ZqCd/oqeE+cZPIVsPwIVa7vbpdg==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "8.4.7", - "@storybook/test": "8.4.7", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" + "@nx/devkit": "21.3.9", + "@zkochan/js-yaml": "0.0.7", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "21.3.9", + "picomatch": "4.0.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@storybook/addon-measure": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.7.tgz", - "integrity": "sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw==", + "node_modules/@nx/workspace/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "tiny-invariant": "^1.3.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openrouter/ai-sdk-provider": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@openrouter/ai-sdk-provider/-/ai-sdk-provider-0.7.2.tgz", + "integrity": "sha512-Fry2mV7uGGJRmP9JntTZRc8ElESIk7AJNTacLbF6Syoeb5k8d7HPGkcK9rTXDlqBb8HgU1hOKtz23HojesTmnw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "@ai-sdk/provider-utils": "2.2.8" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { - "storybook": "^8.4.7" + "ai": "^4.3.16", + "zod": "^3.25.34" } }, - "node_modules/@storybook/addon-outline": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.7.tgz", - "integrity": "sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA==", - "dev": true, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" + "url": "https://opencollective.com/parcel" }, - "peerDependencies": { - "storybook": "^8.4.7" + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/addon-toolbars": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.7.tgz", - "integrity": "sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw==", - "dev": true, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/addon-viewport": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.7.tgz", - "integrity": "sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ==", - "dev": true, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "memoizerific": "^1.11.3" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-8.4.7.tgz", - "integrity": "sha512-PYWWEvoe+sT8riprSQVCyGnQbifbuzT9YNYPi22YBxB8ZGVuIVwjshKjSZvC99ULQbMvJ/g2OPCcBA8hhc3aTg==", - "dev": true, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@storybook/builder-webpack5": "8.4.7", - "@storybook/components": "8.4.7", - "@storybook/core-webpack": "8.4.7", - "@storybook/global": "^5.0.0", - "@storybook/manager-api": "8.4.7", - "@storybook/preview-api": "8.4.7", - "@storybook/theming": "8.4.7", - "@types/node": "^22.0.0", - "@types/react": "^18.0.37", - "@types/react-dom": "^18.0.11", - "@types/semver": "^7.3.4", - "@types/webpack-env": "^1.18.0", - "fd-package-json": "^1.2.0", - "find-up": "^5.0.0", - "semver": "^7.3.7", - "telejson": "^7.2.0", - "ts-dedent": "^2.0.0", - "tsconfig-paths-webpack-plugin": "^4.0.1", - "util-deprecate": "^1.0.2", - "webpack": "5" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=18.0.0" + "node": ">= 10.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "@angular-devkit/architect": ">=0.1500.0 < 0.2000.0", - "@angular-devkit/build-angular": ">=15.0.0 < 20.0.0", - "@angular-devkit/core": ">=15.0.0 < 20.0.0", - "@angular/cli": ">=15.0.0 < 20.0.0", - "@angular/common": ">=15.0.0 < 20.0.0", - "@angular/compiler": ">=15.0.0 < 20.0.0", - "@angular/compiler-cli": ">=15.0.0 < 20.0.0", - "@angular/core": ">=15.0.0 < 20.0.0", - "@angular/forms": ">=15.0.0 < 20.0.0", - "@angular/platform-browser": ">=15.0.0 < 20.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 < 20.0.0", - "rxjs": "^6.0.0 || ^7.4.0", - "storybook": "^8.4.7", - "typescript": "^4.0.0 || ^5.0.0", - "zone.js": ">= 0.11.1 < 1.0.0" - }, - "peerDependenciesMeta": { - "@angular/cli": { - "optional": true - } + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dev": true, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/angular/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@storybook/builder-webpack5": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.7.tgz", - "integrity": "sha512-O8LpsQ+4g2x5kh7rI9+jEUdX8k1a5egBQU1lbudmHchqsV0IKiVqBD9LL5Gj3wpit4vB8coSW4ZWTFBw8FQb4Q==", - "dev": true, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@storybook/core-webpack": "8.4.7", - "@types/node": "^22.0.0", - "@types/semver": "^7.3.4", - "browser-assert": "^1.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "cjs-module-lexer": "^1.2.3", - "constants-browserify": "^1.0.0", - "css-loader": "^6.7.1", - "es-module-lexer": "^1.5.0", - "fork-ts-checker-webpack-plugin": "^8.0.0", - "html-webpack-plugin": "^5.5.0", - "magic-string": "^0.30.5", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "semver": "^7.3.7", - "style-loader": "^3.3.1", - "terser-webpack-plugin": "^5.3.1", - "ts-dedent": "^2.0.0", - "url": "^0.11.0", - "util": "^0.12.4", - "util-deprecate": "^1.0.2", - "webpack": "5", - "webpack-dev-middleware": "^6.1.2", - "webpack-hot-middleware": "^2.25.1", - "webpack-virtual-modules": "^0.6.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dev": true, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/builder-webpack5/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 8.10.0" + "node": ">= 10.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", - "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" }, "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" + "node": ">=0.10" } }, - "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@peculiar/asn1-android": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.4.0.tgz", + "integrity": "sha512-YFueREq97CLslZZBI8dKzis7jMfEHSLxM+nr0Zdx1POiXFLjqqwoY5s0F1UimdBiEw/iKlHey2m56MRDv7Jtyg==", "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" + "@peculiar/asn1-schema": "^2.4.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" } }, - "node_modules/@storybook/builder-webpack5/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", + "node_modules/@peculiar/asn1-ecc": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.4.0.tgz", + "integrity": "sha512-fJiYUBCJBDkjh347zZe5H81BdJ0+OGIg0X9z06v8xXUoql3MFeENUX0JsjCaVaU9A0L85PefLPGYkIoGpTnXLQ==", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "@peculiar/asn1-schema": "^2.4.0", + "@peculiar/asn1-x509": "^2.4.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" } }, - "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" + "node_modules/@peculiar/asn1-rsa": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.4.0.tgz", + "integrity": "sha512-6PP75voaEnOSlWR9sD25iCQyLgFZHXbmxvUfnnDcfL6Zh5h2iHW38+bve4LfH7a60x7fkhZZNmiYqAlAff9Img==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.4.0", + "@peculiar/asn1-x509": "^2.4.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } }, - "node_modules/@storybook/builder-webpack5/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, + "node_modules/@peculiar/asn1-schema": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.4.0.tgz", + "integrity": "sha512-umbembjIWOrPSOzEGG5vxFLkeM8kzIhLkgigtsOrfLKnuzxWxejAcUX+q/SoZCdemlODOcr5WiYa7+dIEzBXZQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" } }, - "node_modules/@storybook/builder-webpack5/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "node_modules/@peculiar/asn1-x509": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.4.0.tgz", + "integrity": "sha512-F7mIZY2Eao2TaoVqigGMLv+NDdpwuBKU1fucHPONfzaBS4JXXCNCmfO0Z3dsy7JzKGqtDcYC1mr9JjaZQZNiuw==", "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "dependencies": { + "@peculiar/asn1-schema": "^2.4.0", + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" } }, - "node_modules/@storybook/builder-webpack5/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", "license": "MIT", + "peer": true, "dependencies": { - "picomatch": "^2.2.1" + "tslib": "^2.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=8.0.0" } }, - "node_modules/@storybook/builder-webpack5/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, + "node_modules/@peculiar/webcrypto": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", + "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", "license": "MIT", + "peer": true, "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.8.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=10.12.0" } }, - "node_modules/@storybook/builder-webpack5/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", - "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "node_modules/@phenomnomnominal/tsquery": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", + "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", "dev": true, "license": "MIT", "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "esquery": "^1.4.0" }, "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "typescript": "^3 || ^4 || ^5" } }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, "engines": { - "node": ">= 10.13.0" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/pkgr" } }, - "node_modules/@storybook/components": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.4.7.tgz", - "integrity": "sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g==", + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } + "license": "MIT" }, - "node_modules/@storybook/core": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.4.7.tgz", - "integrity": "sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/csf": "^0.1.11", - "better-opn": "^3.0.2", - "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", - "esbuild-register": "^3.5.0", - "jsdoc-type-pratt-parser": "^4.0.0", - "process": "^0.11.10", - "recast": "^0.23.5", - "semver": "^7.6.2", - "util": "^0.12.5", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "node_modules/@prisma/client": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.12.0.tgz", + "integrity": "sha512-wn98bJ3Cj6edlF4jjpgXwbnQIo/fQLqqQHPk2POrZPxTlhY3+n90SSIF3LMRVa8VzRFC/Gec3YKJRxRu+AIGVA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" }, "peerDependencies": { - "prettier": "^2 || ^3" + "prisma": "*", + "typescript": ">=5.1.0" }, "peerDependenciesMeta": { - "prettier": { + "prisma": { + "optional": true + }, + "typescript": { "optional": true } } }, - "node_modules/@storybook/core-server": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-8.4.7.tgz", - "integrity": "sha512-RW5R+kqRmcP+7QNTmhcrh46qWYkVpxaRlN8MmkHV52m2H5nbBrvgwc3/sb3wdgm1PEU0K5wxT0cmAMIwtnHC9Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } - }, - "node_modules/@storybook/core-webpack": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.7.tgz", - "integrity": "sha512-Tj+CjQLpFyBJxhhMms+vbPT3+gTRAiQlrhY3L1IEVwBa3wtRMS0qjozH26d1hK4G6mUIEdwu13L54HMU/w33Sg==", - "dev": true, - "license": "MIT", + "node_modules/@prisma/config": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.12.0.tgz", + "integrity": "sha512-HovZWzhWEMedHxmjefQBRZa40P81N7/+74khKFz9e1AFjakcIQdXgMWKgt20HaACzY+d1LRBC+L4tiz71t9fkg==", + "devOptional": true, + "license": "Apache-2.0", "dependencies": { - "@types/node": "^22.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" + "jiti": "2.4.2" } }, - "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dev": true, + "node_modules/@prisma/config/node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "devOptional": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/@storybook/core-webpack/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" + "node_modules/@prisma/debug": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.12.0.tgz", + "integrity": "sha512-plbz6z72orcqr0eeio7zgUrZj5EudZUpAeWkFTA/DDdXEj28YHDXuiakvR6S7sD6tZi+jiwQEJAPeV6J6m/tEQ==", + "devOptional": true, + "license": "Apache-2.0" }, - "node_modules/@storybook/csf": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.13.tgz", - "integrity": "sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q==", - "dev": true, - "license": "MIT", + "node_modules/@prisma/engines": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.12.0.tgz", + "integrity": "sha512-4BRZZUaAuB4p0XhTauxelvFs7IllhPmNLvmla0bO1nkECs8n/o1pUvAVbQ/VOrZR5DnF4HED0PrGai+rIOVePA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "type-fest": "^2.19.0" + "@prisma/debug": "6.12.0", + "@prisma/engines-version": "6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc", + "@prisma/fetch-engine": "6.12.0", + "@prisma/get-platform": "6.12.0" } }, - "node_modules/@storybook/csf-plugin": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.7.tgz", - "integrity": "sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g==", - "dev": true, - "license": "MIT", + "node_modules/@prisma/engines-version": { + "version": "6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc.tgz", + "integrity": "sha512-70vhecxBJlRr06VfahDzk9ow4k1HIaSfVUT3X0/kZoHCMl9zbabut4gEXAyzJZxaCGi5igAA7SyyfBI//mmkbQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.12.0.tgz", + "integrity": "sha512-EamoiwrK46rpWaEbLX9aqKDPOd8IyLnZAkiYXFNuq0YsU0Z8K09/rH8S7feOWAVJ3xzeSgcEJtBlVDrajM9Sag==", + "devOptional": true, + "license": "Apache-2.0", "dependencies": { - "unplugin": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" + "@prisma/debug": "6.12.0", + "@prisma/engines-version": "6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc", + "@prisma/get-platform": "6.12.0" } }, - "node_modules/@storybook/csf/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/@prisma/get-platform": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.12.0.tgz", + "integrity": "sha512-nRerTGhTlgyvcBlyWgt8OLNIV7QgJS2XYXMJD1hysorMCuLAjuDDuoxmVt7C2nLxbuxbWPp7OuFRHC23HqD9dA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.12.0" } }, - "node_modules/@storybook/global": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", - "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@storybook/instrumenter": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.4.7.tgz", - "integrity": "sha512-k6NSD3jaRCCHAFtqXZ7tw8jAzD/yTEWXGya+REgZqq5RCkmJ+9S4Ytp/6OhQMPtPFX23gAuJJzTQVLcCr+gjRg==", - "dev": true, + "node_modules/@redis/client": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", + "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", "license": "MIT", "dependencies": { - "@storybook/global": "^5.0.0", - "@vitest/utils": "^2.1.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" }, - "peerDependencies": { - "storybook": "^8.4.7" + "engines": { + "node": ">=14" } }, - "node_modules/@storybook/manager-api": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.7.tgz", - "integrity": "sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ==", - "dev": true, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", + "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "cpu": [ + "arm" + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@storybook/preview-api": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.7.tgz", - "integrity": "sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg==", - "dev": true, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", + "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@storybook/test": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.4.7.tgz", - "integrity": "sha512-AhvJsu5zl3uG40itSQVuSy5WByp3UVhS6xAnme4FWRwgSxhvZjATJ3AZkkHWOYjnnk+P2/sbz/XuPli1FVCWoQ==", - "dev": true, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", + "integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@storybook/csf": "^0.1.11", - "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "8.4.7", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.5.0", - "@testing-library/user-event": "14.5.2", - "@vitest/expect": "2.0.5", - "@vitest/spy": "2.0.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.4.7" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@storybook/theming": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.7.tgz", - "integrity": "sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw==", - "dev": true, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", + "integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==", + "cpu": [ + "x64" + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", + "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", + "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", + "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", + "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", + "integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", + "integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", + "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", + "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", + "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", + "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", + "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", + "integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", + "integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", + "integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", + "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", + "integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.4.10.tgz", + "integrity": "sha512-awiXN7qTTTLWFThbJFL+M4k1if4sb17xKA5TaHbbxs0qKSlpe3adwNrNHaNU2WOQz+PbuF++OMyd+4gUusKuVg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@rspack/binding-darwin-arm64": "1.4.10", + "@rspack/binding-darwin-x64": "1.4.10", + "@rspack/binding-linux-arm64-gnu": "1.4.10", + "@rspack/binding-linux-arm64-musl": "1.4.10", + "@rspack/binding-linux-x64-gnu": "1.4.10", + "@rspack/binding-linux-x64-musl": "1.4.10", + "@rspack/binding-wasm32-wasi": "1.4.10", + "@rspack/binding-win32-arm64-msvc": "1.4.10", + "@rspack/binding-win32-ia32-msvc": "1.4.10", + "@rspack/binding-win32-x64-msvc": "1.4.10" + } + }, + "node_modules/@rspack/binding-darwin-arm64": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.10.tgz", + "integrity": "sha512-PraYGuVSzvEwdoYC8T70qI/8j1QeUe2sysiWmjSdxUpxJsDfw35hK9TfxULeAJULlAUAiiXs03hdZk29DBc3ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-darwin-x64": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.4.10.tgz", + "integrity": "sha512-rWTSJ08TE0uqUjqAHkTmWqJu+FLSJ70A199Fk9k/FLZTS8UtHjuzZW7rv4qIN2nwJJLherxFUnP6y69cHuaGNw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-linux-arm64-gnu": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.10.tgz", + "integrity": "sha512-cs6yu250FzRU1hl+02VLoJRdzbAveTOqvREeHgqL5AiTc6q1dQo1IZ16/Qt4+g0DMjnvM66pELRIO2nphXL8aA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-arm64-musl": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.4.10.tgz", + "integrity": "sha512-NnOAoWkpZvOa+xM7NAJg25O+tSKt6xCXoga+gOw5XPni1NxHDc3PNh5bU6fAmc2Z29YLLdxeVqPmIDfdk1EkDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-gnu": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.10.tgz", + "integrity": "sha512-FcaBqMclADWiqX+Mez15kggwaVYZkoEqDiQwYRpYDbBMsiJEtfp41GnNRstTWxYxFbcmuWoZl2cYy+LepR21ag==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-musl": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.4.10.tgz", + "integrity": "sha512-vgRQhCw+C/Nxv6MZVNUkPzSXs6kIWHIrGKUvOM1ceeAkT+jNFEQdukkQ5LsYgEqEwP9ezWubxN3IGrMxyimlPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-wasm32-wasi": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.4.10.tgz", + "integrity": "sha512-lk647+Ob3yvVS2FgW0vCfo/gz9h0Q7v9HGBFcsD1uW0/tSqXMa2s9ZvIn+B7S9tRgIoosXEAuq8NeCXKGWVj5Q==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.1" + } + }, + "node_modules/@rspack/binding-win32-arm64-msvc": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.4.10.tgz", + "integrity": "sha512-9mB3kh4pKaY4wFosZwuxb5EUtt7vv/uKW3OF4TJDC35bH7r54s+YYpHyXROT304r6URl4b6HNHlysL2m7BLihg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-ia32-msvc": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.4.10.tgz", + "integrity": "sha512-DPlyLZDUWkNcFI7zp1BQVVnihd4j/hCIbxqvIKvUt7whIVYMP52i8lCsa52uNGBSj7BcbcKAFElXC9dHVvoQGA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-x64-msvc": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.4.10.tgz", + "integrity": "sha512-FEE6OM0Wh7nj90+1ARXojT0Dnqox9UlIUIj7MQmX09yeMtckR+HITeq75F8y0l7HUvKOl2zQovmenk1KgyJV8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/core": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.4.10.tgz", + "integrity": "sha512-eK3H328pihiM1323OlaClKJ9WlqgGBZpcR5AqFoWsG0KD01tKCJOeZEgtCY6paRLrsQrEJwBrLntkG0fE7WNGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime-tools": "0.17.0", + "@rspack/binding": "1.4.10", + "@rspack/lite-tapable": "1.0.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.1" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/error-codes": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.17.0.tgz", + "integrity": "sha512-+pZ12frhaDqh4Xs/MQj4Vu4CAjnJTiEb8Z6fqPfn/TLHh4YLWMOzpzxGuMFDHqXwMb3o8FRAUhNB0eX2ZmhwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rspack/core/node_modules/@module-federation/runtime": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.17.0.tgz", + "integrity": "sha512-eMtrtCSSV6neJpMmQ8WdFpYv93raSgsG5RiAPsKUuSCXfZ5D+yzvleZ+gPcEpFT9HokmloxAn0jep50/1upTQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.17.0", + "@module-federation/runtime-core": "0.17.0", + "@module-federation/sdk": "0.17.0" + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/runtime-core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.17.0.tgz", + "integrity": "sha512-MYwDDevYnBB9gXFfNOmJVIX5XZcbCHd0dral7gT7yVmlwOhbuGOLlm2dh2icwwdCYHA9AFDCfU9l1nJR4ex/ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.17.0", + "@module-federation/sdk": "0.17.0" + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/runtime-tools": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.17.0.tgz", + "integrity": "sha512-t4QcKfhmwOHedwByDKUlTQVw4+gPotySYPyNa8GFrBSr1F6wcGdGyOhzP+PdgpiJLIM03cB6V+IKGGHE28SfDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.17.0", + "@module-federation/webpack-bundler-runtime": "0.17.0" + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/sdk": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.17.0.tgz", + "integrity": "sha512-tjrNaYdDocHZsWu5iXlm83lwEK8A64r4PQB3/kY1cW1iOvggR2RESLAWPxRJXC2cLF8fg8LDKOBdgERZW1HPFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rspack/core/node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.17.0.tgz", + "integrity": "sha512-o8XtXwqTDlqLgcALOfObcCbqXvUcSDHIEXrkcb4W+I8GJY7IqV0+x6rX4mJ3f59tca9qOF8zsZsOA6BU93Pvgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.17.0", + "@module-federation/sdk": "0.17.0" + } + }, + "node_modules/@rspack/dev-server": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rspack/dev-server/-/dev-server-1.1.3.tgz", + "integrity": "sha512-jWPeyiZiGpbLYGhwHvwxhaa4rsr8CQvsWkWslqeMLb2uXwmyy3UWjUR1q+AhAPnf0gs3lZoFZ1hjBQVecHKUvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.6.0", + "http-proxy-middleware": "^2.0.9", + "p-retry": "^6.2.0", + "webpack-dev-server": "5.2.2", + "ws": "^8.18.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@rspack/core": "*" + } + }, + "node_modules/@rspack/dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/@rspack/dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@rspack/dev-server/node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/@rspack/dev-server/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rspack/dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@rspack/lite-tapable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz", + "integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@rspack/plugin-react-refresh": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.4.3.tgz", + "integrity": "sha512-wZx4vWgy5oMEvgyNGd/oUKcdnKaccYWHCRkOqTdAPJC3WcytxhTX+Kady8ERurSBiLyQpoMiU3Iyd+F1Y2Arbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.1.4", + "html-entities": "^2.6.0" + }, + "peerDependencies": { + "react-refresh": ">=0.10.0 <1.0.0", + "webpack-hot-middleware": "2.x" + }, + "peerDependenciesMeta": { + "webpack-hot-middleware": { + "optional": true + } + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@samverschueren/stream-to-observable": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-observable": "^0.3.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "rxjs": { + "optional": true + }, + "zen-observable": { + "optional": true + } + } + }, + "node_modules/@schematics/angular": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.1.3.tgz", + "integrity": "sha512-+YxWsUKI3RJbYc0NrbLoJhncZPA7tUESwBvmsBmAUh1ca+6JbHXo32EoUqsAVX7HmF4IxyPSgu1JL0JxQV32rA==", + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "20.1.3", + "@angular-devkit/schematics": "20.1.3", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@sigstore/bundle": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.1.0.tgz", + "integrity": "sha512-Mm1E3/CmDDCz3nDhFKTuYdB47EdRFRQMOE/EAbiG1MJW77/w1b3P7Qx7JSrVJs8PfwOLOVcKQCHErIwCTyPbag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.4.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-2.0.0.tgz", + "integrity": "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.4.3.tgz", + "integrity": "sha512-fk2zjD9117RL9BjqEwF7fwv7Q/P9yGsMV4MUJZ/DocaQJ6+3pKr+syBq1owU5Q5qGw5CUbXzm+4yJ2JVRDQeSA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-3.1.0.tgz", + "integrity": "sha512-knzjmaOHOov1Ur7N/z4B1oPqZ0QX5geUfhrVaqVlu+hl0EAoL4o+l0MSULINcD5GCWe3Z0+YJO8ues6vFlW0Yw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.1.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.4.0", + "make-fetch-happen": "^14.0.2", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-3.1.1.tgz", + "integrity": "sha512-eFFvlcBIoGwVkkwmTi/vEQFSva3xs5Ot3WmBcjgjVdiaoelBLQaQ/ZBfhlG0MnG0cmTYScPpk7eDdGDWUcFUmg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.4.1", + "tuf-js": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-2.1.1.tgz", + "integrity": "sha512-hVJD77oT67aowHxwT4+M6PGOp+E2LtLdTK3+FC0lBO9T7sYwItDMXZ7Z07IDCvR1M717a4axbIWckrW67KMP/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.1.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.4.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@simplewebauthn/browser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.0.tgz", + "integrity": "sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==", + "license": "MIT" + }, + "node_modules/@simplewebauthn/server": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.1.1.tgz", + "integrity": "sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA==", + "license": "MIT", + "dependencies": { + "@hexagon/base64": "^1.1.27", + "@levischuck/tiny-cbor": "^0.2.2", + "@peculiar/asn1-android": "^2.3.10", + "@peculiar/asn1-ecc": "^2.3.8", + "@peculiar/asn1-rsa": "^2.3.8", + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/asn1-x509": "^2.3.8" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@stencil/core": { + "version": "4.33.1", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz", + "integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==", + "license": "MIT", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.10.0" + }, + "optionalDependencies": { + "@rollup/rollup-darwin-arm64": "4.34.9", + "@rollup/rollup-darwin-x64": "4.34.9", + "@rollup/rollup-linux-arm64-gnu": "4.34.9", + "@rollup/rollup-linux-arm64-musl": "4.34.9", + "@rollup/rollup-linux-x64-gnu": "4.34.9", + "@rollup/rollup-linux-x64-musl": "4.34.9", + "@rollup/rollup-win32-arm64-msvc": "4.34.9", + "@rollup/rollup-win32-x64-msvc": "4.34.9" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.0.17.tgz", + "integrity": "sha512-LOX/kKgQGnyulrqZHsvf77+ZoH/nSUaplGr5hvZglW/U6ak6fO9seJyXAzVKEnC6p+F8n02kFBZbi3s+znQhSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mdx-js/react": "^3.0.0", + "@storybook/csf-plugin": "9.0.17", + "@storybook/icons": "^1.2.12", + "@storybook/react-dom-shim": "9.0.17", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.0.17" + } + }, + "node_modules/@storybook/angular": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-9.0.17.tgz", + "integrity": "sha512-35JDkRT21DXSIJ48K8RB9SEHedafH4YAlOfl42JsBgOVGTc7Gq59JBTrEQS39PYm1gikR6ComuOCgzVekhZuag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/builder-webpack5": "9.0.17", + "@storybook/core-webpack": "9.0.17", + "@storybook/global": "^5.0.0", + "@types/webpack-env": "^1.18.0", + "fd-package-json": "^1.2.0", + "find-up": "^7.0.0", + "telejson": "8.0.0", + "ts-dedent": "^2.0.0", + "tsconfig-paths-webpack-plugin": "^4.0.1", + "webpack": "5" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@angular-devkit/architect": ">=0.1800.0 < 0.2100.0", + "@angular-devkit/build-angular": ">=18.0.0 < 21.0.0", + "@angular-devkit/core": ">=18.0.0 < 21.0.0", + "@angular/animations": ">=18.0.0 < 21.0.0", + "@angular/cli": ">=18.0.0 < 21.0.0", + "@angular/common": ">=18.0.0 < 21.0.0", + "@angular/compiler": ">=18.0.0 < 21.0.0", + "@angular/compiler-cli": ">=18.0.0 < 21.0.0", + "@angular/core": ">=18.0.0 < 21.0.0", + "@angular/forms": ">=18.0.0 < 21.0.0", + "@angular/platform-browser": ">=18.0.0 < 21.0.0", + "@angular/platform-browser-dynamic": ">=18.0.0 < 21.0.0", + "rxjs": "^6.5.3 || ^7.4.0", + "storybook": "^9.0.17", + "typescript": "^4.9.0 || ^5.0.0", + "zone.js": ">=0.14.0" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + }, + "@angular/cli": { + "optional": true + }, + "zone.js": { + "optional": true + } + } + }, + "node_modules/@storybook/angular/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/angular/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/angular/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@storybook/builder-webpack5": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-9.0.17.tgz", + "integrity": "sha512-LiP/nq3qv+Nowxeo4v/p/Rv7FkZS347iBnjTQJxXWpFXrCjfJujzcYizQ1WXKC5jXnLSl4hqLmaB0tzMc/zFiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/core-webpack": "9.0.17", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.0.17" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/builder-webpack5/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/core-webpack": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-9.0.17.tgz", + "integrity": "sha512-NyPSqYUZiD3ICHq/07IC06cDI5mwLA7cqmekWbD9BfSriI9RES88aQ7/WzliHLWwqQXj5Van3tt4IUfaU4Q3ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.0.17" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.0.17.tgz", + "integrity": "sha512-6Q4eo1ObrLlsnB6bIt6T8+45XAb4to2pQGNrI7QPkLQRLrZinrJcNbLY7AGkyIoCOEsEbq08n09/nClQUbu8HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.0.17" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/icons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.4.0.tgz", + "integrity": "sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/react-dom-shim": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.0.17.tgz", + "integrity": "sha512-ak/x/m6MDDxdE6rCDymTltaiQF3oiKrPHSwfM+YPgQR6MVmzTTs4+qaPfeev7FZEHq23IkfDMTmSTTJtX7Vs9A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^9.0.17" + } + }, + "node_modules/@stripe/stripe-js": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.6.1.tgz", + "integrity": "sha512-BUDj5gujbtx53/Cexws0+aPrEBsKAN8ExPf9UfuTCivVU6ug2PjqI0zUeL1jon3795eOLlyqvCDjp6VNknjE0A==", + "license": "MIT", + "engines": { + "node": ">=12.16" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.4.tgz", + "integrity": "sha512-xDXgLjVunjHqczScfkCJ9iyjdNOVHvvCdqHSSxwM9L0l/wHkTRum67SDc020uAlCoqktJplgO2AAQeLP1wgqDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tokenizer/inflate": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", + "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fflate": "^0.8.2", + "token-types": "^6.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz", + "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "javascript-natural-sort": "^0.7.1", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">18.12" + }, + "peerDependencies": { + "@vue/compiler-sfc": "3.x", + "prettier": "2.x - 3.x", + "prettier-plugin-svelte": "3.x", + "svelte": "4.x || 5.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "svelte": { + "optional": true + } + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-3.0.1.tgz", + "integrity": "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/big.js": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz", + "integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/diff-match-patch": { + "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", + "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/google-spreadsheet": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/google-spreadsheet/-/google-spreadsheet-3.1.5.tgz", + "integrity": "sha512-7N+mDtZ1pmya2RRFPPl4KYc2TRgiqCNBLUZfyrKfER+u751JgCO+C24/LzF70UmUm/zhHUbzRZ5mtfaxekQ1ZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.16", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", + "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/jsdom/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@types/jsdom/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/luxon": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.6.2.tgz", + "integrity": "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==", + "license": "MIT" + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.13.tgz", + "integrity": "sha512-zePQJSW5QkwSHKRApqWCVKeKoSOt4xvEnLENZPjyvm9Ezdf/EyDeJM7jqLzOwjVICQQzvLZ63T55MKdJB5H6ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/oauth": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz", + "integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/papaparse": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.7.tgz", + "integrity": "sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-google-oauth20": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", + "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-6//z+4orIOy/g3zx17HyQ71GSRK4bs7Sb+zFasRoc2xzlv7ZCJ+vkDBYFci8U6HY+or6Zy7ajf4mz4rK7nsWJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", + "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz", + "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sizzle": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", + "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/validator": { + "version": "13.15.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", + "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", + "license": "MIT" + }, + "node_modules/@types/webpack-env": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.8.tgz", + "integrity": "sha512-G9eAoJRMLjcvN4I08wB5I7YofOb/kaJNd5uoCMX+LbKXTPCF+ZIHuqTnFaK9Jz1rgs035f9JUPUhNFtqgucy/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz", + "integrity": "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/type-utils": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz", + "integrity": "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz", + "integrity": "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz", + "integrity": "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz", + "integrity": "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz", + "integrity": "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz", + "integrity": "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitejs/plugin-basic-ssl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz", + "integrity": "sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==", + "license": "MIT", + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", + "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ai": { + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.16.tgz", + "integrity": "sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/react": "1.2.12", + "@ai-sdk/ui-utils": "1.2.11", + "@opentelemetry/api": "1.9.0", + "jsondiffpatch": "0.6.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.32.0.tgz", + "integrity": "sha512-84xBncKNPBK8Ae89F65+SyVcOihrIbm/3N7to+GpRBHEUXGjA3ydWTMpcRW6jmFzkBQ/eqYy/y+J+NBpJWYjBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-abtesting": "5.32.0", + "@algolia/client-analytics": "5.32.0", + "@algolia/client-common": "5.32.0", + "@algolia/client-insights": "5.32.0", + "@algolia/client-personalization": "5.32.0", + "@algolia/client-query-suggestions": "5.32.0", + "@algolia/client-search": "5.32.0", + "@algolia/ingestion": "1.32.0", + "@algolia/monitoring": "1.32.0", + "@algolia/recommend": "5.32.0", + "@algolia/requester-browser-xhr": "5.32.0", + "@algolia/requester-fetch": "5.32.0", + "@algolia/requester-node-http": "5.32.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/alphavantage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/alphavantage/-/alphavantage-2.2.0.tgz", + "integrity": "sha512-wsN6c78DWEfnmT7zIqs95N0cBT/h9WHxby3pSscUtTA+wRIO29BqDJQqZnQcy6GddlIsBp5GQk8gEeIAR0FdBg==", + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", + "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true, + "license": "ISC" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz", + "integrity": "sha512-mRijnKimhGDMsizTvBTWotwNpzrkHr+VvZUQBof2AufXKB8NXrL1W69TG20EvOz7aevx6FTJIaBuBkYxS8zolg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.0.5", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.0", + "babel-preset-jest": "30.0.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-loader": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-10.0.0.tgz", + "integrity": "sha512-z8jt+EdS61AMw22nSfoNJAZ0vrtmhPRVi6ghL3rCeRZI8cdNYFiV5xeV3HbE7rlZZNmGH8BVccwWt8/ED0QOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": "^18.20.0 || ^20.10.0 || >=22.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5.61.0" + } + }, + "node_modules/babel-loader/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-const-enum": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-const-enum/-/babel-plugin-const-enum-1.2.0.tgz", + "integrity": "sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-typescript": "^7.3.3", + "@babel/traverse": "^7.16.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@stripe/stripe-js": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-5.4.0.tgz", - "integrity": "sha512-3tfMbSvLGB+OsJ2MsjWjWo+7sp29dwx+3+9kG/TEnZQJt+EwbF/Nomm43cSK+6oXZA9uhspgyrB+BbrPRumx4g==", + "node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", + "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "@types/babel__core": "^7.20.5" + }, "engines": { - "node": ">=12.16" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-typescript-metadata": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz", + "integrity": "sha512-mWEvCQTgXQf48yDqgN7CH50waTyYBeP2Lpqx4nNWab9sxEpdXVeKgfj1qYI2/TgUPQtNFZ85i3PemRtnXVYYJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", + "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/beasties": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.3.4.tgz", + "integrity": "sha512-NmzN1zN1cvGccXFyZ73335+ASXwBlVWcUPssiUDIlFdfyatHPRRufjCd5w8oPaQPvVnf9ELklaCGb1gi9FBwIw==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.8.0" + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "htmlparser2": "^10.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.49", + "postcss-media-query-parser": "^0.2.3" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@swc/helpers/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "node_modules/better-opn/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/better-opn/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "node_modules/better-opn/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" + "is-docker": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/better-opn/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "dequal": "^2.0.3" + "node_modules/big.js": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-7.0.1.tgz", + "integrity": "sha512-iFgV784tD8kq4ccF1xtNMZnXeZzVuXWWM+ERFzKQjv+A5G9HC8CY3DuV45vgzFFcW+u2tIvmF95+AzWgs6BjCg==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bigjs" } }, - "node_modules/@testing-library/dom/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "*" } }, - "node_modules/@testing-library/dom/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", - "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", - "redent": "^3.0.0" - }, "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", "dev": true, - "license": "MIT" + "license": "Apache-2.0" }, - "node_modules/@testing-library/user-event": { - "version": "14.5.2", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", - "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } + "license": "MIT" }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "devOptional": true, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=18" } }, - "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", - "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", - "dev": true, - "license": "Apache-2.0", + "node_modules/body-parser/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "@babel/generator": "7.17.7", - "@babel/parser": "^7.20.5", - "@babel/traverse": "7.23.2", - "@babel/types": "7.17.0", - "javascript-natural-sort": "0.7.1", - "lodash": "^4.17.21" + "side-channel": "^1.1.0" }, - "peerDependencies": { - "@vue/compiler-sfc": "3.x", - "prettier": "2.x - 3.x" + "engines": { + "node": ">=0.6" }, - "peerDependenciesMeta": { - "@vue/compiler-sfc": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator/node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "node_modules/borc/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", - "dev": true, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=6.9.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "fast-json-stable-stringify": "2.x" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" + "node-int64": "^0.4.0" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", "dev": true, - "license": "MIT", + "license": "(MIT OR Apache-2.0)", "bin": { - "jsesc": "bin/jsesc" + "btoa": "bin/btoa.js" }, "engines": { - "node": ">=4" + "node": ">= 0.4.0" } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/@trysound/sax": { + "node_modules/buffer-builder": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "devOptional": true, + "license": "MIT/X11" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": "*" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "license": "MIT" + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/@tufjs/models": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-3.0.1.tgz", - "integrity": "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==", - "dev": true, + "node_modules/bull": { + "version": "4.16.5", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.5.tgz", + "integrity": "sha512-lDsx2BzkKe7gkCYiT5Acj02DpTwDznl/VNN7Psn7M3USPG7Vs/BaClZJJTAG+ufAR9++N1/NiUTdaFBWDIl5TQ==", "license": "MIT", "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" + "cron-parser": "^4.9.0", + "get-port": "^5.1.1", + "ioredis": "^5.3.2", + "lodash": "^4.17.21", + "msgpackr": "^1.11.2", + "semver": "^7.5.2", + "uuid": "^8.3.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=12" } }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/bull/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "run-applescript": "^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tybys/wasm-util/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "devOptional": true, - "license": "MIT", + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "devOptional": true, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "devOptional": true, - "license": "MIT", + "node_modules/cacache": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "dev": true, + "license": "ISC", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" + "node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "node_modules/@types/big.js": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz", - "integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==", + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "node_modules/cacache/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/body-parser/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cacache/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/body-parser/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "license": "MIT", + "node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", "dependencies": { - "@types/node": "*" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/bonjour/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "node_modules/@types/bonjour/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/cache-manager": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.6.tgz", - "integrity": "sha512-8qL93MF05/xrzFm/LSPtzNEOE1eQF3VwGHAcQEylgp5hDSTe41jtFwbSYAPfyYcVa28y1vYSjIt0c1fLLUiC/Q==", + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "license": "MIT", "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/@types/cacheable-request/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cache-manager": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-7.1.0.tgz", + "integrity": "sha512-CzrGUt58dxUnbFo7OcmM5ee0SEo27ulCiXQIy6GbUMoSDs1UVlUSO00i+cPS+q994zcEy8KPN2JJF05Z8HEeiw==", "license": "MIT", + "peer": true, "dependencies": { - "undici-types": "~6.20.0" + "keyv": "^5.3.4" } }, - "node_modules/@types/cacheable-request/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/color": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz", - "integrity": "sha512-NMiNcZFRUAiUUCCf7zkAelY8eV3aKqfbzyFQlXpPIEeoNDbsEHGpb854V3gzTsGKYj830I5zPuOwU/TP5/cW6A==", + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/color-convert": "*" + "engines": { + "node": ">=6" } }, - "node_modules/@types/color-convert": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.4.tgz", - "integrity": "sha512-Ub1MmDdyZ7mX//g25uBAoH/mWGd9swVbt8BseymnaE18SU4po/PjmCrHxqIIRjBo3hV/vh1KGr0eMxUhp+t+dQ==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", "dependencies": { - "@types/color-name": "^1.1.0" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/color-name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.5.tgz", - "integrity": "sha512-j2K5UJqGTxeesj6oQuGpMgifpT5k9HprgQd8D1Y0lOFqKHl3PJu5GMeS4Y5EgjS55AE6OQxf8mPED9uaGbf4Cg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "@types/node": "*" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/connect-history-api-fallback/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=6" } }, - "node_modules/@types/connect-history-api-fallback/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/connect/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" } }, - "node_modules/@types/connect/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/@types/d3-scale": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", - "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@types/d3-time": "*" + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", - "license": "MIT", - "optional": true + "node_modules/caniuse-lite": { + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">=4" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "license": "Apache-2.0" }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "node_modules/chai": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", + "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@types/ms": "*" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "engines": { + "node": ">=10" } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, "license": "MIT" }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "node_modules/chart.js": { + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", + "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", "license": "MIT", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" } }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", - "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", + "node_modules/chartjs-adapter-date-fns": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", + "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "peerDependencies": { + "chart.js": ">=2.8.0", + "date-fns": ">=2.0.0" } }, - "node_modules/@types/express-serve-static-core/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/chartjs-chart-treemap": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/chartjs-chart-treemap/-/chartjs-chart-treemap-3.1.0.tgz", + "integrity": "sha512-0LJxj4J9sCTHmrXCFlqtoBKMJDcS7VzFeRgNBRZRwU1QSpCXJKTNk5TysPEs5/YW0XYvZoN8u44RqqLf0pAzQw==", "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "peerDependencies": { + "chart.js": ">=3.0.0" } }, - "node_modules/@types/express-serve-static-core/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/express/node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "node_modules/chartjs-plugin-annotation": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.1.0.tgz", + "integrity": "sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==", "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "peerDependencies": { + "chart.js": ">=4.0.0" } }, - "node_modules/@types/express/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/chartjs-plugin-datalabels": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", + "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "peerDependencies": { + "chart.js": ">=3.0.0" } }, - "node_modules/@types/express/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/google-spreadsheet": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/google-spreadsheet/-/google-spreadsheet-3.1.5.tgz", - "integrity": "sha512-7N+mDtZ1pmya2RRFPPl4KYc2TRgiqCNBLUZfyrKfER+u751JgCO+C24/LzF70UmUm/zhHUbzRZ5mtfaxekQ1ZQ==", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 16" + } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "devOptional": true, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@types/graceful-fs/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/@types/graceful-fs/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "license": "MIT" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "license": "MIT" + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } }, - "node_modules/@types/http-proxy": { - "version": "1.17.15", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", - "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "node_modules/cheerio/node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", "dependencies": { - "@types/node": "*" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, - "node_modules/@types/http-proxy/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cheerio/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/@types/http-proxy/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "devOptional": true, - "license": "MIT" + "node_modules/cheerio/node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "devOptional": true, - "license": "MIT", + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "devOptional": true, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", "license": "MIT", + "optional": true, "dependencies": { - "@types/istanbul-lib-report": "*" + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" } }, - "node_modules/@types/jest": { - "version": "29.5.13", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", - "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", - "dev": true, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "license": "MIT", "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" } }, - "node_modules/@types/jsdom/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=6.0" } }, - "node_modules/@types/jsdom/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, "license": "MIT" }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, "license": "MIT" }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", "license": "MIT" }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "node_modules/class-validator": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.2.tgz", + "integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==", "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/validator": "^13.11.8", + "libphonenumber-js": "^1.11.1", + "validator": "^13.9.0" } }, - "node_modules/@types/jsonwebtoken/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" } }, - "node_modules/@types/jsonwebtoken/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "node_modules/cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "restore-cursor": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/keyv/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/keyv/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", "license": "MIT", - "optional": true, "dependencies": { - "@types/unist": "^2" + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "node_modules/cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "license": "MIT" + "license": "MIT", + "dependencies": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "node_modules/cli-truncate/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/node-forge/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/node-forge/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } }, - "node_modules/@types/oauth": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz", - "integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==", - "dev": true, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", "license": "MIT", + "optional": true, "dependencies": { - "@types/node": "*" + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/oauth/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@types/oauth/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.8" + } }, - "node_modules/@types/papaparse": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.7.tgz", - "integrity": "sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@types/papaparse/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/papaparse/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/express": "*" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/passport-google-oauth20": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", - "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "node_modules/codelyzer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.1.tgz", + "integrity": "sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g==", "dev": true, "license": "MIT", "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-oauth2": "*" + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "peerDependencies": { + "@angular/compiler": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", + "@angular/core": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", + "tslint": "^5.0.0 || ^6.0.0" } }, - "node_modules/@types/passport-google-oauth20/node_modules/@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "node_modules/codelyzer/node_modules/@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/qs": "*", - "@types/serve-static": "*" + "peerDependencies": { + "tslib": "^1.10.0" } }, - "node_modules/@types/passport-oauth2": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", - "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "node_modules/codelyzer/node_modules/@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", "dev": true, "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/oauth": "*", - "@types/passport": "*" + "peerDependencies": { + "rxjs": "^6.5.3", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" } }, - "node_modules/@types/passport-oauth2/node_modules/@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "node_modules/codelyzer/node_modules/aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/qs": "*", - "@types/serve-static": "*" + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" } }, - "node_modules/@types/passport/node_modules/@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "node_modules/codelyzer/node_modules/axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/qs": "*", - "@types/serve-static": "*" + "ast-types-flow": "0.0.7" } }, - "node_modules/@types/prop-types": { - "version": "15.7.14", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "node_modules/codelyzer/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, - "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", - "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "node_modules/codelyzer/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, - "node_modules/@types/react-dom": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", - "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "node_modules/codelyzer/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/responselike/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/responselike/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/codelyzer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "node_modules/codelyzer/node_modules/zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==", + "dev": true, "license": "MIT" }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true, "license": "MIT" }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/color": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.0.tgz", + "integrity": "sha512-16BlyiuyLq3MLxpRWyOTiWsO3ii/eLQLJUQXBSNcxMBBSnyt1ee9YUdaozQp03ifwm5woztEZGDbk9RGVuCsdw==", "license": "MIT", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "color-convert": "^3.0.1", + "color-string": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/send/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@types/send/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "node_modules/color-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.0.1.tgz", + "integrity": "sha512-5z9FbYTZPAo8iKsNEqRNv+OlpBbDcoE+SY9GjLfDUHEfcNNV7tS9eSAlFHEaub/r5tBL9LtskAeq1l9SaoZ5tQ==", "license": "MIT", "dependencies": { - "@types/express": "*" + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/serve-index/node_modules/@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "node_modules/color-string/node_modules/color-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz", + "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==", "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/qs": "*", - "@types/serve-static": "*" + "engines": { + "node": ">=12.20" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/color/node_modules/color-convert": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.0.tgz", + "integrity": "sha512-TVoqAq8ZDIpK5lsQY874DDnu65CSsc9vzq0wLpNQ6UMBq81GSZocVazPiBbYGzngzBOIRahpkTzCLVe2at4MfA==", "license": "MIT", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" } }, - "node_modules/@types/serve-static/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/color/node_modules/color-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz", + "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==", "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=12.20" } }, - "node_modules/@types/serve-static/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz", - "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sizzle": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", - "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true, "license": "MIT" }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/sockjs/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/sockjs/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "license": "MIT" }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", "devOptional": true, "license": "MIT" }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "license": "MIT" - }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/validator": { - "version": "13.12.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", - "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==", - "license": "MIT" - }, - "node_modules/@types/webpack-env": { - "version": "1.18.5", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.5.tgz", - "integrity": "sha512-wz7kjjRRj8/Lty4B+Kr0LN6Ypc/3SymeCCGSbaXp2leH0ZVg/PriNiOwNj4bD4uphI7A8NXS4b6Gl373sfO5mA==", + "node_modules/columnify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "license": "MIT", "dependencies": { - "@types/node": "*" + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/@types/ws/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/ws/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "devOptional": true, + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "devOptional": true, - "license": "MIT" + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true, + "license": "ISC" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "mime-db": ">= 1.43.0 < 2" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "safe-buffer": "~5.1.0" } }, - "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "license": "MIT", + "optional": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true, + "license": "MIT" + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz", - "integrity": "sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==", - "dev": true, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.18.2", - "@typescript-eslint/utils": "8.18.2", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "safe-buffer": "5.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", - "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", - "dev": true, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", - "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", - "dev": true, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.18.2", - "eslint-visitor-keys": "^4.2.0" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.6.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "depd": "~2.0.0", + "keygrip": "~1.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.8" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz", - "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==", - "dev": true, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "devOptional": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "is-what": "^3.14.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "node_modules/copy-webpack-plugin": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.0.tgz", + "integrity": "sha512-FgR/h5a6hzJqATDGd9YG41SeDViH+0bkHn6WNXCi5zKAZkeESeSxLySSsFLHqLEVCh0E+rITmCf0dusXWYukeQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2", + "tinyglobby": "^0.2.12" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/webpack" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "webpack": "^5.1.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "node_modules/core-js-compat": { + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", + "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", "dev": true, "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" + "dependencies": { + "browserslist": "^4.25.1" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/core-js" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/@typescript-eslint/utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz", - "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==", - "dev": true, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node": ">= 0.10" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz", - "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==", + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.4.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", - "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", - "dev": true, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", "license": "MIT", + "optional": true, "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "layout-base": "^1.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", - "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "eslint-visitor-keys": "^4.2.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 6" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/countries-and-timezones": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.8.0.tgz", + "integrity": "sha512-+Ze9h5f4dQpUwbzTm0DEkiPiZyim9VHV4/mSnT4zNYJnrnfwsKjAZPtnp7J5VzejCDgySs+2SSc6MDdCnD43GA==", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8.x", + "npm": ">=5.x" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "node_modules/countries-list": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/countries-list/-/countries-list-3.1.1.tgz", + "integrity": "sha512-nPklKJ5qtmY5MdBKw1NiBAoyx5Sa7p2yPpljZyQ7gyCN1m+eMFs9I6CT37Mxt8zvR5L3VzD3DJBE4WQzX3WF4A==", + "license": "MIT" + }, + "node_modules/countup.js": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.2.tgz", + "integrity": "sha512-UtRoPH6udaru/MOhhZhI/GZHJKAyAxuKItD2Tr7AbrqrOPBX/uejWBBJt8q86169AMqKkE9h9/24kFWbUk/Bag==", + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" }, - "engines": { - "node": "^16.0.0 || >=18.0.0" + "bin": { + "create-jest": "bin/create-jest.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", - "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", + "node_modules/create-jest/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, - "license": "ISC" - }, - "node_modules/@vitejs/plugin-basic-ssl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", - "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", "license": "MIT", - "engines": { - "node": ">=14.6.0" + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/expect": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", - "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "node_modules/create-jest/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/expect/node_modules/@vitest/pretty-format": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", - "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "node_modules/create-jest/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/expect/node_modules/@vitest/utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", - "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "node_modules/create-jest/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "estree-walker": "^3.0.3", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", - "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", + "node_modules/create-jest/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/spy": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", - "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "node_modules/create-jest/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/utils": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", - "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", + "node_modules/create-jest/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.8", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "node_modules/create-jest/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "node_modules/create-jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "node_modules/create-jest/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, "license": "MIT" }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "license": "Apache-2.0", + "node_modules/create-jest/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@xtuc/long": "4.2.2" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "node_modules/create-jest/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "license": "MIT", + "node_modules/create-jest/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "node_modules/create-jest/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "node_modules/create-jest/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "license": "Apache-2.0" + "node_modules/create-jest/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "node_modules/create-jest/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT" }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", - "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", + "node_modules/create-jest/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=18.12.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@yarnpkg/parsers/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/create-jest/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "0BSD" + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@zkochan/js-yaml": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", - "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "node_modules/create-jest/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "devOptional": true, - "license": "BSD-3-Clause" + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "node_modules/create-jest/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/create-jest/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=6.5" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/create-jest/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "node_modules/create-jest/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "devOptional": true, + "node_modules/create-jest/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/create-jest/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", - "peerDependencies": { - "acorn": "^8" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/create-jest/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/create-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "node_modules/create-jest/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "node_modules/create-jest/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8.9" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/adm-zip": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", - "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "node_modules/create-jest/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=12.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "license": "MIT", + "node_modules/create-jest/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/create-jest/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/create-jest/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/create-jest/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, "engines": { - "node": ">= 14" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" + }, + "node_modules/cron": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cron/-/cron-4.3.0.tgz", + "integrity": "sha512-ciiYNLfSlF9MrDqnbMdRWFiA6oizSF7kA1osPP9lRzNu0Uu+AWog1UKy7SkckiDY2irrNjeO6qLyKnXC8oxmrw==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@types/luxon": "~3.6.0", + "luxon": "~3.6.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=18.x" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", "license": "MIT", "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "node-fetch": "^2.7.0" } }, - "node_modules/alphavantage": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/alphavantage/-/alphavantage-2.2.0.tgz", - "integrity": "sha512-wsN6c78DWEfnmT7zIqs95N0cBT/h9WHxby3pSscUtTA+wRIO29BqDJQqZnQcy6GddlIsBp5GQk8gEeIAR0FdBg==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { - "cross-fetch": "^3.0.5" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">= 8" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "license": "MIT", + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=6" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/css-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">= 18.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" - ], - "license": "Apache-2.0", - "bin": { - "ansi-html": "bin/ansi-html" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/ansi-regex": { + "node_modules/css-minimizer-webpack-plugin": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">= 14.15.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } } }, - "node_modules/any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "node_modules/css-minimizer-webpack-plugin/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", + "node_modules/css-minimizer-webpack-plugin/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/css-minimizer-webpack-plugin/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "node_modules/css-minimizer-webpack-plugin/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 6.0.0" + "node": ">=8" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", - "license": "MIT" - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "node_modules/css-minimizer-webpack-plugin/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "node_modules/css-minimizer-webpack-plugin/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "node_modules/css-minimizer-webpack-plugin/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/css-minimizer-webpack-plugin/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "node_modules/css-minimizer-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "node_modules/css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "through": "X.X.X" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" } }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "license": "BSD-3-Clause", + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "dev": true, + "license": "MIT", "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" }, "engines": { - "node": ">=12.0.0" + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" } }, - "node_modules/asn1js/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8" + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", "dev": true, "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, "engines": { - "node": ">=12" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" } }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.1" + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=4" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" } }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true, - "license": "ISC" + "license": "CC0-1.0" }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", "dev": true, "license": "MIT" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=8" } }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cypress": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.1.tgz", + "integrity": "sha512-OYkSgzA4J4Q7eMjZvNf5qWpBLR4RXrkqjL3UZ1UzGGLAskO0nFTi/RomNTG6TKvL3Zp4tw4zFY1gp5MtmkCZrA==", + "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" + "@cypress/listr-verbose-renderer": "^0.4.1", + "@cypress/request": "^2.88.5", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "^6.0.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.1.2", + "blob-util": "2.0.2", + "bluebird": "^3.7.2", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-table3": "~0.6.0", + "commander": "^5.1.0", + "common-tags": "^1.8.0", + "debug": "^4.1.1", + "eventemitter2": "^6.4.2", + "execa": "^4.0.2", + "executable": "^4.1.1", + "extract-zip": "^1.7.0", + "fs-extra": "^9.0.1", + "getos": "^3.2.1", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.2", + "lazy-ass": "^1.6.0", + "listr": "^0.14.3", + "lodash": "^4.17.19", + "log-symbols": "^4.0.0", + "minimist": "^1.2.5", + "moment": "^2.27.0", + "ospath": "^1.2.2", + "pretty-bytes": "^5.4.1", + "ramda": "~0.26.1", + "request-progress": "^3.0.0", + "supports-color": "^7.2.0", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "url": "^0.11.0", + "yauzl": "^2.10.0" }, "bin": { - "autoprefixer": "bin/autoprefixer" + "cypress": "bin/cypress" }, "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=10.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "dev": true, - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "node_modules/cypress/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axobject-query": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", - "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "ast-types-flow": "0.0.7" + "engines": { + "node": ">= 6" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "devOptional": true, + "node_modules/cytoscape": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.0.tgz", + "integrity": "sha512-2d2EwwhaxLWC8ahkH1PpQwCyu6EY3xDRdcEJXrLTb4fOUtVc+YWQalHU67rFS1a6ngj1fgv9dQLtJxP/KAFZEw==", "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, + "optional": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "node": ">=0.10" } }, - "node_modules/babel-loader": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", - "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", "license": "MIT", - "dependencies": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" + "optional": true, + "dependencies": { + "cose-base": "^1.0.0" }, "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" + "cytoscape": "^3.2.0" } }, - "node_modules/babel-plugin-const-enum": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-const-enum/-/babel-plugin-const-enum-1.2.0.tgz", - "integrity": "sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg==", - "dev": true, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-typescript": "^7.3.3", - "@babel/traverse": "^7.16.0" + "cose-base": "^2.2.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "cytoscape": "^3.2.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" + "layout-base": "^2.0.0" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT", + "optional": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "optional": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "devOptional": true, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "devOptional": true, - "license": "MIT", + "optional": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "internmap": "1 - 2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, - "license": "MIT", + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", "optional": true, - "peer": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": ">=12" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", - "license": "MIT", + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "optional": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", - "semver": "^6.3.1" + "d3-path": "1 - 3" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "optional": true, + "engines": { + "node": ">=12" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "license": "MIT", + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "optional": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "d3-array": "^3.2.0" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", - "license": "MIT", + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "optional": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" + "delaunator": "5" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-transform-typescript-metadata": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz", - "integrity": "sha512-mWEvCQTgXQf48yDqgN7CH50waTyYBeP2Lpqx4nNWab9sxEpdXVeKgfj1qYI2/TgUPQtNFZ85i3PemRtnXVYYJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "devOptional": true, - "license": "MIT", + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "optional": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "d3-dispatch": "1 - 3", + "d3-selection": "3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/base64-arraybuffer": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", - "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "optional": true, + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=12" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } }, - "node_modules/base64url": { + "node_modules/d3-ease": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "optional": true, "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "license": "MIT", + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "optional": true, "dependencies": { - "safe-buffer": "5.1.2" + "d3-dsv": "1 - 3" }, "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "license": "MIT" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "optional": true, "dependencies": { - "tweetnacl": "^0.14.3" + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" } }, - "node_modules/beasties": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.1.0.tgz", - "integrity": "sha512-+Ssscd2gVG24qRNC+E2g88D+xsQW4xwakWtKAiGEQ3Pw54/FGdyo9RrfxhGhEv6ilFVbB7r3Lgx+QnAxnSpECw==", - "license": "Apache-2.0", - "dependencies": { - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "htmlparser2": "^9.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-media-query-parser": "^0.2.3" + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" } }, - "node_modules/better-opn": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", - "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", - "dev": true, - "license": "MIT", + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "optional": true, "dependencies": { - "open": "^8.0.4" + "d3-array": "2.5.0 - 3" }, "engines": { - "node": ">=12.0.0" + "node": ">=12" } }, - "node_modules/better-opn/node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "license": "MIT", + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "optional": true, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/better-opn/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "optional": true, "dependencies": { - "is-docker": "^2.0.0" + "d3-color": "1 - 3" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/better-opn/node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "optional": true, "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/big.js": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", - "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", - "license": "MIT", + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "optional": true, "engines": { - "node": "*" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bigjs" + "node": ">=12" } }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "license": "MIT", + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "optional": true, "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "optional": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "optional": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "internmap": "^1.0.0" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause", + "optional": true }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "license": "MIT", + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "optional": true, "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "d3-path": "1" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC", + "optional": true }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", - "license": "MIT", + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "optional": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "license": "ISC" - }, - "node_modules/bootstrap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", - "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, - "peerDependencies": { - "jquery": "1.9.1 - 3", - "popper.js": "^1.16.1" + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" } }, - "node_modules/borc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", - "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", - "license": "MIT", + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "optional": true, "dependencies": { - "bignumber.js": "^9.0.0", - "buffer": "^5.5.0", - "commander": "^2.15.0", - "ieee754": "^1.1.13", - "iso-url": "~0.4.7", - "json-text-sequence": "~0.1.0", - "readable-stream": "^3.6.0" + "d3-path": "^3.1.0" }, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "devOptional": true, - "license": "MIT", + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "optional": true, "dependencies": { - "balanced-match": "^1.0.0" + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "optional": true, "dependencies": { - "fill-range": "^7.1.1" + "d3-time": "1 - 3" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/browser-assert": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", - "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", - "dev": true + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } }, - "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "optional": true, "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "license": "MIT", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "optional": true, "dependencies": { - "fast-json-stable-stringify": "2.x" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": ">= 6" + "node": ">=12" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "devOptional": true, - "license": "Apache-2.0", + "node_modules/dagre-d3-es": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "license": "MIT", + "optional": true, "dependencies": { - "node-int64": "^0.4.0" + "d3": "^7.9.0", + "lodash-es": "^4.17.21" } }, - "node_modules/btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true, - "license": "(MIT OR Apache-2.0)", - "bin": { - "btoa": "bin/btoa.js" - }, - "engines": { - "node": ">= 0.4.0" - } + "license": "BSD-2-Clause" }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", "dev": true, "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/bull": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.2.tgz", - "integrity": "sha512-VCy33UdPGiIoZHDTrslGXKXWxcIUHNH5Z82pihr8HicbIfAH4SHug1HxlwKEbibVv85hq8rJ9tKAW/cuxv2T0A==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, "license": "MIT", "dependencies": { - "cron-parser": "^4.2.1", - "get-port": "^5.1.1", - "ioredis": "^5.3.2", - "lodash": "^4.17.21", - "msgpackr": "^1.10.1", - "semver": "^7.5.2", - "uuid": "^8.3.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=12" - } - }, - "node_modules/bull/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, "license": "MIT", "dependencies": { - "run-applescript": "^7.0.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", "dependencies": { - "streamsearch": "^1.1.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=10.16.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", "license": "MIT", - "engines": { - "node": ">= 0.8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/cacache": { - "version": "19.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", - "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^4.0.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=4.0" } }, - "node_modules/cacache/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT", + "optional": true }, - "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/cacache/node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", - "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - }, "engines": { - "node": ">= 6.0.0" + "node": ">=6" } }, - "node_modules/cache-manager": { - "version": "5.7.6", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz", - "integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==", + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "lodash.clonedeep": "^4.5.0", - "lru-cache": "^10.2.2", - "promise-coalesce": "^1.1.2" - }, "engines": { - "node": ">= 18" + "node": ">=0.10.0" } }, - "node_modules/cache-manager-redis-yet": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/cache-manager-redis-yet/-/cache-manager-redis-yet-5.1.4.tgz", - "integrity": "sha512-2mXZjo+txfH2m+mSTHTITNq8c5SssU2nP7NutzrocO3Mw/SbjHcDo+mriI3ZuR63ov/oUUIaF9iF+MzDqVzMoQ==", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, "license": "MIT", "dependencies": { - "@redis/bloom": "^1.2.0", - "@redis/client": "^1.6.0", - "@redis/graph": "^1.1.1", - "@redis/json": "^1.0.7", - "@redis/search": "^1.2.0", - "@redis/time-series": "^1.1.0", - "cache-manager": "^5.7.6", - "redis": "^4.7.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">= 18" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "node": ">=18" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -14478,27 +19465,29 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -14507,2502 +19496,2746 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "optional": true, + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "devOptional": true, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "optional": true + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", + "license": "BSD-2-Clause" + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" } }, - "node_modules/camel-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "devOptional": true, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, - "license": "Apache-2.0" + "license": "MIT" }, - "node_modules/chai": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", - "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", "dev": true, "license": "MIT", "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" }, "engines": { - "node": ">=12" + "node": ">= 4.0.0" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.3.1" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "devOptional": true, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "license": "Apache-2.0" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "license": "MIT", - "optional": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, - "license": "MIT" - }, - "node_modules/chart.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.0.tgz", - "integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==", "license": "MIT", "dependencies": { - "@kurkle/color": "^0.3.0" + "@leichtgewicht/ip-codec": "^2.0.1" }, "engines": { - "pnpm": "^7.0.0" + "node": ">=6" } }, - "node_modules/chartjs-adapter-date-fns": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", - "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", - "license": "MIT", - "peerDependencies": { - "chart.js": ">=2.8.0", - "date-fns": ">=2.0.0" + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/chartjs-chart-treemap": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/chartjs-chart-treemap/-/chartjs-chart-treemap-2.3.1.tgz", - "integrity": "sha512-GW+iODLICIJhNZtHbTtaOjCwRIxmXcquXRKDFMsrkXyqyDeSN1aiVfzNNj6Xjy55soopqRA+YfHqjT2S2zF7lQ==", + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, "license": "MIT", - "peerDependencies": { - "chart.js": ">=3.0.0" - } + "peer": true }, - "node_modules/chartjs-plugin-annotation": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-2.1.2.tgz", - "integrity": "sha512-kmEp2WtpogwnKKnDPO3iO3mVwvVGtmG5BkZVtAEZm5YzJ9CYxojjYEgk7OTrFbJ5vU098b84UeJRe8kRfNcq5g==", + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, "license": "MIT", - "peerDependencies": { - "chart.js": ">=3.7.0" + "dependencies": { + "utila": "~0.4" } }, - "node_modules/chartjs-plugin-datalabels": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", - "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "license": "MIT", - "peerDependencies": { - "chart.js": ">=3.0.0" + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cheerio": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", - "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", - "license": "MIT", "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "encoding-sniffer": "^0.2.0", - "htmlparser2": "^9.1.0", - "parse5": "^7.1.2", - "parse5-htmlparser2-tree-adapter": "^7.0.0", - "parse5-parser-stream": "^7.1.2", - "undici": "^6.19.5", - "whatwg-mimetype": "^4.0.0" + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=18.17" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + "node": ">=12" } }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "license": "BSD-2-Clause", "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/cheerio/node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "license": "MIT", - "engines": { - "node": ">=18" + "node_modules/dompurify": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", + "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "license": "MIT", + "node_modules/dotenv-expand": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.1.tgz", + "integrity": "sha512-LaKRbou8gt0RNID/9RoI+J2rvXsBRPMV7p+ElHlPhcSARbCPDYcYG2s1TIzAfWv4YSgyY5taidWzzs31lNV3yQ==", + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, "engines": { - "node": ">=6.0" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "devOptional": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", - "devOptional": true, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true, "license": "MIT" }, - "node_modules/class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, "license": "MIT" }, - "node_modules/class-validator": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", - "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/validator": "^13.11.8", - "libphonenumber-js": "^1.10.53", - "validator": "^13.9.0" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "devOptional": true, - "license": "MIT", + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" + "safe-buffer": "^5.0.1" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "license": "MIT", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "restore-cursor": "^3.1.0" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/electron-to-chromium": { + "version": "1.5.192", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.192.tgz", + "integrity": "sha512-rP8Ez0w7UNw/9j5eSXCe10o1g/8B1P5SM90PCCMVkIRQn2R0LEHWz4Eh9RnxkniuDe1W0cTSOB3MLlkTGDcuCg==", + "license": "ISC" + }, + "node_modules/elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, "engines": { - "node": "10.* || >= 12.*" + "node": ">=12" }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/emoji-toolkit": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-9.0.1.tgz", + "integrity": "sha512-sMMNqKNLVHXJfIKoPbrRJwtYuysVNC9GlKetr72zE3SSVbHqoeDLWVrxP0uM0AE0qvdl3hbUk+tJhhwXZrDHaw==", + "license": "MIT", + "optional": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "license": "MIT" - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "devOptional": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "iconv-lite": "^0.6.2" } }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "license": "ISC", - "engines": { - "node": ">= 12" + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/clipboard": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", - "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" + "once": "^1.4.0" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", + "node_modules/enhanced-resolve": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=12" + "node": ">=10.13.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-colors": "^4.1.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8.6" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "license": "MIT", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.8" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, "engines": { "node": ">=6" } }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/envalid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/envalid/-/envalid-8.0.0.tgz", + "integrity": "sha512-PGeYJnJB5naN0ME6SH8nFcDj9HVbLpYIfg1p5lAyM9T4cH2lwtu2fLbozC/bq+HUUOIFxhX/LP0/GmlqPHT4tQ==", "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "tslib": "2.6.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.12" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "node_modules/envalid/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clone-response/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "devOptional": true, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "dependencies": { + "is-arrayish": "^0.2.1" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "stackframe": "^1.3.4" } }, - "node_modules/codelyzer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.1.tgz", - "integrity": "sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g==", + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, "license": "MIT", "dependencies": { - "@angular/compiler": "9.0.0", - "@angular/core": "9.0.0", - "app-root-path": "^3.0.0", - "aria-query": "^3.0.0", - "axobject-query": "2.0.2", - "css-selector-tokenizer": "^0.7.1", - "cssauron": "^1.4.0", - "damerau-levenshtein": "^1.0.4", - "rxjs": "^6.5.3", - "semver-dsl": "^1.0.1", - "source-map": "^0.5.7", - "sprintf-js": "^1.1.2", - "tslib": "^1.10.0", - "zone.js": "~0.10.3" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, - "peerDependencies": { - "@angular/compiler": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", - "@angular/core": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", - "tslint": "^5.0.0 || ^6.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/codelyzer/node_modules/@angular/compiler": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", - "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", - "dev": true, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "peerDependencies": { - "tslib": "^1.10.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/codelyzer/node_modules/@angular/core": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", - "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "peerDependencies": { - "rxjs": "^6.5.3", - "tslib": "^1.10.0", - "zone.js": "~0.10.2" + "engines": { + "node": ">= 0.4" } }, - "node_modules/codelyzer/node_modules/aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { - "ast-types-flow": "0.0.7", - "commander": "^2.11.0" + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/codelyzer/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "tslib": "^1.9.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "npm": ">=2.0.0" + "node": ">= 0.4" } }, - "node_modules/codelyzer/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/codelyzer/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/codelyzer/node_modules/zone.js": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", - "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==", + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, - "license": "MIT" - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { - "node": ">=12.5.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=7.0.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/esbuild-register": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dev": true, "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" } }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", + "node_modules/esbuild-wasm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.25.5.tgz", + "integrity": "sha512-V/rbdOws2gDcnCAECfPrajhuafI0WY4WumUgc8ZHwOLnvmM0doLQ+dqvVFI2qkVxQsvo6880aC9IjpyDqcwwTw==", "dev": true, "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=8.0.0" + "node": ">=18" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "devOptional": true, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/comment-json": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz", - "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">= 6" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "license": "ISC" - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "optional": true, "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/eslint": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", + "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "dev": true, "license": "MIT", "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.24.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compressible/node_modules/mime-db": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", - "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "node_modules/eslint-config-prettier": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "dev": true, "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.0.2", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "engines": { - "node": ">= 0.8.0" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/compression/node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "ms": "^2.1.1" } }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/eslint-plugin-cypress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-4.2.0.tgz", + "integrity": "sha512-v5cyt0VYb1tEEODBJSE44PocYOwQsckyexJhCs7LtdD3FGO6D2GjnZB2s2Sts4RcxdxECTWX01nObOZRs26bQw==", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "globals": "^15.11.0" + }, + "peerDependencies": { + "eslint": ">=9" } }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "node_modules/eslint-plugin-cypress/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, - "license": "MIT" - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "license": "MIT" - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">= 0.6" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-storybook": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-9.0.17.tgz", + "integrity": "sha512-IuTdlwCEwoDNobdygRCxNhlKXHmsDfPtPvHGcsY35x2Bx8KItrjfekO19gJrjc1VT2CMfcZMYF8OBKaxHELupw==", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.8.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=20.0.0" + }, + "peerDependencies": { + "eslint": ">=8", + "storybook": "^9.0.17" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/cookies": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", - "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { - "is-what": "^3.14.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", - "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 12.20.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/copy-webpack-plugin/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-js-compat": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", - "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.2" + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">= 0.10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">= 0.4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/cose-base": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", - "license": "MIT", - "optional": true, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "layout-base": "^1.0.0" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": ">=4.0" } }, - "node_modules/countries-and-timezones": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.7.2.tgz", - "integrity": "sha512-BHAMt4pKb3U3r/mRfiIlVnDhRd8m6VC20gwCWtpZGZkSsjZmnMDKFnnjWYGWhBmypQAqcQILFJwmEhIgWGVTmw==", - "license": "MIT", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=8.x", - "npm": ">=5.x" + "node": ">=4.0" } }, - "node_modules/countries-list": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/countries-list/-/countries-list-3.1.1.tgz", - "integrity": "sha512-nPklKJ5qtmY5MdBKw1NiBAoyx5Sa7p2yPpljZyQ7gyCN1m+eMFs9I6CT37Mxt8zvR5L3VzD3DJBE4WQzX3WF4A==", - "license": "MIT" + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/countup.js": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.0.tgz", - "integrity": "sha512-f7xEhX0awl4NOElHulrl4XRfKoNH3rB+qfNSZZyjSZhaAoUk6elvhH+MNxMmlmuUJ2/QNTWPSA7U4mNtIAKljQ==", - "license": "MIT" + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "devOptional": true, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", "license": "MIT" }, - "node_modules/cron": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.0.tgz", - "integrity": "sha512-Cx77ic1TyIAtUggr0oAhtS8MLzPBUqGNIvdDM7jE3oFIxfe8LXWI9q3iQN/H2CebAiMir53LQKWOhEKnzkJTAQ==", + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "license": "MIT", - "dependencies": { - "luxon": "^3.2.1" + "engines": { + "node": ">=0.8.x" } }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, "license": "MIT", "dependencies": { - "luxon": "^3.2.1" + "eventsource-parser": "^3.0.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "node_modules/eventsource-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.3.tgz", + "integrity": "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==", + "dev": true, "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "devOptional": true, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, - "license": "ISC", + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "pify": "^2.2.0" }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "node_modules/css-declaration-sorter": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", - "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "license": "ISC", "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": ">= 0.8.0" } }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "node_modules/exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dev": true, "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", - "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "cssnano": "^6.0.1", - "jest-worker": "^29.4.3", - "postcss": "^8.4.24", - "schema-utils": "^4.0.1", - "serialize-javascript": "^6.0.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "lightningcss": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "license": "BSD-2-Clause", + "node_modules/expect/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-selector-tokenizer": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", - "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "node_modules/expect/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "fastparse": "^1.1.2" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "node_modules/expect/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/expect/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "license": "BSD-2-Clause", + "node_modules/expect/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node": ">=8" } }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cssauron": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", - "integrity": "sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw==", + "node_modules/expect/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { - "through": "X.X.X" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/expect/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssnano": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", - "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "node_modules/expect/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "cssnano-preset-default": "^6.1.2", - "lilconfig": "^3.1.1" - }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=8.6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/cssnano-preset-default": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", - "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "node_modules/exponential-backoff": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", + "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.23.0", - "css-declaration-sorter": "^7.2.0", - "cssnano-utils": "^4.0.2", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.1.0", - "postcss-convert-values": "^6.1.0", - "postcss-discard-comments": "^6.0.2", - "postcss-discard-duplicates": "^6.0.3", - "postcss-discard-empty": "^6.0.3", - "postcss-discard-overridden": "^6.0.2", - "postcss-merge-longhand": "^6.0.5", - "postcss-merge-rules": "^6.1.1", - "postcss-minify-font-values": "^6.1.0", - "postcss-minify-gradients": "^6.0.3", - "postcss-minify-params": "^6.1.0", - "postcss-minify-selectors": "^6.0.4", - "postcss-normalize-charset": "^6.0.2", - "postcss-normalize-display-values": "^6.0.2", - "postcss-normalize-positions": "^6.0.2", - "postcss-normalize-repeat-style": "^6.0.2", - "postcss-normalize-string": "^6.0.2", - "postcss-normalize-timing-functions": "^6.0.2", - "postcss-normalize-unicode": "^6.1.0", - "postcss-normalize-url": "^6.0.2", - "postcss-normalize-whitespace": "^6.0.2", - "postcss-ordered-values": "^6.0.2", - "postcss-reduce-initial": "^6.1.0", - "postcss-reduce-transforms": "^6.0.2", - "postcss-svgo": "^6.0.3", - "postcss-unique-selectors": "^6.0.4" + "license": "Apache-2.0" + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">= 18" }, - "peerDependencies": { - "postcss": "^8.4.31" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/cssnano-utils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", - "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", "dev": true, "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" }, "peerDependencies": { - "postcss": "^8.4.31" + "express": ">= 4.11" } }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, + "node_modules/express/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "dependencies": { - "css-tree": "~2.2.0" - }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">= 0.6" } }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, + "node_modules/express/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" + "mime-db": "^1.54.0" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">= 0.6" } }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "devOptional": true, - "license": "MIT", + "node_modules/express/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "cssom": "~0.3.6" + "side-channel": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "devOptional": true, - "license": "MIT" + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "license": "MIT", + "optional": true }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, - "node_modules/cypress": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.1.tgz", - "integrity": "sha512-OYkSgzA4J4Q7eMjZvNf5qWpBLR4RXrkqjL3UZ1UzGGLAskO0nFTi/RomNTG6TKvL3Zp4tw4zFY1gp5MtmkCZrA==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "@cypress/listr-verbose-renderer": "^0.4.1", - "@cypress/request": "^2.88.5", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "^6.0.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.1.2", - "blob-util": "2.0.2", - "bluebird": "^3.7.2", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-table3": "~0.6.0", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "debug": "^4.1.1", - "eventemitter2": "^6.4.2", - "execa": "^4.0.2", - "executable": "^4.1.1", - "extract-zip": "^1.7.0", - "fs-extra": "^9.0.1", - "getos": "^3.2.1", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.2", - "lazy-ass": "^1.6.0", - "listr": "^0.14.3", - "lodash": "^4.17.19", - "log-symbols": "^4.0.0", - "minimist": "^1.2.5", - "moment": "^2.27.0", - "ospath": "^1.2.2", - "pretty-bytes": "^5.4.1", - "ramda": "~0.26.1", - "request-progress": "^3.0.0", - "supports-color": "^7.2.0", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "url": "^0.11.0", - "yauzl": "^2.10.0" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, - "bin": { - "cypress": "bin/cypress" + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=10.0.0" + "node": ">=0.10.0" } }, - "node_modules/cypress/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, "engines": { - "node": ">= 6" + "node": ">=0.6.0" } }, - "node_modules/cytoscape": { - "version": "3.30.4", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.4.tgz", - "integrity": "sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A==", + "node_modules/extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + } + }, + "node_modules/extract-zip/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/cytoscape-cose-bilkent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "node_modules/extract-zip/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "cose-base": "^1.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, - "peerDependencies": { - "cytoscape": "^3.2.0" + "engines": { + "node": ">=8.6.0" } }, - "node_modules/d3": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", - "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", - "optional": true, "dependencies": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=12" + "node": ">= 6" } }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "license": "Apache-2.0" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, "license": "ISC", - "optional": true, "dependencies": { - "internmap": "1 - 2" + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" }, "engines": { - "node": ">=12" + "node": ">=0.8.0" } }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "license": "ISC", - "optional": true, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" + "walk-up-path": "^3.0.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "engines": { - "node": ">=12" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "license": "ISC", - "optional": true, + "node_modules/fetch-mock-cache": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fetch-mock-cache/-/fetch-mock-cache-2.1.3.tgz", + "integrity": "sha512-fiQO09fEhN6ZY7GMb71cs9P09B3lBgGQ9CygydJHKQWZQv95bzsyl6dJERHuy34tQyG0gsHZK1pR/6Pkj2b9Qw==", + "license": "MIT", "dependencies": { - "d3-path": "1 - 3" + "debug": "^4.3.4", + "filenamify-url": "2.1.2" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "optional": true, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.8.0" } }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "license": "ISC", - "optional": true, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "^3.2.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=16.0.0" } }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "optional": true, + "node_modules/file-type": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", + "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", + "license": "MIT", "dependencies": { - "delaunator": "5" + "@tokenizer/inflate": "^0.2.7", + "strtok3": "^10.2.2", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=12" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" } }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "optional": true, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" + "balanced-match": "^1.0.0" } }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "license": "ISC", - "optional": true, "dependencies": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json.js", - "csv2tsv": "bin/dsv2dsv.js", - "dsv2dsv": "bin/dsv2dsv.js", - "dsv2json": "bin/dsv2json.js", - "json2csv": "bin/json2dsv.js", - "json2dsv": "bin/json2dsv.js", - "json2tsv": "bin/json2dsv.js", - "tsv2csv": "bin/dsv2dsv.js", - "tsv2json": "bin/dsv2json.js" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/d3-dsv/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "optional": true, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "license": "ISC", - "optional": true, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "license": "MIT", "dependencies": { - "d3-dsv": "1 - 3" + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "license": "ISC", - "optional": true, + "node_modules/filenamify-url": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-2.1.2.tgz", + "integrity": "sha512-3rMbAr7vDNMOGsj1aMniQFl749QjgM+lMJ/77ZRSPTIgxvolZwoQbn8dXLs7xfd+hAdli+oTnSWZNkJJLWQFEQ==", + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" + "filenamify": "^4.3.0", + "humanize-url": "^2.1.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "optional": true, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, + "license": "MIT", "dependencies": { - "d3-array": "2.5.0 - 3" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "optional": true, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", "dependencies": { - "d3-color": "1 - 3" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "optional": true, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, "engines": { - "node": ">=12" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "license": "ISC", - "optional": true, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "optional": true, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, "engines": { - "node": ">=12" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "license": "ISC", - "optional": true, + "node_modules/find-file-up": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-2.0.1.tgz", + "integrity": "sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-dir": "^1.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "optional": true, + "node_modules/find-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-2.0.0.tgz", + "integrity": "sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" + "find-file-up": "^2.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "optional": true, + "node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "license": "MIT", "dependencies": { - "internmap": "^1.0.0" + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "d3-path": "1" + "bin": { + "flat": "cli.js" } }, - "node_modules/d3-sankey/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC", - "optional": true - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "optional": true, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">=12" + "node": ">=16" } }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "optional": true, + "node_modules/flat-cache/node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" + "json-buffer": "3.0.1" } }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" - } + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "optional": true, - "dependencies": { - "d3-path": "^3.1.0" - }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "optional": true, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "2 - 3" + "is-callable": "^1.2.7" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, "license": "ISC", - "optional": true, "dependencies": { - "d3-time": "1 - 3" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "optional": true, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "optional": true, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "7.2.13", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz", + "integrity": "sha512-fR3WRkOb4bQdWB/y7ssDUlVdrclvwtyCUIHCfivAoYxq9dF7XfrDKbMdZIfwJ7hxIAqkYSGeU7lLJE6xrxIBdg==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" }, "engines": { - "node": ">=12" + "node": ">=12.13.0", + "yarn": ">=1.0.0" }, "peerDependencies": { - "d3-selection": "2 - 3" + "typescript": ">3.6.0", + "vue-template-compiler": "*", + "webpack": "^5.11.0" + }, + "peerDependenciesMeta": { + "vue-template-compiler": { + "optional": true + } } }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "optional": true, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=12" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/dagre-d3-es": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", - "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "d3": "^7.8.2", - "lodash-es": "^4.17.21" + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=0.10" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "devOptional": true, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "license": "MIT", "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { "node": ">=12" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/inspect-js" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.10.0" } }, - "node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "node_modules/form-data": { + "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": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, "engines": { - "node": ">=4.0" + "node": ">= 6" } }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", - "optional": true + "engines": { + "node": ">= 0.6" + } }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" + "node": "*" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", - "optional": true, - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 0.8" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "js-yaml": "^3.13.1" } }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "devOptional": true, + "node_modules/front-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "node_modules/front-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "node_modules/front-matter/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "devOptional": true, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "license": "MIT", + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "license": "ISC", "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "node_modules/fs-monkey": { + "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" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "license": "MIT", - "engines": { - "node": ">=10" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -17011,1444 +22244,1423 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, + "node_modules/fuse.js": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz", + "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==", + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "optional": true, + "node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "license": "Apache-2.0", "dependencies": { - "robust-predicates": "^3.0.2" + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "devOptional": true, + "node_modules/gaxios/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", + "dependencies": { + "debug": "4" + }, "engines": { - "node": ">=0.4.0" + "node": ">= 6.0.0" } }, - "node_modules/delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", - "optional": true - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/delimit-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", - "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", - "license": "BSD-2-Clause" - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, "engines": { - "node": ">=0.10" + "node": ">= 6" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", + "node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "devOptional": true, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" } }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "license": "Apache-2.0", - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { - "node": ">=0.10" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "devOptional": true, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "license": "MIT" - }, - "node_modules/detect-port": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", - "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "license": "BSD-3-Clause", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=8.0.0" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "devOptional": true, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "license": "MIT", "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" + "pump": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "node_modules/get-them-args": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz", + "integrity": "sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==", "dev": true, "license": "MIT" }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "async": "^3.2.0" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "devOptional": true, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" + "assert-plus": "^1.0.0" } }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "license": "BSD-2-Clause", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/dompurify": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", - "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true - }, - "node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", - "license": "BSD-2-Clause", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "is-glob": "^4.0.3" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "devOptional": true, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "balanced-match": "^1.0.0" } }, - "node_modules/dot-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" - }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "ini": "1.3.7" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "node_modules/global-dirs/node_modules/ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", "dev": true, - "license": "MIT" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "devOptional": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "license": "MIT", "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "jake": "^10.8.5" + "isexe": "^2.0.0" }, "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" + "which": "bin/which" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", - "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", - "license": "ISC" - }, - "node_modules/elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/elkjs": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", - "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", - "license": "EPL-2.0", - "optional": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "devOptional": true, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/emoji-toolkit": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-8.0.0.tgz", - "integrity": "sha512-Vz8YIqQJsQ+QZ4yuKMMzliXceayqfWbNjb6bST+vm77QAhU2is3I+/PRxrNknW+q1bvHHMgjLCQXxzINWLVapg==", - "license": "MIT", - "optional": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, "license": "MIT", + "dependencies": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, "engines": { - "node": ">= 4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/globby/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "devOptional": true, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", "license": "MIT", + "optional": true, "dependencies": { - "iconv-lite": "^0.6.2" + "delegate": "^3.1.2" } }, - "node_modules/encoding-sniffer": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", - "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", - "license": "MIT", + "node_modules/google-auth-library": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", + "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", + "license": "Apache-2.0", "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/encoding-sniffer/node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "license": "MIT", + "node_modules/google-auth-library/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { - "iconv-lite": "0.6.3" + "yallist": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "deprecated": "Package is no longer maintained", "license": "MIT", "dependencies": { - "once": "^1.4.0" + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/enhanced-resolve": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", - "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", - "license": "MIT", + "node_modules/google-spreadsheet": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/google-spreadsheet/-/google-spreadsheet-3.2.0.tgz", + "integrity": "sha512-z7XMaqb+26rdo8p51r5O03u8aPLAPzn5YhOXYJPcf2hdMVr0dUbIARgdkRdmGiBeoV/QoU/7VNhq1MMCLZv3kQ==", + "license": "Unlicense", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "axios": "^0.21.4", + "google-auth-library": "^6.1.3", + "lodash": "^4.17.21" }, "engines": { - "node": ">=10.13.0" + "node": ">=0.8.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, + "node_modules/google-spreadsheet/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" + "follow-redirects": "^1.14.0" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "license": "MIT", - "engines": { - "node": ">=6" - } + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, - "node_modules/envalid": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/envalid/-/envalid-7.3.1.tgz", - "integrity": "sha512-KL1YRwn8WcoF/Ty7t+yLLtZol01xr9ZJMTjzoGRM8NaSU+nQQjSWOQKKJhJP2P57bpdakJ9jbxqQX4fGTOicZg==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", "license": "MIT", "dependencies": { - "tslib": "2.3.1" + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" }, "engines": { - "node": ">=8.12" + "node": ">=10" } }, - "node_modules/envalid/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "license": "0BSD" - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT", + "optional": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true, "license": "MIT" }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true, + "license": "(Apache-2.0 OR MPL-1.1)" + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "prr": "~1.0.1" + "ansi-regex": "^2.0.0" }, - "bin": { - "errno": "cli.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/es-abstract": { - "version": "1.23.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz", - "integrity": "sha512-OygGC8kIcDhXX+6yAZRGLqwi2CmEXCbLQixeGUgYeR+Qwlppqmo7DIDr8XibtEBZp+fJcoYpoatp5qwLMEdcqQ==", + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.6", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-regex-test": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" + "bin": { + "he": "bin/he" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "node_modules/helmet": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.0.0.tgz", + "integrity": "sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "parse-passwd": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/esbuild-register": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", - "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4" - }, - "peerDependencies": { - "esbuild": ">=0.12 <1" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, - "node_modules/esbuild-wasm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.0.tgz", - "integrity": "sha512-xhNn5tL1AhkPg4ft59yXT6FkwKXiPSYyz1IeinJHUJpjvOHOIPvdmFQc0pGdjxlKSbzZc2mNmtVOWAR1EF/JAg==", + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/html-encoding-sniffer/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "license": "BSD-2-Clause", + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "license": "MIT", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" }, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "html-minifier-terser": "cli.js" }, "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">=12" } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 12" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "node_modules/html-webpack-plugin": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", + "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" } }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=0.12" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", "dev": true, "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "engines": { + "node": ">= 0.6" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "node_modules/http-assert/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } + "license": "BSD-2-Clause" }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true, "license": "MIT" }, - "node_modules/eslint-plugin-cypress": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.1.tgz", - "integrity": "sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==", - "dev": true, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { - "globals": "^13.20.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, - "peerDependencies": { - "eslint": ">= 3.2.1" + "engines": { + "node": ">= 0.8" } }, - "node_modules/eslint-plugin-cypress/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/eslint-plugin-cypress/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "debug": "4" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/http-proxy-middleware": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", + "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.15", + "debug": "^4.3.6", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.3", + "is-plain-object": "^5.0.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", "dev": true, "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" } }, - "node_modules/eslint-plugin-storybook": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.15.tgz", - "integrity": "sha512-lAGqVAJGob47Griu29KXYowI4G7KwMoJDOkEip8ujikuDLxU+oWJ1l0WL6F2oDO4QiyUFXvtDkEkISMOPzo+7w==", + "node_modules/http-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf": "^0.0.1", - "@typescript-eslint/utils": "^5.45.0", - "requireindex": "^1.1.0", - "ts-dedent": "^2.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "12.x || 14.x || >= 16" + "node": ">=10" }, - "peerDependencies": { - "eslint": ">=6" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", - "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, "license": "MIT", "dependencies": { - "lodash": "^4.17.15" + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 14" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=8.12.0" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/humanize-url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-2.1.1.tgz", + "integrity": "sha512-V4nxsPGNE7mPjr1qDp471YfW8nhBiTRWrG/4usZlpvFU8I7gsV7Jvrrzv/snbLm5dWO3dr1ennu2YqnhTWFmYA==", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "normalize-url": "^4.5.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=8" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "bin": { + "husky": "bin.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "license": "BSD-2-Clause", + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "license": "ISC" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "harmony-reflect": "^1.4.6" }, "engines": { - "node": ">=8.0.0" + "node": ">=4" } }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 4" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/ignore-walk": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", + "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "minimatch": "^10.0.3" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/eslint/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "esutils": "^2.0.2" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=6.0.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "optional": true, + "bin": { + "image-size": "bin/image-size.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { "node": ">=8" @@ -18457,1171 +23669,1188 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=0.8.19" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "ISC", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.4" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "optional": true, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">= 0.10" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "license": "BSD-2-Clause", + "node_modules/ionicons": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.10.tgz", + "integrity": "sha512-w+6VmjcRwlAtryXzM+BOlIHKyJYlrfbIIYWW4cU0BM8OECoTn/KF8ecOE5j4401z5/FcmHf/yXol1xinKuPM8g==", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "@stencil/core": "^4.30.0" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", + "node_modules/ioredis": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz", + "integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, "engines": { - "node": ">=4.0" + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0" + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "license": "BSD-2-Clause", + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.10" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eventemitter2": { - "version": "6.4.9", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", - "license": "MIT" - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, "license": "MIT" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">=0.8.x" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "pify": "^2.2.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "devOptional": true, - "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "devOptional": true, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "ci-info": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "is-ci": "bin.js" } }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, - "license": "Apache-2.0" - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "hasown": "^2.0.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, "engines": { - "node": ">= 0.8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/express/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=0.6" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/express/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/express/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "license": "MIT", "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/external-editor/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", "dependencies": { - "os-tmpdir": "~1.0.2" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" + "node": ">=14.16" }, - "bin": { - "extract-zip": "cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extract-zip/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extract-zip/node_modules/ms": { + "node_modules/is-interactive": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" + "node": ">=12" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "license": "MIT" - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, - "node_modules/fast-text-encoding": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", - "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", - "license": "Apache-2.0" - }, - "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "license": "BSD-3-Clause" - }, - "node_modules/fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" + "license": "MIT", + "engines": { + "node": ">=0.12.0" } }, - "node_modules/fd-package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", - "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "walk-up-path": "^3.0.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fd-slicer": { + "node_modules/is-observable": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dev": true, "license": "MIT", "dependencies": { - "pend": "~1.2.0" + "symbol-observable": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/finalhandler/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true, "license": "MIT" }, - "node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, "license": "MIT", - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, "engines": { - "node": ">=14.16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/find-cache-dir/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" + "call-bound": "^1.0.3" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/find-cache-dir/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^6.0.0" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/find-cache-dir/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^1.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-cache-dir/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^4.0.0" + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=v0.10.0" } }, - "node_modules/find-cache-dir/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" } }, - "node_modules/find-cache-dir/node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, "license": "MIT", - "dependencies": { - "find-up": "^6.3.0" - }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "dev": true, "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", "engines": { - "node": ">=12.20" + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/find-file-up": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-2.0.1.tgz", - "integrity": "sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "resolve-dir": "^1.0.1" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/find-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-2.0.0.tgz", - "integrity": "sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "find-file-up": "^2.0.1" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "devOptional": true, - "license": "MIT", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=10" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "debug": { + "node-notifier": { "optional": true } } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "devOptional": true, - "license": "ISC", "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "node_modules/jest-changed-files/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz", - "integrity": "sha512-fR3WRkOb4bQdWB/y7ssDUlVdrclvwtyCUIHCfivAoYxq9dF7XfrDKbMdZIfwJ7hxIAqkYSGeU7lLJE6xrxIBdg==", + "node_modules/jest-changed-files/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "vue-template-compiler": "*", - "webpack": "^5.11.0" - }, - "peerDependenciesMeta": { - "vue-template-compiler": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/jest-changed-files/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-changed-files/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/jest-changed-files/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "engines": { + "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=10.17.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jest-changed-files/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/picomatch": { + "node_modules/jest-changed-files/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", @@ -19634,2904 +24863,3348 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/jest-changed-files/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jest-circus": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.5.tgz", + "integrity": "sha512-h/sjXEs4GS+NFFfqBDYT7y5Msfxh04EwWLhQi0F8kuWpe+J/7tICSlswU8qvBqumR3kFgHbfu7vU6qruWWBPug==", "dev": true, "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-runtime": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "p-limit": "^3.1.0", + "pretty-format": "30.0.5", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">=8.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/jest-circus/node_modules/@jest/expect-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", + "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@jest/get-type": "30.0.1" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "devOptional": true, + "node_modules/jest-circus/node_modules/@jest/globals": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz", + "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==", + "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/types": "30.0.5", + "jest-mock": "30.0.5" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "node_modules/jest-circus/node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, "license": "MIT", - "engines": { - "node": "*" + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/front-matter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", - "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "js-yaml": "^3.13.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "node_modules/jest-circus/node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", "dev": true, "license": "MIT" }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/jest-circus/node_modules/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", "dev": true, "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^7.0.3" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", + "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", "dev": true, - "license": "Unlicense" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.5", + "pretty-format": "30.0.5" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "node_modules/jest-circus/node_modules/jest-runtime": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz", + "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/globals": "30.0.5", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/jest-circus/node_modules/jest-snapshot": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", + "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gaxios": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", - "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", - "license": "Apache-2.0", "dependencies": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", + "semver": "^7.7.2", + "synckit": "^0.11.8" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", - "license": "Apache-2.0", + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "dev": true, + "license": "MIT", "dependencies": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=10" - } - }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "devOptional": true, + "node_modules/jest-cli/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=8.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "node_modules/jest-cli/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/jest-cli/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "node_modules/jest-cli/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "node_modules/jest-cli/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "async": "^3.2.0" + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "node_modules/jest-cli/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "devOptional": true, - "license": "ISC", + "node_modules/jest-cli/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", + "node_modules/jest-cli/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause" + "node_modules/jest-cli/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-cli/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/jest-cli/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } }, - "node_modules/global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "node_modules/jest-cli/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "ini": "1.3.7" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-dirs/node_modules/ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "node_modules/jest-cli/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "license": "MIT", "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "node_modules/jest-cli/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/global-prefix/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/jest-cli/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/jest-cli/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/jest-cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-cli/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "node_modules/jest-cli/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "delegate": "^3.1.2" - } - }, - "node_modules/google-auth-library": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", - "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", - "license": "Apache-2.0", "dependencies": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/google-auth-library/node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "node_modules/jest-cli/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/google-auth-library/node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "node_modules/jest-cli/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, "license": "MIT", "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/google-auth-library/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", + "node_modules/jest-cli/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "node_modules/jest-cli/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "license": "MIT", "dependencies": { - "node-forge": "^1.3.1" - }, - "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/google-spreadsheet": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/google-spreadsheet/-/google-spreadsheet-3.2.0.tgz", - "integrity": "sha512-z7XMaqb+26rdo8p51r5O03u8aPLAPzn5YhOXYJPcf2hdMVr0dUbIARgdkRdmGiBeoV/QoU/7VNhq1MMCLZv3kQ==", - "license": "Unlicense", + "node_modules/jest-cli/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", "dependencies": { - "axios": "^0.21.4", - "google-auth-library": "^6.1.3", - "lodash": "^4.17.21" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=0.8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/google-spreadsheet/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/jest-cli/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/jest-cli/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "node_modules/jest-cli/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, "license": "MIT", "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "node_modules/jest-cli/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, - "license": "MIT" - }, - "node_modules/gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", "license": "MIT", "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", - "jws": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/gtoken/node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "node_modules/jest-cli/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/gtoken/node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "node_modules/jest-cli/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "node_modules/jest-cli/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "duplexer": "^0.1.2" - }, "engines": { - "node": ">=10" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "node_modules/jest-cli/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], "license": "MIT" }, - "node_modules/harmony-reflect": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "node_modules/jest-cli/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "(Apache-2.0 OR MPL-1.1)" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "node_modules/jest-cli/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/jest-cli/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^2.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "node_modules/jest-config": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.5.tgz", + "integrity": "sha512-aIVh+JNOOpzUgzUnPn5FLtyVnqc3TQHVMupYtyeURSb//iLColiMIR8TxCIDKyx9ZgjKnXGucuW68hCxgbrwmA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.0.1", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.0.5", + "@jest/types": "30.0.5", + "babel-jest": "30.0.5", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.0.5", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-runner": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "node_modules/jest-config/node_modules/@jest/expect-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", + "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" + }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/jest-config/node_modules/@jest/globals": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz", + "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/types": "30.0.5", + "jest-mock": "30.0.5" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "node_modules/jest-config/node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/jest-config/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-config/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "devOptional": true, + "node_modules/jest-config/node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-config/node_modules/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", + "dev": true, "license": "MIT", - "bin": { - "he": "bin/he" + "dependencies": { + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/helmet": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.0.0.tgz", - "integrity": "sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ==", + "node_modules/jest-config/node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" + }, "engines": { - "node": ">=16.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "node_modules/jest-config/node_modules/jest-leak-detector": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.5.tgz", + "integrity": "sha512-3Uxr5uP8jmHMcsOtYMRB/zf1gXN3yUIc+iPorhNETG54gErFIiUhLvyY/OggYpSMOEYqsmRxmuU4ZOoX5jpRFg==", "dev": true, "license": "MIT", "dependencies": { - "parse-passwd": "^1.0.0" + "@jest/get-type": "30.0.1", + "pretty-format": "30.0.5" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/hosted-git-info": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", - "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", + "node_modules/jest-config/node_modules/jest-matcher-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", + "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^10.0.1" + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.5", + "pretty-format": "30.0.5" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "node_modules/jest-config/node_modules/jest-runner": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.5.tgz", + "integrity": "sha512-JcCOucZmgp+YuGgLAXHNy7ualBx4wYSgJVWrYMRBnb79j9PD0Jxh0EHvR5Cx/r0Ce+ZBC4hCdz2AzFFLl9hCiw==", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "@jest/console": "30.0.5", + "@jest/environment": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-haste-map": "30.0.5", + "jest-leak-detector": "30.0.5", + "jest-message-util": "30.0.5", + "jest-resolve": "30.0.5", + "jest-runtime": "30.0.5", + "jest-util": "30.0.5", + "jest-watcher": "30.0.5", + "jest-worker": "30.0.5", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/jest-config/node_modules/jest-runtime": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz", + "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==", + "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/globals": "30.0.5", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/jest-config/node_modules/jest-snapshot": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", + "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "devOptional": true, + "node_modules/jest-config/node_modules/jest-validate": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", + "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", + "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^2.0.0" + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.5" }, "engines": { - "node": ">=12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "devOptional": true, + "node_modules/jest-config/node_modules/jest-watcher": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.5.tgz", + "integrity": "sha512-z9slj/0vOwBDBjN3L4z4ZYaA+pG56d6p3kTUhFRYGvXbXMWhXmb/FIxREZCD06DYUwDKKnj2T80+Pb71CQ0KEg==", + "dev": true, "license": "MIT", "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.0.5", + "string-length": "^4.0.2" }, "engines": { - "node": ">=12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "devOptional": true, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, "engines": { - "node": ">= 12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/html-minifier-terser/node_modules/terser": { - "version": "5.37.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", - "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", - "devOptional": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, + "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "devOptional": true, - "license": "MIT" + "node_modules/jest-config/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/html-webpack-plugin": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", - "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", - "devOptional": true, + "node_modules/jest-config/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, "license": "MIT", "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/htmlparser2": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", - "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/jest-docblock": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", + "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", + "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "entities": "^4.5.0" + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/http-assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "node_modules/jest-each": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.5.tgz", + "integrity": "sha512-dKjRsx1uZ96TVyejD3/aAWcNKy6ajMaN531CwWIsrazIqIoXI9TnnpPlkrEYku/8rkS3dh2rbH+kMOyiEIv0xQ==", "dev": true, "license": "MIT", "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "jest-util": "30.0.5", + "pretty-format": "30.0.5" }, "engines": { - "node": ">= 0.8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/http-assert/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/http-assert/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "node_modules/jest-each/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/http-assert/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "license": "BSD-2-Clause" - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "license": "MIT" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/jest-environment-jsdom/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "license": "MIT", "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=8.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "devOptional": true, + "node_modules/jest-environment-jsdom/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "devOptional": true, + "node_modules/jest-environment-jsdom/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "node_modules/jest-environment-jsdom/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "node_modules/jest-environment-jsdom/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, "license": "MIT" }, - "node_modules/http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "node_modules/jest-environment-jsdom/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "bin": { - "http-server": "bin/http-server" - }, - "engines": { - "node": ">=12" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "node_modules/jest-environment-jsdom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/http-status-codes": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", - "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "license": "MIT" - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "node_modules/jest-environment-jsdom/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, "engines": { - "node": ">=10.19.0" + "node": ">=8" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/jest-environment-jsdom/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/jest-environment-jsdom/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "node_modules/jest-environment-jsdom/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=8.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "node_modules/jest-environment-jsdom/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "bin": { - "husky": "bin.js" - }, "engines": { - "node": ">=18" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", - "license": "MIT", - "engines": { - "node": ">=10.18" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/jest-environment-node": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.5.tgz", + "integrity": "sha512-ppYizXdLMSvciGsRsMEnv/5EFpvOdXBaXRBzFUDPWrsfmog4kYrOGWXarLllz6AXan6ZAA/kYokgDWuos1IKDA==", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "license": "ISC", + "node_modules/jest-environment-node/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", - "license": "ISC" - }, - "node_modules/identity-obj-proxy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", - "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "node_modules/jest-environment-node/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "harmony-reflect": "^1.4.6" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "license": "MIT", - "engines": { - "node": ">= 4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ignore-walk": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-7.0.0.tgz", - "integrity": "sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ==", + "node_modules/jest-environment-node/node_modules/jest-validate": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", + "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minimatch": "^9.0.0" + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.5" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/jest-environment-node/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, "license": "MIT", - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/immutable": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", - "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/jest-haste-map": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.5.tgz", + "integrity": "sha512-dkmlWNlsTSR0nH3nRfW5BKbqHefLZv0/6LCccG0xFCTWcJu8TuEwG+5Cm75iBfjVoockmO6J35o5gxtFSn5xeg==", + "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@jest/types": "30.0.5", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "devOptional": true, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, + "node_modules/jest-message-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.5.tgz", + "integrity": "sha512-NAiDOhsK3V7RU0Aa/HnrQo+E4JlbarbmI3q6Pi4KcxicdtjV82gcIUrejOtczChtVQR4kddu1E1EJlW6EN9IyA==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.5", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, "engines": { - "node": ">=0.8.19" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "devOptional": true, - "license": "ISC", + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", - "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", + "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "node_modules/jest-mock": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", + "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-util": "30.0.5" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "optional": true, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "node_modules/jest-preset-angular": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.6.0.tgz", + "integrity": "sha512-LGSKLCsUhtrs2dw6f7ega/HOS8/Ni/1gV+oXmxPHmJDLHFpM6cI78Monmz8Z1P87a/A4OwnKilxgPRr+6Pzmgg==", "dev": true, "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "esbuild-wasm": ">=0.15.13", + "jest-environment-jsdom": "^29.7.0", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0", + "ts-jest": "^29.3.0" + }, "engines": { - "node": ">= 0.10" + "node": "^14.15.0 || >=16.10.0" + }, + "optionalDependencies": { + "esbuild": ">=0.15.13" + }, + "peerDependencies": { + "@angular/compiler-cli": ">=15.0.0 <21.0.0", + "@angular/core": ">=15.0.0 <21.0.0", + "@angular/platform-browser-dynamic": ">=15.0.0 <21.0.0", + "jest": "^29.0.0", + "jsdom": ">=20.0.0", + "typescript": ">=4.8" + }, + "peerDependenciesMeta": { + "jsdom": { + "optional": true + } } }, - "node_modules/ionicons": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz", - "integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==", + "node_modules/jest-preset-angular/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", "dependencies": { - "@stencil/core": "^4.0.3" + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ioredis": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz", - "integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==", + "node_modules/jest-preset-angular/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "node_modules/jest-preset-angular/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-preset-angular/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ip-address/node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "node_modules/jest-preset-angular/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "license": "MIT" - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "node_modules/jest-preset-angular/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "node_modules/jest-preset-angular/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "node_modules/jest-resolve": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.5.tgz", + "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.2" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "node_modules/jest-resolve/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "node_modules/jest-resolve/node_modules/jest-validate": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", + "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", "dev": true, "license": "MIT", "dependencies": { - "ci-info": "^2.0.0" + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.5" }, - "bin": { - "is-ci": "bin.js" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "node_modules/jest-resolve/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", "dev": true, - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "node_modules/jest-resolve/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/jest-runner/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", - "bin": { - "is-docker": "cli.js" + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-runner/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "node_modules/jest-runner/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-runner/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "devOptional": true, + "node_modules/jest-runner/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/jest-runner/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-runner/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "license": "MIT", + "node_modules/jest-runner/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runner/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/jest-runner/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", - "bin": { - "is-docker": "cli.js" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "node_modules/jest-runner/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "license": "MIT", + "node_modules/jest-runner/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runner/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, "engines": { "node": ">=8" } }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "node_modules/jest-runner/node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "detect-newline": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "node_modules/jest-runner/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=16" + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-runner/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/jest-runner/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "node_modules/jest-runner/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", "dependencies": { - "symbol-observable": "^1.1.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-observable/node_modules/symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "node_modules/jest-runner/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/jest-runner/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "node_modules/jest-runner/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/jest-runner/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/jest-runner/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", + "node_modules/jest-runner/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/jest-runtime/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "node_modules/jest-runtime/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "node_modules/jest-runtime/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "node_modules/jest-runtime/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/jest-runtime/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "license": "MIT" - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "node_modules/jest-runtime/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "node_modules/jest-runtime/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "is-inside-container": "^1.0.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/jest-runtime/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true, "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "devOptional": true, - "license": "ISC" - }, - "node_modules/iso-url": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", - "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", - "license": "MIT", - "engines": { - "node": ">=10" + "node_modules/jest-runtime/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "license": "MIT", + "node_modules/jest-runtime/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/isomorphic-rslog": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/isomorphic-rslog/-/isomorphic-rslog-0.0.6.tgz", - "integrity": "sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==", + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=14.17.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "node_modules/jest-runtime/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "peerDependencies": { - "ws": "*" + "engines": { + "node": ">=8" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "node_modules/jest-runtime/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "license": "BSD-3-Clause", + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "devOptional": true, + "node_modules/jest-runtime/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "devOptional": true, + "node_modules/jest-runtime/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/jest-runtime/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", - "license": "ISC", + "node_modules/jest-runtime/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "devOptional": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "node_modules/jest-runtime/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true, - "license": "MIT" - }, - "node_modules/jest": { + "node_modules/jest-runtime/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/jest-changed-files": { + "node_modules/jest-runtime/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "license": "MIT", "dependencies": { - "execa": "^5.0.0", + "@types/node": "*", "jest-util": "^29.7.0", - "p-limit": "^3.1.0" + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "devOptional": true, + "node_modules/jest-runtime/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-changed-files/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "devOptional": true, + "node_modules/jest-runtime/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-runtime/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jest-runtime/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "devOptional": true, - "license": "Apache-2.0", "engines": { - "node": ">=10.17.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/jest-circus": { + "node_modules/jest-snapshot": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@types/node": "*", + "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", - "p-limit": "^3.1.0", + "natural-compare": "^1.4.0", "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/jest-circus/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/jest-config": { + "node_modules/jest-snapshot/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", + "jest-haste-map": "^29.7.0", "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", + "pirates": "^4.0.4", "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "write-file-atomic": "^4.0.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/jest-snapshot/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "devOptional": true, - "license": "MIT", + "node_modules/jest-snapshot/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-environment-jsdom": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", - "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0", - "jsdom": "^20.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "canvas": "^2.5.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-environment-jsdom/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=8" } }, - "node_modules/jest-environment-jsdom/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, "license": "MIT" }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "node_modules/jest-snapshot/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "node": ">=8" } }, - "node_modules/jest-environment-node/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node_modules/jest-snapshot/node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/jest-haste-map": { + "node_modules/jest-snapshot/node_modules/jest-haste-map": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -22553,547 +28226,457 @@ "fsevents": "^2.3.2" } }, - "node_modules/jest-haste-map/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/jest-haste-map/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-leak-detector": { + "node_modules/jest-snapshot/node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util": { + "node_modules/jest-snapshot/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", + "@types/node": "*", "chalk": "^4.0.0", + "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock": { + "node_modules/jest-snapshot/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.7.0" + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-mock/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "devOptional": true, + "node_modules/jest-snapshot/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "node": ">=8.6" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-preset-angular": { - "version": "14.4.2", - "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.4.2.tgz", - "integrity": "sha512-BYYv0FaTDfBNh8WyA9mpOV3krfw20kurBGK8INZUnv7KZDAWZuQtCET4TwTWxSNQ9jS1OX1+a5weCm/bTDDM1A==", + "node_modules/jest-snapshot/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/jest-snapshot/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", "dependencies": { - "bs-logger": "^0.2.6", - "esbuild-wasm": ">=0.15.13", - "jest-environment-jsdom": "^29.0.0", - "jest-util": "^29.0.0", - "pretty-format": "^29.0.0", - "ts-jest": "^29.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": "^14.15.0 || >=16.10.0" - }, - "optionalDependencies": { - "esbuild": ">=0.15.13" - }, - "peerDependencies": { - "@angular/compiler-cli": ">=15.0.0 <20.0.0", - "@angular/core": ">=15.0.0 <20.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 <20.0.0", - "jest": "^29.0.0", - "typescript": ">=4.8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/jest-preset-angular/node_modules/esbuild-wasm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.2.tgz", - "integrity": "sha512-03/7Z1gD+ohDnScFztvI4XddTAbKVmMEzCvvkBpQdWKEXJ+73dTyeNrmdxP1Q0zpDMFjzUJwtK4rLjqwiHbzkw==", + "node_modules/jest-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", + "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", "dev": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-preset-angular/node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "bs-logger": "^0.2.6", - "ejs": "^3.1.10", - "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.6.3", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" + "node": ">=10" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "devOptional": true, + "node_modules/jest-util/node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-resolve": { + "node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, "license": "MIT", "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "devOptional": true, + "node_modules/jest-validate/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "devOptional": true, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/jest-validate/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "devOptional": true, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-runner/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-runtime": { + "node_modules/jest-watcher": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", + "emittery": "^0.13.1", "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "string-length": "^4.0.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/jest-watcher/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "devOptional": true, + "node_modules/jest-watcher/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/jest-snapshot": { + "node_modules/jest-watcher/node_modules/@jest/test-result": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", + "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "devOptional": true, + "node_modules/jest-watcher/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } + "node_modules/jest-watcher/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "devOptional": true, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-util/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" + "node_modules/jest-watcher/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/jest-validate": { + "node_modules/jest-watcher/node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", "dependencies": { + "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", + "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher": { + "node_modules/jest-watcher/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, + "node_modules/jest-watcher/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-watcher/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "devOptional": true, + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.5.tgz", + "integrity": "sha512-ojRXsWzEP16NdUuBw/4H/zkZdHOa7MMYCk4E430l+8fELeLg/mqmMlRhjL7UNZvQrDmnovWZV4DxX03fZF48fQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "jest-util": "^29.7.0", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.5", "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "supports-color": "^8.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -23105,17 +28688,66 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-worker/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, + "node_modules/jest/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, "license": "MIT" }, + "node_modules/jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jiti": { "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "devOptional": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -23141,58 +28773,30 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "devOptional": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js-yaml/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/js-yaml/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "devOptional": true, - "license": "BSD-3-Clause" - }, "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "dev": true, "license": "MIT" }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", - "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "abab": "^2.0.6", @@ -23234,26 +28838,80 @@ } } }, - "node_modules/jsdom/node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" + "debug": "4" }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/jsdom/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=6.0" + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" } }, "node_modules/jsesc": { @@ -23281,19 +28939,23 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "license": "MIT" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { @@ -23325,44 +28987,90 @@ "delimit-stream": "0.1.0" } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/jsondiffpatch": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.6.0.tgz", + "integrity": "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==", "license": "MIT", + "dependencies": { + "@types/diff-match-patch": "^1.0.36", + "chalk": "^5.3.0", + "diff-match-patch": "^1.0.5" + }, "bin": { - "json5": "lib/cli.js" + "jsondiffpatch": "bin/jsondiffpatch.js" }, "engines": { - "node": ">=6" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/jsonc-eslint-parser": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", - "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", - "dev": true, + "node_modules/jsondiffpatch/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "license": "MIT", - "dependencies": { - "acorn": "^8.5.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", - "semver": "^7.3.5" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ota-meshi" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true, - "license": "MIT" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -23410,21 +29118,48 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "license": "MIT", "dependencies": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">=12", "npm": ">=6" } }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jsonwebtoken/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -23448,23 +29183,23 @@ } }, "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "1.0.1", + "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, @@ -23472,15 +29207,16 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, "license": "MIT", "dependencies": { "source-map-support": "^0.5.5" } }, "node_modules/katex": { - "version": "0.16.18", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz", - "integrity": "sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ==", + "version": "0.16.22", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", + "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -23518,12 +29254,13 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.4.0.tgz", + "integrity": "sha512-TMckyVjEoacG5IteUpUrOBsFORtheqziVyyY2dLUwg1jwTb8u48LX4TgmtogkNl9Y9unaEJ1luj10fGyjMGFOQ==", "license": "MIT", + "peer": true, "dependencies": { - "json-buffer": "3.0.1" + "@keyv/serialize": "^1.1.0" } }, "node_modules/khroma": { @@ -23532,10 +29269,25 @@ "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", "optional": true }, + "node_modules/kill-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/kill-port/-/kill-port-1.6.1.tgz", + "integrity": "sha512-un0Y55cOM7JKGaLnGja28T38tDDop0AQ8N0KlAdyh+B1nmMoX8AnNmqPNZbS3mUMgiST51DCVqmbFT1gNJpVNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-them-args": "1.3.2", + "shell-exec": "1.0.2" + }, + "bin": { + "kill-port": "cli.js" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -23545,7 +29297,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -23562,9 +29314,9 @@ } }, "node_modules/koa": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.15.3.tgz", - "integrity": "sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.16.1.tgz", + "integrity": "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==", "dev": true, "license": "MIT", "dependencies": { @@ -23617,6 +29369,53 @@ "node": ">= 10" } }, + "node_modules/koa/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/koa/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/koa/node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -23644,6 +29443,26 @@ "node": ">= 0.6" } }, + "node_modules/koa/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/koa/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -23654,14 +29473,53 @@ "node": ">= 0.6" } }, + "node_modules/koa/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "license": "MIT", + "optional": true + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.0.tgz", + "integrity": "sha512-R/PIF14L6e2eHkhvQPu7jDRCr0msfCYCxbYiLgkkAGi0dVPWuM+RrsPu0a5dpuNe0KWGL3jpAkOlv53xGfPheQ==", + "dev": true, "license": "MIT", "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" } }, "node_modules/layout-base": { @@ -23671,53 +29529,123 @@ "license": "MIT", "optional": true }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "> 0.8" + } + }, + "node_modules/less": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.3.0.tgz", + "integrity": "sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.3.0.tgz", + "integrity": "sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": "> 0.8" + "node": ">=6" } }, - "node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "license": "Apache-2.0", - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "optional": true, "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" + "semver": "bin/semver" } }, - "node_modules/less/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -23737,39 +29665,17 @@ "node": ">= 0.8.0" } }, - "node_modules/levn/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/levn/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/libphonenumber-js": { - "version": "1.11.17", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.17.tgz", - "integrity": "sha512-Jr6v8thd5qRlOlc6CslSTzGzzQW03uiscab7KHQZX1Dfo4R6n6FDhZ0Hri6/X7edLIDv9gl4VMZXhxTjLnl0VQ==", + "version": "1.12.10", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.10.tgz", + "integrity": "sha512-E91vHJD61jekHHR/RF/E83T/CMoaLXT7cwYA75T4gim4FZjnM6hbJjVIGg7chqlSqRsSvQ3izGmOjHy1SQzcGQ==", "license": "MIT" }, "node_modules/license-webpack-plugin": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, "license": "ISC", "dependencies": { "webpack-sources": "^3.0.0" @@ -23860,16 +29766,6 @@ "listr": "^0.14.2" } }, - "node_modules/listr-update-renderer/node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/listr-update-renderer/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -23907,44 +29803,14 @@ "node": ">=0.10.0" } }, - "node_modules/listr-update-renderer/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "node_modules/listr-update-renderer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, "node_modules/listr-update-renderer/node_modules/log-symbols": { @@ -23960,83 +29826,6 @@ "node": ">=0.10.0" } }, - "node_modules/listr-update-renderer/node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/listr-update-renderer/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -24060,67 +29849,6 @@ "node": ">=0.8.0" } }, - "node_modules/listr-update-renderer/node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/listr-verbose-renderer": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", @@ -24202,6 +29930,16 @@ "dev": true, "license": "MIT" }, + "node_modules/listr-verbose-renderer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/listr-verbose-renderer/node_modules/figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -24262,6 +30000,13 @@ "node": ">=4" } }, + "node_modules/listr-verbose-renderer/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/listr-verbose-renderer/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -24306,9 +30051,9 @@ "license": "0BSD" }, "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", @@ -24322,208 +30067,101 @@ "node": ">=18.0.0" } }, - "node_modules/lmdb": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.1.5.tgz", - "integrity": "sha512-46Mch5Drq+A93Ss3gtbg+Xuvf5BOgIuvhKDWoGa3HcPHI6BL2NCOkRdSx1D4VfzwrxhnsjbyIVsLRlQHu6URvw==", - "hasInstallScript": true, + "node_modules/listr2/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "license": "MIT", - "optional": true, "dependencies": { - "msgpackr": "^1.11.2", - "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.5.3", - "weak-lru-cache": "^1.2.2" + "environment": "^1.0.0" }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" + "engines": { + "node": ">=18" }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.1.5", - "@lmdb/lmdb-darwin-x64": "3.1.5", - "@lmdb/lmdb-linux-arm": "3.1.5", - "@lmdb/lmdb-linux-arm64": "3.1.5", - "@lmdb/lmdb-linux-x64": "3.1.5", - "@lmdb/lmdb-win32-x64": "3.1.5" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lmdb/node_modules/node-addon-api": { + "node_modules/listr2/node_modules/ansi-regex": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "license": "MIT", - "optional": true - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "node": ">=12" }, - "engines": { - "node": ">=8.9.0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/loader-utils/node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "license": "MIT", "engines": { - "node": "*" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/locate-path": { + "node_modules/listr2/node_modules/cli-cursor": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "node_modules/listr2/node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "license": "MIT", - "optional": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "license": "MIT" - }, - "node_modules/lodash.clonedeepwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz", - "integrity": "sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "license": "MIT" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "license": "MIT" }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update": { + "node_modules/listr2/node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", @@ -24542,52 +30180,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { + "node_modules/listr2/node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "get-east-asian-width": "^1.0.0" }, "engines": { "node": ">=18" @@ -24596,22 +30195,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "node_modules/listr2/node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.0.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/onetime": { + "node_modules/listr2/node_modules/onetime": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", @@ -24626,7 +30226,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/restore-cursor": { + "node_modules/listr2/node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", @@ -24642,35 +30242,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", + "node_modules/listr2/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, "engines": { - "node": ">=14" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/strip-ansi": { + "node_modules/listr2/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", @@ -24685,846 +30290,690 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", - "dev": true, - "license": "Apache-2.0", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/long-timeout": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, + "node_modules/lmdb": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.1.tgz", + "integrity": "sha512-hoG9RIv42kdGJiieyElgWcKCTaw5S6Jqwyd1gLSVdsJ3+8MVm8e4yLronThiRJI9DazFAAs9xfB9nWeMQ2DWKA==", + "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "msgpackr": "^1.11.2", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", + "weak-lru-cache": "^1.2.2" }, "bin": { - "loose-envify": "cli.js" + "download-lmdb-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "3.4.1", + "@lmdb/lmdb-darwin-x64": "3.4.1", + "@lmdb/lmdb-linux-arm": "3.4.1", + "@lmdb/lmdb-linux-arm64": "3.4.1", + "@lmdb/lmdb-linux-x64": "3.4.1", + "@lmdb/lmdb-win32-arm64": "3.4.1", + "@lmdb/lmdb-win32-x64": "3.4.1" } }, - "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "devOptional": true, + "node_modules/load-esm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.2.tgz", + "integrity": "sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" + "engines": { + "node": ">=13.2.0" } }, - "node_modules/lower-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 12.13.0" } }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "node_modules/local-pkg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", + "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.0.1", + "quansync": "^0.2.8" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } }, - "node_modules/luxon": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", - "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT", + "optional": true + }, + "node_modules/lodash.clonedeepwith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz", + "integrity": "sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true, - "license": "MIT", - "bin": { - "lz-string": "bin/bin.js" - } + "license": "MIT" }, - "node_modules/magic-string": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", - "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "license": "ISC" - }, - "node_modules/make-fetch-happen": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", - "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "node_modules/log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=4" } }, - "node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "devOptional": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" + "node": ">=4" } }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, - "license": "MIT" - }, - "node_modules/marked": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.4.tgz", - "integrity": "sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "node_modules/log-update/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" + "restore-cursor": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=4" } }, - "node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=4" } }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "node_modules/log-update/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, - "license": "CC0-1.0" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/memfs": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.6.0.tgz", - "integrity": "sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ==", + "node_modules/log-update/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, - "license": "Unlicense", + "license": "MIT", "dependencies": { - "fs-monkey": "^1.0.4" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=4" } }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "node_modules/log-update/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dev": true, "license": "MIT", "dependencies": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, "engines": { - "node": ">= 8" - } - }, - "node_modules/mermaid": { - "version": "10.9.3", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.3.tgz", - "integrity": "sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw==", - "license": "MIT", - "optional": true, - "dependencies": { - "@braintree/sanitize-url": "^6.0.1", - "@types/d3-scale": "^4.0.3", - "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.28.1", - "cytoscape-cose-bilkent": "^4.1.0", - "d3": "^7.4.0", - "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.10", - "dayjs": "^1.11.7", - "dompurify": "^3.0.5 <3.1.7", - "elkjs": "^0.9.0", - "katex": "^0.16.9", - "khroma": "^2.0.0", - "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^1.3.0", - "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.3", - "ts-dedent": "^2.2.0", - "uuid": "^9.0.0", - "web-worker": "^1.2.0" - } - }, - "node_modules/mermaid/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=4" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/log-update/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/log-update/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/log-update/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "optional": true, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" } }, - "node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/long-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", - "optional": true, "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/loupe": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", + "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "tslib": "^2.0.3" } }, - "node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "optional": true, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "yallist": "^3.0.2" } }, - "node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/lru-cache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/luxon": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz", + "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==", "license": "MIT", - "optional": true, - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "micromark-util-symbol": "^1.0.0" + "peer": true, + "bin": { + "lz-string": "bin/bin.js" } }, - "node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "license": "MIT", - "optional": true, "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "optional": true, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", "dependencies": { - "micromark-util-symbol": "^1.0.0" + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marked": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.4.tgz", + "integrity": "sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw==", "license": "MIT", - "optional": true, - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" } }, - "node_modules/micromark-util-encode": { + "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", - "optional": true + "engines": { + "node": ">= 0.4" + } }, - "node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "optional": true + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" }, - "node_modules/micromark-util-normalize-identifier": { + "node_modules/media-typer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", - "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "license": "Unlicense", "dependencies": { - "micromark-util-symbol": "^1.0.0" + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", - "optional": true, - "dependencies": { - "micromark-util-types": "^1.0.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "engines": { + "node": ">= 8" } }, - "node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/mermaid": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.9.0.tgz", + "integrity": "sha512-YdPXn9slEwO0omQfQIsW6vS84weVQftIyyTGAZCwM//MGhPzL1+l6vO6bkf0wnP4tHigH1alZ5Ooy3HXI2gOag==", "license": "MIT", "optional": true, "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "@braintree/sanitize-url": "^7.0.4", + "@iconify/utils": "^2.1.33", + "@mermaid-js/parser": "^0.6.2", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.13", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.0.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" } }, - "node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/mermaid/node_modules/marked": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.1.tgz", + "integrity": "sha512-ij/2lXfCRT71L6u0M29tJPhP0bM5shLL3u5BePhFwPELj2blMJ6GDtD7PfJhRLhJ/c2UwrK17ySVcDzy2YHjHQ==", "license": "MIT", - "optional": true + "optional": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } }, - "node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">= 0.6" + } }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "devOptional": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -25538,6 +30987,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -25550,6 +31000,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -25583,6 +31034,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -25600,18 +31052,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -25623,13 +31063,14 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", - "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", "dev": true, "license": "MIT", "dependencies": { - "schema-utils": "^4.0.0" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { "node": ">= 12.13.0" @@ -25646,13 +31087,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, "license": "ISC" }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -25661,17 +31103,6 @@ "node": "*" } }, - "node_modules/minimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -25685,7 +31116,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -25705,9 +31136,9 @@ } }, "node_modules/minipass-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", - "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -25801,14 +31232,13 @@ } }, "node_modules/minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" + "minipass": "^7.1.2" }, "engines": { "node": ">= 18" @@ -25826,6 +31256,38 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "license": "MIT", + "optional": true, + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT", + "optional": true + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -25836,20 +31298,10 @@ "node": "*" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "license": "MIT", "engines": { "node": ">=10" @@ -25865,9 +31317,9 @@ } }, "node_modules/msgpackr": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", - "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.5.tgz", + "integrity": "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==", "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.2" @@ -25896,27 +31348,65 @@ } }, "node_modules/multer": { - "version": "1.4.4-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", - "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz", + "integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" + "type-is": "^1.6.18", + "xtend": "^4.0.2" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, "license": "MIT", "dependencies": { "dns-packet": "^5.2.2", @@ -25927,19 +31417,18 @@ } }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -25948,23 +31437,40 @@ ], "license": "MIT", "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", + "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" } }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/needle": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -25979,9 +31485,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -25991,50 +31497,96 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, "license": "MIT" }, "node_modules/ng-extract-i18n-merge": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/ng-extract-i18n-merge/-/ng-extract-i18n-merge-2.13.1.tgz", - "integrity": "sha512-aU+shz0VSe0qqKYmlpg42P2C6Ol6eQ+DZDTYzQM4PTMfEBWJNFtl+c7B+MA68/AzdpcNPKu0BWJLZchCdZtjhQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ng-extract-i18n-merge/-/ng-extract-i18n-merge-3.0.0.tgz", + "integrity": "sha512-vTWtAz6a/wVYxnUMFHp1ur6o4JSLm+LcxdSMV8o8Ml2p5oCsSB4iFd5E6h8Yb8X8D596qyBz0ELgiDmbn4YyRQ==", "license": "MIT", "dependencies": { - "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0 || ^0.1800.0 || ^0.1900.0", - "@angular-devkit/core": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "@angular-devkit/schematics": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "@schematics/angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "@angular-devkit/architect": "^0.2000.0", + "@angular-devkit/core": "^20.0.0", + "@angular-devkit/schematics": "^20.0.0", + "@schematics/angular": "^20.0.0", "xmldoc": "^1.1.3" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" }, "peerDependencies": { - "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "@angular/build": "^20.0.0" } }, - "node_modules/ngx-device-detector": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ngx-device-detector/-/ngx-device-detector-9.0.0.tgz", - "integrity": "sha512-zpio/wqH1GnxIpWCdA7cp5fmWf7YLycgzfXzQHmB9vaS7eAcqpBF5mxDS65IhE7TzNTJziDrYJCT+9tVqBcsDg==", + "node_modules/ng-extract-i18n-merge/node_modules/@angular-devkit/architect": { + "version": "0.2000.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2000.6.tgz", + "integrity": "sha512-LvXYe7hqEgkBKzDy4VKTgCg2E2nAl8vC986n1+snzt2zMjo2l8wFl6BWal3AtaKGhPlp8/57Y53MdG2TIgUJNA==", "license": "MIT", "dependencies": { - "tslib": "^2.0.0" + "@angular-devkit/core": "20.0.6", + "rxjs": "7.8.2" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/ng-extract-i18n-merge/node_modules/@angular-devkit/core": { + "version": "20.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.0.6.tgz", + "integrity": "sha512-kalYqR/soAMPgYdaKJL3iOMCubiq0gljpbQFzS+Uey/P1nn+MDY8V0zzc9cBNhKKkAxCXPN/NIEKC7ICOfaJbg==", + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.2", + "source-map": "0.7.4" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0" + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/ngx-device-detector/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/ng-extract-i18n-merge/node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/ngx-device-detector": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/ngx-device-detector/-/ngx-device-detector-10.0.2.tgz", + "integrity": "sha512-KLbd2hJtpUT7lRek+9pRUINvxa6yG4YDZ6RKzYmMbIbNpYEPJwXVmszG2fMPq+DarXABdqOYwp7wUQ2DQFgihw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.3" + }, + "peerDependencies": { + "@angular/common": "^20.0.0", + "@angular/core": "^20.0.0" + } }, "node_modules/ngx-markdown": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-19.0.0.tgz", - "integrity": "sha512-/UDTYxK2sbG9LjeuPfqErCg9gbT1O64Rnqvs9qgvK70X//gEVCMStNUi1zYIqw/SLRk19Rk48DZMgPiFRbgb1Q==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-20.0.0.tgz", + "integrity": "sha512-AtB0EhYlfZbNBFzzhOkqxw5tIX+Z1rLqkRP207ee8c3QHQTn/uRmVVTMwE7LenF2ZOW11Brq/O8h6VfLy9FG+w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -26044,80 +31596,55 @@ "emoji-toolkit": ">= 8.0.0 < 10.0.0", "katex": "^0.16.0", "mermaid": ">= 10.6.0 < 12.0.0", - "prismjs": "^1.28.0" + "prismjs": "^1.30.0" }, "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/platform-browser": "^19.0.0", + "@angular/common": "^20.0.0", + "@angular/core": "^20.0.0", + "@angular/platform-browser": "^20.0.0", "marked": "^15.0.0", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" } }, - "node_modules/ngx-markdown/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/ngx-skeleton-loader": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ngx-skeleton-loader/-/ngx-skeleton-loader-9.0.0.tgz", - "integrity": "sha512-aO4/V6oGdZGNcTjasTg/fwzJJYl/ZmNKgCukOEQdUK3GSFOZtB/3GGULMJuZ939hk3Hzqh1OBiLfIM1SqTfhqg==", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/ngx-skeleton-loader/-/ngx-skeleton-loader-11.2.1.tgz", + "integrity": "sha512-0YWwQgK3X4trtiLvTv3/CMGxcvjPkUbtTTKJJ2EOHhFuvPf0b+XO1KwguK0Ub9BMHnsqK8xOol0cEoVXyNh64Q==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0" + "@angular/common": ">=19.0.0", + "@angular/core": ">=19.0.0" } }, - "node_modules/ngx-skeleton-loader/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/ngx-stripe": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/ngx-stripe/-/ngx-stripe-19.0.0.tgz", - "integrity": "sha512-Q95EnHcEjZrHg4f4XMwMhRlJNg/jenBfypk9JISC3T4R2hc+J6HS2NMHBuft9hfRepKrcQY+FiSLzH2yS+5cAg==", + "version": "20.7.0", + "resolved": "https://registry.npmjs.org/ngx-stripe/-/ngx-stripe-20.7.0.tgz", + "integrity": "sha512-gwrjOSfGKXgdjlqyxt61Tz6kKnlJhs38iMqAuyZH+UJ2TeClBA4+iywIheTU3GOg8DLnaANKunr7BDO/gjQkPQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": ">=19.0.0 <20.0.0", - "@angular/core": ">=19.0.0 <20.0.0", - "@stripe/stripe-js": ">=5.0.0 <6.0.0" + "@angular/common": ">=20.0.0 <21.0.0", + "@angular/core": ">=20.0.0 <21.0.0", + "@stripe/stripe-js": ">=7.0.0 <8.0.0" } }, - "node_modules/ngx-stripe/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, - "node_modules/no-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" - }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", @@ -26126,9 +31653,9 @@ "license": "MIT" }, "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "license": "MIT", "optional": true }, @@ -26184,21 +31711,21 @@ } }, "node_modules/node-gyp": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.0.0.tgz", - "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.3.0.tgz", + "integrity": "sha512-9J0+C+2nt3WFuui/mC46z2XCZ21/cKlFDuywULmseD/LlmnOrSeEAE4c/1jw6aybXLmpZnQY3/LmOJfgyHIcng==", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", + "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bin": { @@ -26223,58 +31750,91 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/node-gyp-build-optional-packages/node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "optional": true, + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", "bin": { - "glob": "dist/esm/bin.mjs" + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/node-gyp/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/node-machine-id": { @@ -26305,21 +31865,14 @@ "node": ">=6" } }, - "node_modules/non-layered-tidy-tree-layout": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", - "license": "MIT", - "optional": true - }, "node_modules/nopt": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.0.0.tgz", - "integrity": "sha512-1L/fTJ4UmV/lUxT2Uf006pfZKTvAgCF+chz+0OgBHO8u2Z67pE7AaAUUj7CJy0lXqHmymUvGFt6NE9R3HER0yw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^2.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" @@ -26328,25 +31881,11 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/normalize-package-data": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-7.0.0.tgz", - "integrity": "sha512-k6U0gKRIuNCTkwHGZqblCfLfBRh+w1vI6tBo+IeJwq2M8FUiOqhX7GH+GArQGScA7azd1WfyRCvxoXDO3hQDIA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^8.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -26356,21 +31895,19 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/npm-bundled": { @@ -26410,9 +31947,9 @@ } }, "node_modules/npm-package-arg": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.1.tgz", - "integrity": "sha512-aDxjFfPV3Liw0WOBWlyZLMBqtbgbg03rmGvHDJa2Ttv7tIz+1oB5qWec4psCDFZcZi9b5XdGkPdQiJxOPzvQRQ==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", "dev": true, "license": "ISC", "dependencies": { @@ -26426,16 +31963,16 @@ } }, "node_modules/npm-packlist": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-9.0.0.tgz", - "integrity": "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.1.tgz", + "integrity": "sha512-vaC03b2PqJA6QqmwHi1jNU8fAPXEnnyv4j/W4PVfgm24C4/zZGSVut3z0YUeN0WIFCo1oGOL02+6LbvFK7JL4Q==", "dev": true, "license": "ISC", "dependencies": { - "ignore-walk": "^7.0.0" + "ignore-walk": "^8.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm-pick-manifest": { @@ -26478,7 +32015,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.0.0" @@ -26510,16 +32047,16 @@ } }, "node_modules/nwsapi": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", - "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", - "devOptional": true, + "version": "2.2.21", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz", + "integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==", + "dev": true, "license": "MIT" }, "node_modules/nx": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.3.0.tgz", - "integrity": "sha512-Nzi4k7tV22zwO2iBLk+pHxorLEWPJpPrVCACtz0SQ63j/LiAgfhoqruJO+VU+V+E9qdyPsvmqIL/Iaf/GRQlqA==", + "version": "21.3.9", + "resolved": "https://registry.npmjs.org/nx/-/nx-21.3.9.tgz", + "integrity": "sha512-humOjQvzsWe7z8vx2JwpmxZfwDxHmoD5DyveqnUm8t7yIFJEf8/LzjNDVLSth0rSdCJe+VsoL26s4mRdx/oU1w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -26528,7 +32065,7 @@ "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", + "axios": "^1.8.3", "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", @@ -26540,7 +32077,7 @@ "flat": "^5.0.2", "front-matter": "^4.0.2", "ignore": "^5.0.4", - "jest-diff": "^29.4.1", + "jest-diff": "^30.0.2", "jsonc-parser": "3.2.0", "lines-and-columns": "2.0.3", "minimatch": "9.0.3", @@ -26553,6 +32090,7 @@ "string-width": "^4.2.3", "tar-stream": "~2.2.0", "tmp": "~0.2.1", + "tree-kill": "^1.2.2", "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0", "yaml": "^2.6.0", @@ -26564,16 +32102,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.3.0", - "@nx/nx-darwin-x64": "20.3.0", - "@nx/nx-freebsd-x64": "20.3.0", - "@nx/nx-linux-arm-gnueabihf": "20.3.0", - "@nx/nx-linux-arm64-gnu": "20.3.0", - "@nx/nx-linux-arm64-musl": "20.3.0", - "@nx/nx-linux-x64-gnu": "20.3.0", - "@nx/nx-linux-x64-musl": "20.3.0", - "@nx/nx-win32-arm64-msvc": "20.3.0", - "@nx/nx-win32-x64-msvc": "20.3.0" + "@nx/nx-darwin-arm64": "21.3.9", + "@nx/nx-darwin-x64": "21.3.9", + "@nx/nx-freebsd-x64": "21.3.9", + "@nx/nx-linux-arm-gnueabihf": "21.3.9", + "@nx/nx-linux-arm64-gnu": "21.3.9", + "@nx/nx-linux-arm64-musl": "21.3.9", + "@nx/nx-linux-x64-gnu": "21.3.9", + "@nx/nx-linux-x64-musl": "21.3.9", + "@nx/nx-win32-arm64-msvc": "21.3.9", + "@nx/nx-win32-x64-msvc": "21.3.9" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -26588,17 +32126,66 @@ } } }, - "node_modules/nx/node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "node_modules/nx/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/nx/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/nx/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/nx/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/nx/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, "node_modules/nx/node_modules/define-lazy-prop": { @@ -26627,6 +32214,16 @@ "url": "https://dotenvx.com" } }, + "node_modules/nx/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/nx/node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -26643,6 +32240,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nx/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/nx/node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -26656,6 +32279,29 @@ "node": ">=8" } }, + "node_modules/nx/node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/nx/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, "node_modules/nx/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -26713,43 +32359,103 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/ora/node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/nx/node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, "engines": { - "node": ">=6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/nx/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/nx/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/nx/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, - "license": "0BSD" + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/nx/node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "node_modules/nx/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" + "license": "ISC" + }, + "node_modules/nx/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nx/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">= 14" + "node": ">=6" + } + }, + "node_modules/nx/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, "node_modules/oauth": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", - "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.2.tgz", + "integrity": "sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==", "license": "MIT" }, "node_modules/object-assign": { @@ -26762,9 +32468,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -26861,6 +32567,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, "license": "MIT" }, "node_modules/on-finished": { @@ -26876,9 +32583,10 @@ } }, "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": { "node": ">= 0.8" @@ -26897,6 +32605,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -26915,9 +32624,10 @@ "dev": true }, "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", + "dev": true, "license": "MIT", "dependencies": { "default-browser": "^5.2.1", @@ -26932,90 +32642,227 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open-color": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/open-color/-/open-color-1.9.1.tgz", - "integrity": "sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw==", - "license": "MIT" - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" + "node_modules/open-color": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/open-color/-/open-color-1.9.1.tgz", + "integrity": "sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw==", + "license": "MIT" + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, + "node_modules/ora/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "license": "MIT", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, + "node_modules/ora/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/ordered-binary": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", - "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.0.tgz", + "integrity": "sha512-IQh2aMfMIDbPjI/8a3Edr+PiOpcsB7yo8NdW7aHWVaoR/pcDldunMvnnwbk/auPGqmKeAdxtZl7MHX/QmPwhvQ==", "license": "MIT", "optional": true }, @@ -27036,20 +32883,29 @@ "dev": true, "license": "MIT" }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -27062,29 +32918,45 @@ } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "devOptional": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "devOptional": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -27104,6 +32976,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/retry": "0.12.2", @@ -27121,7 +32994,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -27131,13 +33004,20 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "devOptional": true, + "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT", + "optional": true + }, "node_modules/pacote": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", - "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.0.tgz", + "integrity": "sha512-lcqexq73AMv6QNLo7SOpz0JJoaGdS3rBFgF122NZVl1bApo2mfu+XzUBU/X/XsiJu+iUmKpekRayqQYAs+PhkA==", "dev": true, "license": "ISC", "dependencies": { @@ -27150,7 +33030,7 @@ "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", + "npm-packlist": "^10.0.0", "npm-pick-manifest": "^10.0.0", "npm-registry-fetch": "^18.0.0", "proc-log": "^5.0.0", @@ -27163,111 +33043,7 @@ "pacote": "bin/index.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/pacote/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/pacote/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/pacote/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pacote/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pacote/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pacote/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/pacote/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pacote/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/papaparse": { @@ -27280,24 +33056,18 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, - "node_modules/param-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -27310,6 +33080,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -27324,16 +33095,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/parse-json/node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, "license": "MIT" }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -27350,24 +33130,24 @@ } }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "license": "MIT", "dependencies": { - "entities": "^4.5.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.1.0.tgz", + "integrity": "sha512-2ifK6Jb+ONoqOy5f+cYHsqvx1obHQdvIk13Jmt/5ezxP0U9p+fqd+R6O73KblGswyuzBYfetmsfK9ThMgnuPPg==", "license": "MIT", "dependencies": { - "entities": "^4.3.0", + "entities": "^6.0.0", "parse5": "^7.0.0", "parse5-sax-parser": "^7.0.0" }, @@ -27375,6 +33155,30 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-html-rewriting-stream/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", @@ -27388,6 +33192,30 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parse5-parser-stream": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", @@ -27400,6 +33228,30 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-parser-stream/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-parser-stream/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parse5-sax-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", @@ -27412,6 +33264,42 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-sax-parser/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -27425,20 +33313,13 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, - "node_modules/pascal-case/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" - }, "node_modules/passport": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", @@ -27489,34 +33370,6 @@ "passport-strategy": "^1.0.0" } }, - "node_modules/passport-jwt/node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/passport-jwt/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/passport-oauth2": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", @@ -27545,28 +33398,28 @@ "node": ">= 0.4.0" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, - "license": "MIT" + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT", + "optional": true }, "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "devOptional": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -27576,7 +33429,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -27586,13 +33439,14 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "devOptional": true, + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -27605,11 +33459,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/path-type": { "version": "4.0.0", @@ -27621,10 +33485,17 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT", + "optional": true + }, "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -27679,29 +33550,42 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "devOptional": true, + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/piscina": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.7.0.tgz", - "integrity": "sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.2.tgz", + "integrity": "sha512-9cE/BTA/xhDiyNUEj6EKWLEQC17fh/24ydYzQwcA7QdYh75K6kzL2GHvxDF5i9rFGtUaaKk7/u4xp07qiKXccQ==", "license": "MIT", + "engines": { + "node": ">=20.x" + }, "optionalDependencies": { "@napi-rs/nice": "^1.0.1" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.0.0" @@ -27710,6 +33594,84 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", + "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -27720,17 +33682,22 @@ "node": ">=4" } }, - "node_modules/polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "dev": true, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT", + "optional": true + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", "license": "MIT", + "optional": true, "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" } }, "node_modules/popper.js": { @@ -27746,51 +33713,23 @@ } }, "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz", + "integrity": "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw==", "dev": true, "license": "MIT", "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" + "async": "^3.2.6", + "debug": "^4.3.6" }, "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" + "node": ">= 10.12" } }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/portfinder/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { @@ -27798,9 +33737,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -27817,7 +33756,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -27949,26 +33888,62 @@ } }, "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "dev": true, "license": "MIT", "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "postcss": "^7.0.0 || ^8.0.1", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/postcss-media-query-parser": { @@ -28085,6 +34060,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" @@ -28097,6 +34073,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", @@ -28111,9 +34088,10 @@ } }, "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -28127,6 +34105,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, "license": "ISC", "dependencies": { "postcss-selector-parser": "^7.0.0" @@ -28139,9 +34118,10 @@ } }, "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -28155,6 +34135,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, "license": "ISC", "dependencies": { "icss-utils": "^5.0.0" @@ -28409,20 +34390,23 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -28465,7 +34449,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "lodash": "^4.17.20", @@ -28476,7 +34460,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", @@ -28487,11 +34471,31 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/pretty-format/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -28501,14 +34505,15 @@ } }, "node_modules/prisma": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.1.0.tgz", - "integrity": "sha512-aFI3Yi+ApUxkwCJJwyQSwpyzUX7YX3ihzuHNHOyv4GJg3X5tQsmRaJEnZ+ZyfHpMtnyahhmXVfbTZ+lS8ZtfKw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.12.0.tgz", + "integrity": "sha512-pmV7NEqQej9WjizN6RSNIwf7Y+jeh9mY1JEX2WjGxJi4YZWexClhde1yz/FuvAM+cTwzchcMytu2m4I6wPkIzg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/engines": "6.1.0" + "@prisma/config": "6.12.0", + "@prisma/engines": "6.12.0" }, "bin": { "prisma": "build/index.js" @@ -28516,14 +34521,19 @@ "engines": { "node": ">=18.18" }, - "optionalDependencies": { - "fsevents": "2.3.3" + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", "license": "MIT", "optional": true, "engines": { @@ -28540,37 +34550,12 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" - }, - "node_modules/promise-coalesce": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.2.tgz", - "integrity": "sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=16" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, - "license": "ISC" + "license": "MIT" }, "node_modules/promise-retry": { "version": "2.0.1", @@ -28600,7 +34585,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -28623,15 +34608,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -28643,6 +34619,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, "license": "MIT", "optional": true }, @@ -28659,9 +34636,10 @@ } }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -28678,10 +34656,10 @@ } }, "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "devOptional": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, "funding": [ { "type": "individual", @@ -28703,12 +34681,6 @@ "tslib": "^2.8.1" } }, - "node_modules/pvtsutils/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/pvutils": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", @@ -28719,9 +34691,10 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -28733,6 +34706,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", + "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT", + "optional": true + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -28743,6 +34733,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -28759,22 +34750,10 @@ ], "license": "MIT" }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/rambda": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/rambda/-/rambda-9.4.1.tgz", - "integrity": "sha512-awZe9AzmPI8XqizJz+NlaRbAdjhWKvuIaPikqRH6r41/ui9UTUQY5jTVdgQwnVrv1HnSMB6IBAAnNYs8HoVvZg==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-9.4.2.tgz", + "integrity": "sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==", "dev": true, "license": "MIT" }, @@ -28789,6 +34768,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" @@ -28804,37 +34784,24 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.4.24", + "iconv-lite": "0.6.3", "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -28861,9 +34828,20 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "devOptional": true, + "dev": true, "license": "MIT" }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -28889,12 +34867,12 @@ } }, "node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "license": "MIT", "engines": { - "node": ">= 14.16.0" + "node": ">= 14.18.0" }, "funding": { "type": "individual", @@ -28902,9 +34880,9 @@ } }, "node_modules/recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", "dev": true, "license": "MIT", "dependencies": { @@ -28918,6 +34896,16 @@ "node": ">= 4" } }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -28954,23 +34942,6 @@ "node": ">=8" } }, - "node_modules/redis": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", - "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", - "license": "MIT", - "workspaces": [ - "./packages/*" - ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.0", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } - }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -28993,25 +34964,25 @@ } }, "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "license": "Apache-2.0" }, "node_modules/reflect.getprototypeof": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", - "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "dunder-proto": "^1.0.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" }, "engines": { @@ -29025,12 +34996,14 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -29039,37 +35012,25 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/regex-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", - "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.1.tgz", + "integrity": "sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==", + "dev": true, "license": "MIT" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -29083,6 +35044,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", @@ -29100,12 +35062,14 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -29118,6 +35082,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -29130,7 +35095,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -29140,7 +35105,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "css-select": "^4.1.3", @@ -29154,7 +35119,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -29167,581 +35132,1072 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/renderkid/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "devOptional": true, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-in-file": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-8.3.0.tgz", + "integrity": "sha512-4VhddQiMCPIuypiwHDTM+XHjZoVu9h7ngBbSCnwGRcwdHwxltjt/m//Ep3GDwqaOx1fDSrKFQ+n7uo4uVcEz9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "glob": "^10.4.2", + "yargs": "^17.7.2" + }, + "bin": { + "replace-in-file": "bin/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/replace-in-file/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/replace-in-file/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/request-progress/node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=12" } }, - "node_modules/renderkid/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "devOptional": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, + "node_modules/resolve-url-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": "*" } }, - "node_modules/renderkid/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=8.9.0" } }, - "node_modules/renderkid/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "devOptional": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/renderkid/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "devOptional": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "node_modules/restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw==", "dev": true, "license": "MIT", + "dependencies": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + }, "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, - "node_modules/replace-in-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-7.0.1.tgz", - "integrity": "sha512-KbhgPq04eA+TxXuUxpgWIH9k/TjF+28ofon2PXP7vq6izAILhxOtksCVcLuuQLtyjouBaPdlH6RJYYcSPVxCOA==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "glob": "^8.1.0", - "yargs": "^17.7.2" - }, - "bin": { - "replace-in-file": "bin/cli.js" - }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/replace-in-file/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 4" } }, - "node_modules/replace-in-file/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "license": "ISC", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense", + "optional": true + }, + "node_modules/rollup": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", + "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.44.1", + "@rollup/rollup-android-arm64": "4.44.1", + "@rollup/rollup-darwin-arm64": "4.44.1", + "@rollup/rollup-darwin-x64": "4.44.1", + "@rollup/rollup-freebsd-arm64": "4.44.1", + "@rollup/rollup-freebsd-x64": "4.44.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", + "@rollup/rollup-linux-arm-musleabihf": "4.44.1", + "@rollup/rollup-linux-arm64-gnu": "4.44.1", + "@rollup/rollup-linux-arm64-musl": "4.44.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-musl": "4.44.1", + "@rollup/rollup-linux-s390x-gnu": "4.44.1", + "@rollup/rollup-linux-x64-gnu": "4.44.1", + "@rollup/rollup-linux-x64-musl": "4.44.1", + "@rollup/rollup-win32-arm64-msvc": "4.44.1", + "@rollup/rollup-win32-ia32-msvc": "4.44.1", + "@rollup/rollup-win32-x64-msvc": "4.44.1", + "fsevents": "~2.3.2" } }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, + "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", + "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", + "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", + "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", + "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", + "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", + "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", + "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", + "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", "license": "MIT", + "optional": true, "dependencies": { - "throttleit": "^1.0.0" + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 18" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/router/node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/rslog": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/rslog/-/rslog-1.2.9.tgz", + "integrity": "sha512-KSjM8jJKYYaKgI4jUGZZ4kdTBTM/EIGH1JnoB0ptMkzcyWaHeXW9w6JVLCYs37gh8sFZkLLqAyBb2sT02bqpcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/requireindex": { + "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", - "engines": { - "node": ">=0.10.5" + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause", + "optional": true }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 0.4" + "node": ">=0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "devOptional": true, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "devOptional": true, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz", + "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==", "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "node_modules/sass-embedded": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.89.2.tgz", + "integrity": "sha512-Ack2K8rc57kCFcYlf3HXpZEJFNUX8xd8DILldksREmYXQkRHI879yy8q4mRDJgrojkySMZqmmmW1NxrFxMsYaA==", + "devOptional": true, "license": "MIT", "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" + "@bufbuild/protobuf": "^2.5.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" }, "engines": { - "node": ">=12" + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-android-arm": "1.89.2", + "sass-embedded-android-arm64": "1.89.2", + "sass-embedded-android-riscv64": "1.89.2", + "sass-embedded-android-x64": "1.89.2", + "sass-embedded-darwin-arm64": "1.89.2", + "sass-embedded-darwin-x64": "1.89.2", + "sass-embedded-linux-arm": "1.89.2", + "sass-embedded-linux-arm64": "1.89.2", + "sass-embedded-linux-musl-arm": "1.89.2", + "sass-embedded-linux-musl-arm64": "1.89.2", + "sass-embedded-linux-musl-riscv64": "1.89.2", + "sass-embedded-linux-musl-x64": "1.89.2", + "sass-embedded-linux-riscv64": "1.89.2", + "sass-embedded-linux-x64": "1.89.2", + "sass-embedded-win32-arm64": "1.89.2", + "sass-embedded-win32-x64": "1.89.2" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.89.2.tgz", + "integrity": "sha512-oHAPTboBHRZlDBhyRB6dvDKh4KvFs+DZibDHXbkSI6dBZxMTT+Yb2ivocHnctVGucKTLQeT7+OM5DjWHyynL/A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/resolve-url-loader/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "license": "MIT" - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "devOptional": true, + "node_modules/sass-embedded-android-arm64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.89.2.tgz", + "integrity": "sha512-+pq7a7AUpItNyPu61sRlP6G2A8pSPpyazASb+8AK2pVlFayCSPAEgpwpCE9A2/Xj86xJZeMizzKUHxM2CBCUxA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "node_modules/sass-embedded-android-riscv64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.89.2.tgz", + "integrity": "sha512-HfJJWp/S6XSYvlGAqNdakeEMPOdhBkj2s2lN6SHnON54rahKem+z9pUbCriUJfM65Z90lakdGuOfidY61R9TYg==", + "cpu": [ + "riscv64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/sass-embedded-android-x64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.89.2.tgz", + "integrity": "sha512-BGPzq53VH5z5HN8de6jfMqJjnRe1E6sfnCWFd4pK+CAiuM7iw5Fx6BQZu3ikfI1l2GY0y6pRXzsVLdp/j4EKEA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.89.2.tgz", + "integrity": "sha512-UCm3RL/tzMpG7DsubARsvGUNXC5pgfQvP+RRFJo9XPIi6elopY5B6H4m9dRYDpHA+scjVthdiDwkPYr9+S/KGw==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 4" + "node": ">=14.0.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/sass-embedded-darwin-x64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.89.2.tgz", + "integrity": "sha512-D9WxtDY5VYtMApXRuhQK9VkPHB8R79NIIR6xxVlN2MIdEid/TZWi1MHNweieETXhWGrKhRKglwnHxxyKdJYMnA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=14.0.0" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/sass-embedded-linux-arm": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.89.2.tgz", + "integrity": "sha512-leP0t5U4r95dc90o8TCWfxNXwMAsQhpWxTkdtySDpngoqtTy3miMd7EYNYd1znI0FN1CBaUvbdCMbnbPwygDlA==", + "cpu": [ + "arm" + ], "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/sass-embedded-linux-arm64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.89.2.tgz", + "integrity": "sha512-2N4WW5LLsbtrWUJ7iTpjvhajGIbmDR18ZzYRywHdMLpfdPApuHPMDF5CYzHbS+LLx2UAx7CFKBnj5LLjY6eFgQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.89.2.tgz", + "integrity": "sha512-Z6gG2FiVEEdxYHRi2sS5VIYBmp17351bWtOCUZ/thBM66+e70yiN6Eyqjz80DjL8haRUegNQgy9ZJqsLAAmr9g==", + "cpu": [ + "arm" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=14.0.0" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense", - "optional": true - }, - "node_modules/rollup": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.26.0.tgz", - "integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==", + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.89.2.tgz", + "integrity": "sha512-nTyuaBX6U1A/cG7WJh0pKD1gY8hbg1m2SnzsyoFG+exQ0lBX/lwTLHq3nyhF+0atv7YYhYKbmfz+sjPP8CZ9lw==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.26.0", - "@rollup/rollup-android-arm64": "4.26.0", - "@rollup/rollup-darwin-arm64": "4.26.0", - "@rollup/rollup-darwin-x64": "4.26.0", - "@rollup/rollup-freebsd-arm64": "4.26.0", - "@rollup/rollup-freebsd-x64": "4.26.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.26.0", - "@rollup/rollup-linux-arm-musleabihf": "4.26.0", - "@rollup/rollup-linux-arm64-gnu": "4.26.0", - "@rollup/rollup-linux-arm64-musl": "4.26.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.26.0", - "@rollup/rollup-linux-riscv64-gnu": "4.26.0", - "@rollup/rollup-linux-s390x-gnu": "4.26.0", - "@rollup/rollup-linux-x64-gnu": "4.26.0", - "@rollup/rollup-linux-x64-musl": "4.26.0", - "@rollup/rollup-win32-arm64-msvc": "4.26.0", - "@rollup/rollup-win32-ia32-msvc": "4.26.0", - "@rollup/rollup-win32-x64-msvc": "4.26.0", - "fsevents": "~2.3.2" + "node": ">=14.0.0" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.89.2.tgz", + "integrity": "sha512-N6oul+qALO0SwGY8JW7H/Vs0oZIMrRMBM4GqX3AjM/6y8JsJRxkAwnfd0fDyK+aICMFarDqQonQNIx99gdTZqw==", + "cpu": [ + "riscv64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.0.0" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.89.2.tgz", + "integrity": "sha512-K+FmWcdj/uyP8GiG9foxOCPfb5OAZG0uSVq80DKgVSC0U44AdGjvAvVZkrgFEcZ6cCqlNC2JfYmslB5iqdL7tg==", + "cpu": [ + "x64" ], + "dev": true, "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.89.2.tgz", + "integrity": "sha512-g9nTbnD/3yhOaskeqeBQETbtfDQWRgsjHok6bn7DdAuwBsyrR3JlSFyqKc46pn9Xxd9SQQZU8AzM4IR+sY0A0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "node_modules/sass-embedded-linux-x64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.89.2.tgz", + "integrity": "sha512-Ax7dKvzncyQzIl4r7012KCMBvJzOz4uwSNoyoM5IV6y5I1f5hEwI25+U4WfuTqdkv42taCMgpjZbh9ERr6JVMQ==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "mri": "^1.1.0" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">=14.0.0" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "node_modules/sass-embedded-win32-arm64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.89.2.tgz", + "integrity": "sha512-j96iJni50ZUsfD6tRxDQE2QSYQ2WrfHxeiyAXf41Kw0V4w5KYR/Sf6rCZQLMTUOHnD16qTMVpQi20LQSqf4WGg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.0.0" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } + "node_modules/sass-embedded-win32-x64": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.89.2.tgz", + "integrity": "sha512-cS2j5ljdkQsb4PaORiClaVYynE9OAPZG/XjbOMxpQmjRIf7UroY4PEIH+Waf+y47PfXFX9SyxhYuw2NIKGbEng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" ], - "license": "MIT" + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "devOptional": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/sass": { - "version": "1.80.7", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", - "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", + "node_modules/sass-loader": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz", + "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==", + "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "neo-async": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">= 18.12.0" }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/sax": { @@ -29754,7 +36210,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -29774,9 +36230,10 @@ } }, "node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -29792,6 +36249,24 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/schema-utils/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/secure-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", @@ -29799,6 +36274,12 @@ "dev": true, "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, "node_modules/select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", @@ -29810,12 +36291,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, "license": "MIT" }, "node_modules/selfsigned": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, "license": "MIT", "dependencies": { "@types/node-forge": "^1.3.0", @@ -29826,9 +36309,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -29858,43 +36341,47 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/send/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "node_modules/send/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/send/node_modules/ms": { "version": "2.1.3", @@ -29906,6 +36393,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -29915,6 +36403,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.4", @@ -29929,10 +36418,25 @@ "node": ">= 0.8.0" } }, + "node_modules/serve-index/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/serve-index/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -29942,6 +36446,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -29951,6 +36456,7 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, "license": "MIT", "dependencies": { "depd": "~1.1.2", @@ -29966,105 +36472,56 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, "license": "ISC" }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, "license": "MIT" }, + "node_modules/serve-index/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true, "license": "ISC" }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-static/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "node": ">= 18" } }, "node_modules/set-function-length": { @@ -30101,6 +36558,21 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -30111,6 +36583,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, "license": "MIT", "dependencies": { "kind-of": "^6.0.2" @@ -30123,7 +36596,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -30136,16 +36609,24 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/shell-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz", + "integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==", + "dev": true, + "license": "MIT" + }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -30172,6 +36653,28 @@ "node": ">=4" } }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/shx": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", @@ -30262,24 +36765,30 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/sigstore": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", - "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.1.0.tgz", + "integrity": "sha512-ZpzWAFHIFqyFE56dXqgX/DkDRZdz+rRcjoIk/RQU4IX0wiCv1l8S7ZrXDHcCc+uaf+6o7w3h2l3g6GYG5TKN9Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^3.0.0", + "@sigstore/bundle": "^3.1.0", "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^3.0.0", - "@sigstore/tuf": "^3.0.0", - "@sigstore/verify": "^2.0.0" + "@sigstore/protobuf-specs": "^0.4.0", + "@sigstore/sign": "^3.1.0", + "@sigstore/tuf": "^3.1.0", + "@sigstore/verify": "^2.1.0" }, "engines": { "node": "^18.17.0 || >=20.5.0" @@ -30291,21 +36800,6 @@ "integrity": "sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w==", "license": "ISC" }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" - }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -30325,57 +36819,27 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/smart-buffer": { @@ -30393,6 +36857,7 @@ "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, "license": "MIT", "dependencies": { "faye-websocket": "^0.11.3", @@ -30404,15 +36869,16 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", + "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", "dev": true, "license": "MIT", "dependencies": { @@ -30447,12 +36913,12 @@ "license": "MIT" }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { @@ -30468,6 +36934,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "dev": true, "license": "MIT", "dependencies": { "iconv-lite": "^0.6.3", @@ -30494,6 +36961,15 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -30524,9 +37000,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -30534,6 +37010,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, "license": "MIT", "dependencies": { "debug": "^4.1.0", @@ -30550,6 +37027,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, "license": "MIT", "dependencies": { "debug": "^4.1.0", @@ -30593,6 +37071,20 @@ "node": ">=0.10.0" } }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, "node_modules/ssri": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", @@ -30610,7 +37102,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" @@ -30623,12 +37115,19 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true, + "license": "MIT" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -30644,27 +37143,152 @@ "escodegen": "^1.8.1" } }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/storybook": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.4.7.tgz", - "integrity": "sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw==", + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.0.17.tgz", + "integrity": "sha512-O+9jgJ+Trlq9VGD1uY4OBLKQWHHDKM/A/pA8vMW6PVehhGHNvpzcIC1bngr6mL5gGHZP2nBv+9XG8pTMcggMmg==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core": "8.4.7" + "@storybook/global": "^5.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/user-event": "^14.6.1", + "@vitest/expect": "3.2.4", + "@vitest/spy": "3.2.4", + "better-opn": "^3.0.2", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", + "esbuild-register": "^3.5.0", + "recast": "^0.23.5", + "semver": "^7.6.2", + "ws": "^8.18.0" }, "bin": { - "getstorybook": "bin/index.cjs", - "sb": "bin/index.cjs", "storybook": "bin/index.cjs" }, "funding": { @@ -30751,7 +37375,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "char-regex": "^1.0.2", @@ -30780,7 +37404,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -30867,7 +37491,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -30877,20 +37501,20 @@ } }, "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -30913,7 +37537,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -30922,35 +37546,54 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stripe": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-17.3.0.tgz", - "integrity": "sha512-WACmytj1MssbIwGwPfAomo61jgldb2B/cB6A3W/Bqs9zId1olVcAa8X7HERkqpw4190GSsbvrD7KnkZogatyvw==", + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "license": "MIT", "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" + "escape-string-regexp": "^1.0.2" }, "engines": { - "node": ">=12.*" + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/stripe/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/stripe": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-18.3.0.tgz", + "integrity": "sha512-FkxrTUUcWB4CVN2yzgsfF/YHD6WgYHduaa7VmokCy5TLCgl5UNJkwortxcedrxSavQ8Qfa4Ir4JxcbIYiBsyLg==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "qs": "^6.11.0" + }, + "engines": { + "node": ">=12.*" + }, + "peerDependencies": { + "@types/node": ">=12.x.x" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/stripe/node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -30959,11 +37602,21 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stripe/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } }, "node_modules/style-loader": { "version": "3.3.4", @@ -31000,115 +37653,17 @@ } }, "node_modules/stylis": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", - "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", "license": "MIT", "optional": true }, - "node_modules/stylus": { - "version": "0.64.0", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.64.0.tgz", - "integrity": "sha512-ZIdT8eUv8tegmqy1tTIdJv9We2DumkNZFdCF5mz/Kpq3OcTaxSuCAYZge6HKK2CmNC02G1eJig2RV7XTw5hQrA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@adobe/css-tools": "~4.3.3", - "debug": "^4.3.2", - "glob": "^10.4.5", - "sax": "~1.4.1", - "source-map": "^0.7.3" - }, - "bin": { - "stylus": "bin/stylus" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://opencollective.com/stylus" - } - }, - "node_modules/stylus-loader": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-7.1.3.tgz", - "integrity": "sha512-TY0SKwiY7D2kMd3UxaWKSf3xHF0FFN/FAfsSqfrhxRT/koXTwffq2cgEWDkLQz7VojMu7qEEHt5TlMjkPx9UDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "^3.2.12", - "normalize-path": "^3.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "stylus": ">=0.52.4", - "webpack": "^5.0.0" - } - }, - "node_modules/stylus/node_modules/@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/stylus/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/stylus/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/stylus/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -31121,6 +37676,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -31136,12 +37692,12 @@ "license": "BSD-2-Clause" }, "node_modules/svgmap": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.6.0.tgz", - "integrity": "sha512-MePkVjgYlHwEfCSuGt+wB6WX6Z2fTD6yDtqZO5syzKYH7gamt1Hp9f/Bw5R49OvBtbsF7WCaGR0/GhewZGGA+w==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.12.2.tgz", + "integrity": "sha512-SCX1Oys3v1dz3mTEbQha+6lrHGyu3LwXBhcgW0HlTh7waQDMFqNUKD8hADvDaPkPapRvNCLMnXaVD1Pbxbnhow==", "license": "MIT", "dependencies": { - "svg-pan-zoom": "^3.6.1" + "svg-pan-zoom": "^3.6.2" } }, "node_modules/svgo": { @@ -31180,48 +37736,101 @@ "node": ">= 10" } }, + "node_modules/swr": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.4.tgz", + "integrity": "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "devOptional": true, + "dev": true, "license": "MIT" }, + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" } }, "node_modules/tar-stream": { @@ -31241,50 +37850,134 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tar/node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "dependencies": { + "ms": "2.1.2" }, "engines": { - "node": ">=10" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "node_modules/tcp-port-used/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } + "license": "MIT" }, "node_modules/telejson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", - "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-8.0.0.tgz", + "integrity": "sha512-8mCI1dHX80nchOkIEgvyWlGLgeh/SxO7JZPOud0DxvfFdI6MgwxRL8ff7rVdj6436uHhpWaxLQjU74Jb2I0u9g==", "dev": true, - "license": "MIT", - "dependencies": { - "memoizerific": "^1.11.3" - } + "license": "MIT" }, "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "devOptional": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -31296,9 +37989,10 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", - "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -31329,19 +38023,11 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -31356,6 +38042,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -31367,35 +38054,18 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.37.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", - "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, "license": "MIT" }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", @@ -31406,19 +38076,49 @@ "node": ">=8" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/throttleit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", + "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -31434,6 +38134,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, "license": "MIT" }, "node_modules/tiny-emitter": { @@ -31450,24 +38151,33 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "license": "MIT", + "optional": true + }, "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", - "dev": true, + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "license": "MIT", "dependencies": { - "fdir": "^6.4.2", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -31475,15 +38185,33 @@ } }, "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" } }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "license": "MIT" + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -31498,23 +38226,14 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "devOptional": true, - "license": "BSD-3-Clause" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "BSD-3-Clause" }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -31532,6 +38251,23 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.4.tgz", + "integrity": "sha512-MD9MjpVNhVyH4fyd5rKphjvt/1qj+PtQUz65aFqAZA6XniWAuSFRjLk3e2VALEFlh9OwBpXUN7rfeqSnT/Fmkw==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -31582,7 +38318,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.1.1" @@ -31591,1583 +38327,1549 @@ "node": ">=12" } }, + "node_modules/tree-dump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.3.tgz", + "integrity": "sha512-il+Cv80yVHFBwokQSfd4bldvr1Md951DpgAGfmhydt04L+YzHgubm2tQ7zueWDcGENKHq0ZvGFR/hjvNXilHEg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, "license": "MIT", "bin": { "tree-kill": "cli.js" } }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "license": "MIT", - "engines": { - "node": ">=16" + "dependencies": { + "escape-string-regexp": "^1.0.2" }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "devOptional": true, - "license": "MIT", "engines": { - "node": ">=6.10" + "node": ">=0.10.0" } }, - "node_modules/ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", - "dev": true, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "node": ">=0.8.0" } }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, "engines": { - "node": ">=12.0.0" + "node": ">=18.12" }, "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" + "typescript": ">=4.8.4" } }, - "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/ts-checker-rspack-plugin": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ts-checker-rspack-plugin/-/ts-checker-rspack-plugin-1.1.4.tgz", + "integrity": "sha512-lDpKuAubxUlsonUE1LpZS5fw7tfjutNb0lwjAo0k8OcxpWv/q18ytaD6eZXdjrFdTEFNIHtKp9dNkUKGky8SgA==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "@babel/code-frame": "^7.16.7", + "@rspack/lite-tapable": "^1.0.0", + "chokidar": "^3.5.3", + "is-glob": "^4.0.3", + "memfs": "^4.14.0", + "minimatch": "^9.0.5", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=16.0.0" }, "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "@rspack/core": "^1.0.0", + "typescript": ">=3.8.0" }, "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { + "@rspack/core": { "optional": true } } }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "node_modules/ts-checker-rspack-plugin/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" + "balanced-match": "^1.0.0" } }, - "node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", - "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "node_modules/ts-checker-rspack-plugin/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tapable": "^2.2.1", - "tsconfig-paths": "^4.1.2" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=10.13.0" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "license": "0BSD" - }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "node_modules/ts-checker-rspack-plugin/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "Apache-2.0", - "peer": true, + "license": "ISC", "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + "node": ">= 6" } }, - "node_modules/tslint/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/ts-checker-rspack-plugin/node_modules/memfs": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.24.0.tgz", + "integrity": "sha512-PiyWpigBOgdsdvnn4U3PlQytj46ZEw/dMVmcqXuX1KUHoYzaGTL25E9rfK+c26mPAh9RmBdXldoxbQkYbH20Uw==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "dependencies": { - "color-convert": "^1.9.0" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/ts-checker-rspack-plugin/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", - "peer": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tslint/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/ts-checker-rspack-plugin/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "1.1.3" + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tslint/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/tslint/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/ts-checker-rspack-plugin/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">=4" + "node": ">=8.10.0" } }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver" + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6.10" } }, - "node_modules/tslint/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/ts-jest": { + "version": "29.4.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz", + "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "has-flag": "^3.0.0" + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.2", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } } }, - "node_modules/tslint/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "0BSD", - "peer": true + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/tslint/node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/ts-loader": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", + "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "tslib": "^1.8.1" + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" }, "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + "typescript": "*", + "webpack": "^5.0.0" } }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.6.x" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "license": "MIT", "dependencies": { - "tslib": "^1.8.1" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "engines": { - "node": ">= 6" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tuf-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", - "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", "dependencies": { - "@tufjs/models": "3.0.1", - "debug": "^4.3.6", - "make-fetch-happen": "^14.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.0.tgz", + "integrity": "sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10.13.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "Unlicense" - }, - "node_modules/twitter-api-v2": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/twitter-api-v2/-/twitter-api-v2-1.14.2.tgz", - "integrity": "sha512-389e/rWaN8zWkmD5z2IpKVb5+ojPxVtrexQoGBI1Xfib1mE/9M7k7zbnZ3Q/WLwthwcWkQIlB25ecT64AL8LvQ==", - "license": "Apache-2.0" - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" + "minimist": "^1.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "peer": true, "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" }, "engines": { - "node": ">= 0.4" + "node": ">=4.8.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" } }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "license": "MIT" - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/tslint/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" }, "engines": { - "node": ">=14.17" + "node": ">=4" } }, - "node_modules/uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "node_modules/tslint/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@lukeed/csprng": "^1.0.0" - }, - "engines": { - "node": ">=8" + "sprintf-js": "~1.0.2" } }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==", - "license": "MIT" - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/tslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/undici": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", - "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "node_modules/tslint/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=18.17" + "peer": true, + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "node_modules/tslint/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "node_modules/tslint/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, "license": "MIT", + "peer": true + }, + "node_modules/tslint/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "license": "MIT", + "node_modules/tslint/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=4" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "node_modules/tslint/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/tslint/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/tslint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { "node": ">=4" } }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD", + "peer": true + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.6.x" } }, - "node_modules/union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "qs": "^6.4.0" + "tslib": "^1.8.1" }, - "engines": { - "node": ">= 0.8.0" + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" } }, - "node_modules/union/node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD", + "peer": true + }, + "node_modules/tuf-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.1.0.tgz", + "integrity": "sha512-3T3T04WzowbwV2FDiGXBbr81t64g1MUGGJRgT4x5o97N+8ArdhVCAF9IxFrxuSJmM3E5Asn7nKHkao0ibcZXAg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" + "@tufjs/models": "3.0.1", + "debug": "^4.4.1", + "make-fetch-happen": "^14.0.3" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/unique-filename": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", - "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "unique-slug": "^5.0.0" + "safe-buffer": "^5.0.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "*" } }, - "node_modules/unique-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", - "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/twitter-api-v2": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/twitter-api-v2/-/twitter-api-v2-1.23.0.tgz", + "integrity": "sha512-5i1agETVpTuY68Zuk9i2B3N9wHzc4JIWw0WKyG4CEaFv9mRKmU87roa+U1oYYXTChWb0HMcqfkwoBJHYmLbeDA==", + "license": "Apache-2.0" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4" + "prelude-ls": "^1.2.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.8.0" } }, - "node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "@types/unist": "^2.0.0" + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/universalify": { + "node_modules/type-is": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": ">= 0.6" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/type-is/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/unplugin": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz", - "integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==", - "dev": true, + "node_modules/type-is/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "acorn": "^8.14.0", - "webpack-virtual-modules": "^0.6.2" + "mime-db": "^1.54.0" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.6" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=4", - "yarn": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, - "bin": { - "update-browserslist-db": "cli.js" + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.12.3" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", "dev": true, "license": "MIT" }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT", + "optional": true + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", "license": "MIT", "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==", "license": "MIT" }, - "node_modules/url/node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, + "node_modules/uint8array-extras": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", + "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "devOptional": true, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/undici": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">=18.17" } }, - "node_modules/uuid": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.2.tgz", - "integrity": "sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" + "engines": { + "node": ">=4" } }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/uvu/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "optional": true, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=4" } }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "license": "MIT" + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "devOptional": true, - "license": "ISC", + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "qs": "^6.4.0" }, "engines": { - "node": ">=10.12.0" + "node": ">= 0.8.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/unique-filename": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/validate-npm-package-name": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", - "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", + "node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 10.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "node_modules/unplugin": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz", + "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==", "dev": true, - "engines": [ - "node >=0.6.0" - ], "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/verror/node_modules/extsprintf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", - "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" + "napi-postinstall": "^0.3.0" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" + "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=12" + "node": ">=4", + "yarn": "*" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/url/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, "engines": { - "node": ">=12" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.4.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10.12.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz", + "integrity": "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/validator": { + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.10" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" ], "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", + "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.40.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=14.0.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" } }, - "node_modules/vite/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", - "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", - "cpu": [ - "arm64" - ], + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "optional": true }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "hasInstallScript": true, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite/node_modules/rollup": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", - "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.1", - "@rollup/rollup-android-arm64": "4.29.1", - "@rollup/rollup-darwin-arm64": "4.29.1", - "@rollup/rollup-darwin-x64": "4.29.1", - "@rollup/rollup-freebsd-arm64": "4.29.1", - "@rollup/rollup-freebsd-x64": "4.29.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", - "@rollup/rollup-linux-arm-musleabihf": "4.29.1", - "@rollup/rollup-linux-arm64-gnu": "4.29.1", - "@rollup/rollup-linux-arm64-musl": "4.29.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", - "@rollup/rollup-linux-riscv64-gnu": "4.29.1", - "@rollup/rollup-linux-s390x-gnu": "4.29.1", - "@rollup/rollup-linux-x64-gnu": "4.29.1", - "@rollup/rollup-linux-x64-musl": "4.29.1", - "@rollup/rollup-win32-arm64-msvc": "4.29.1", - "@rollup/rollup-win32-ia32-msvc": "4.29.1", - "@rollup/rollup-win32-x64-msvc": "4.29.1", - "fsevents": "~2.3.2" - } + "optional": true + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT", + "optional": true }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "xml-name-validator": "^4.0.0" @@ -33187,16 +39889,16 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -33210,6 +39912,7 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, "license": "MIT", "dependencies": { "minimalistic-assert": "^1.0.0" @@ -33219,6 +39922,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -33231,13 +39935,6 @@ "license": "MIT", "optional": true }, - "node_modules/web-worker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", - "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", - "license": "Apache-2.0", - "optional": true - }, "node_modules/webcrypto-core": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz", @@ -33252,31 +39949,26 @@ "tslib": "^2.7.0" } }, - "node_modules/webcrypto-core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" } }, "node_modules/webpack": { - "version": "5.97.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", - "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "version": "5.99.9", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", + "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", @@ -33293,9 +39985,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", + "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, @@ -33342,27 +40034,24 @@ "node": ">= 10.13.0" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/webpack-bundle-analyzer/node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=10.0.0" } }, - "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10" } }, "node_modules/webpack-bundle-analyzer/node_modules/ws": { @@ -33391,6 +40080,7 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", + "dev": true, "license": "MIT", "dependencies": { "colorette": "^2.0.10", @@ -33408,72 +40098,19 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware/node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.1.tgz", - "integrity": "sha512-osjeBqMJ2lb/j/M8NCPjs1ylqWIcTRTycIhVB5pt6LgzgeRSb0YRZ7j9RfA8wIUrsr/medIuhVyonXRZWLyfdw==", - "license": "Apache-2.0", - "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/@jsonjoy.com/util": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz", - "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==", - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.15.1.tgz", - "integrity": "sha512-ufCzgFwiVnR6R9cCYuvwznJdhdYXEvFl0hpnM4cCtVaVkHuqBR+6fo2sqt1SSMdp+uiHw9GyPZr3OMM5tqjSmQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.24.0.tgz", + "integrity": "sha512-PiyWpigBOgdsdvnn4U3PlQytj46ZEw/dMVmcqXuX1KUHoYzaGTL25E9rfK+c26mPAh9RmBdXldoxbQkYbH20Uw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", @@ -33489,49 +40126,17 @@ "url": "https://github.com/sponsors/streamich" } }, - "node_modules/webpack-dev-middleware/node_modules/thingies": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", - "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", - "license": "Unlicense", - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "tslib": "^2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/tree-dump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", - "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/webpack-dev-server": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", - "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "dev": true, "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", "@types/sockjs": "^0.3.36", @@ -33542,10 +40147,9 @@ "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "express": "^4.19.2", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", + "http-proxy-middleware": "^2.0.9", "ipaddr.js": "^2.1.0", "launch-editor": "^2.6.1", "open": "^10.0.3", @@ -33580,46 +40184,309 @@ } } }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/webpack-dev-server/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/webpack-dev-server/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server/node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-dev-server/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/webpack-dev-server/node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webpack-dev-server/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 8.10.0" - }, + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-server/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-server/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, + "node_modules/webpack-dev-server/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-dev-server/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">= 0.6" } }, + "node_modules/webpack-dev-server/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, "node_modules/webpack-dev-server/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -33628,10 +40495,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/webpack-dev-server/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/webpack-dev-server/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/webpack-dev-server/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -33640,6 +40540,88 @@ "node": ">=8.10.0" } }, + "node_modules/webpack-dev-server/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/webpack-dev-server/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webpack-dev-server/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-dev-server/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/webpack-dev-server/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webpack-dev-server/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/webpack-hot-middleware": { "version": "2.26.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", @@ -33656,6 +40638,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", @@ -33677,9 +40660,10 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -33689,6 +40673,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, "license": "MIT", "dependencies": { "typed-assert": "^1.0.8" @@ -33713,59 +40698,42 @@ "dev": true, "license": "MIT" }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/webpack/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", @@ -33780,39 +40748,38 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=0.8.0" } }, "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "devOptional": true, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "devOptional": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "tr46": "^3.0.0", @@ -33823,19 +40790,19 @@ } }, "node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^3.1.1" + "isexe": "^2.0.0" }, "bin": { - "node-which": "bin/which.js" + "node-which": "bin/node-which" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 8" } }, "node_modules/which-boxed-primitive": { @@ -33906,16 +40873,17 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, @@ -33926,20 +40894,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, "license": "MIT" }, "node_modules/word-wrap": { @@ -33952,20 +40911,17 @@ } }, "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/wrap-ansi-cjs": { @@ -33973,7 +40929,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -33987,68 +40943,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -34056,23 +40950,24 @@ "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "devOptional": true, + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -34094,7 +40989,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12" @@ -34104,7 +40999,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/xmldoc": { @@ -34135,39 +41030,33 @@ } }, "node_modules/yahoo-finance2": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-2.11.3.tgz", - "integrity": "sha512-yN4ADFNi2oNYtO79ntbEkSWdVi4KVmGYLwDJ5KV0czxILbAGj4ah6oCBYvMONeHAeDqxtS62zrG8xrHNF/2STw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-3.4.1.tgz", + "integrity": "sha512-L8Ubmdsn6f+uJEuEDUUHR5n95TFcGkMiMkV0phmvPONFekAn1vWzsEzGfIDG2ODR7aYBB+aURdQg7a3HX2iUHA==", "license": "MIT", "dependencies": { - "@types/tough-cookie": "^4.0.2", - "ajv": "8.10.0", - "ajv-formats": "2.1.1", - "node-fetch": "^2.6.1", - "tough-cookie": "^4.1.2", - "tough-cookie-file-store": "^2.0.3" + "@deno/shim-deno": "~0.18.0", + "fetch-mock-cache": "npm:fetch-mock-cache@^2.1.3", + "tough-cookie": "npm:tough-cookie@^5.1.1", + "tough-cookie-file-store": "npm:tough-cookie-file-store@^2.0.3" }, "bin": { - "yahoo-finance": "bin/yahoo-finance.js" + "yahoo-finance": "bin/yahoo-finance.mjs" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.0.0" } }, - "node_modules/yahoo-finance2/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "license": "MIT", + "node_modules/yahoo-finance2/node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "license": "BSD-3-Clause", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "tldts": "^6.1.32" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=16" } }, "node_modules/yallist": { @@ -34177,40 +41066,145 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "devOptional": true, "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14.6" } }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/yargs/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/yargs/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yauzl": { @@ -34247,7 +41241,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -34268,10 +41262,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, "node_modules/zone.js": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", - "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", + "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", "license": "MIT" } } diff --git a/package.json b/package.json index 650918efd..c1aa0762d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.132.0", + "version": "2.186.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", @@ -15,7 +15,7 @@ "affected:test": "nx affected:test", "analyze:client": "nx run client:build:production --stats-json && webpack-bundle-analyzer -p 1234 dist/apps/client/en/stats.json", "angular": "node --max_old_space_size=32768 ./node_modules/@angular/cli/bin/ng", - "build:production": "nx run api:copy-assets && nx run api:build:production && nx run client:copy-assets && nx run client:build:production && npm run replace-placeholders-in-build", + "build:production": "nx run api:copy-assets && nx run api:build:production && nx run client:copy-assets && nx run client:build:production && nx run ui:build-storybook && npm run replace-placeholders-in-build", "build:storybook": "nx run ui:build-storybook", "database:format-schema": "prisma format", "database:generate-typings": "prisma generate", @@ -39,7 +39,7 @@ "postinstall": "prisma generate", "prepare": "husky", "prisma": "prisma", - "replace-placeholders-in-build": "node ./replace.build.js", + "replace-placeholders-in-build": "node ./replace.build.mjs", "start": "node dist/apps/api/main", "start:client": "nx run client:copy-assets && nx run client:serve --configuration=development-en --hmr -o", "start:production": "npm run database:migrate && npm run database:seed && node main", @@ -56,165 +56,162 @@ "workspace-generator": "nx workspace-generator" }, "dependencies": { - "@angular/animations": "19.0.5", - "@angular/cdk": "19.0.4", - "@angular/common": "19.0.5", - "@angular/compiler": "19.0.5", - "@angular/core": "19.0.5", - "@angular/forms": "19.0.5", - "@angular/material": "19.0.4", - "@angular/platform-browser": "19.0.5", - "@angular/platform-browser-dynamic": "19.0.5", - "@angular/router": "19.0.5", - "@angular/service-worker": "19.0.5", + "@angular/animations": "20.1.3", + "@angular/cdk": "20.1.3", + "@angular/common": "20.1.3", + "@angular/compiler": "20.1.3", + "@angular/core": "20.1.3", + "@angular/forms": "20.1.3", + "@angular/material": "20.1.3", + "@angular/platform-browser": "20.1.3", + "@angular/platform-browser-dynamic": "20.1.3", + "@angular/router": "20.1.3", + "@angular/service-worker": "20.1.3", "@codewithdan/observable-store": "2.2.15", + "@date-fns/utc": "2.1.0", "@dfinity/agent": "0.15.7", "@dfinity/auth-client": "0.15.7", "@dfinity/candid": "0.15.7", "@dfinity/identity": "0.15.7", "@dfinity/principal": "0.15.7", "@dinero.js/currencies": "2.0.0-alpha.8", - "@internationalized/number": "3.6.0", - "@nestjs/bull": "10.0.1", - "@nestjs/cache-manager": "2.2.2", - "@nestjs/common": "10.1.3", - "@nestjs/config": "3.0.0", - "@nestjs/core": "10.1.3", - "@nestjs/event-emitter": "2.0.4", - "@nestjs/jwt": "10.1.0", - "@nestjs/passport": "10.0.3", - "@nestjs/platform-express": "10.1.3", - "@nestjs/schedule": "3.0.2", - "@nestjs/serve-static": "4.0.0", - "@prisma/client": "6.1.0", - "@simplewebauthn/browser": "9.0.1", - "@simplewebauthn/server": "9.0.3", - "@stripe/stripe-js": "5.4.0", + "@internationalized/number": "3.6.3", + "@ionic/angular": "8.6.3", + "@keyv/redis": "4.4.0", + "@nestjs/bull": "11.0.2", + "@nestjs/cache-manager": "3.0.1", + "@nestjs/common": "11.1.3", + "@nestjs/config": "4.0.2", + "@nestjs/core": "11.1.3", + "@nestjs/event-emitter": "3.0.1", + "@nestjs/jwt": "11.0.0", + "@nestjs/passport": "11.0.5", + "@nestjs/platform-express": "11.1.3", + "@nestjs/schedule": "6.0.0", + "@nestjs/serve-static": "5.0.3", + "@openrouter/ai-sdk-provider": "0.7.2", + "@prisma/client": "6.12.0", + "@simplewebauthn/browser": "13.1.0", + "@simplewebauthn/server": "13.1.1", + "@stripe/stripe-js": "7.6.1", + "ai": "4.3.16", "alphavantage": "2.2.0", - "big.js": "6.2.2", - "bootstrap": "4.6.0", - "bull": "4.16.2", - "cache-manager": "5.7.6", - "cache-manager-redis-yet": "5.1.4", - "chart.js": "4.2.0", + "big.js": "7.0.1", + "bootstrap": "4.6.2", + "bull": "4.16.5", + "chart.js": "4.4.9", "chartjs-adapter-date-fns": "3.0.0", - "chartjs-chart-treemap": "2.3.1", - "chartjs-plugin-annotation": "2.1.2", + "chartjs-chart-treemap": "3.1.0", + "chartjs-plugin-annotation": "3.1.0", "chartjs-plugin-datalabels": "2.2.0", "cheerio": "1.0.0", "class-transformer": "0.5.1", - "class-validator": "0.14.1", - "color": "4.2.3", - "countries-and-timezones": "3.7.2", + "class-validator": "0.14.2", + "color": "5.0.0", + "countries-and-timezones": "3.8.0", "countries-list": "3.1.1", - "countup.js": "2.8.0", - "date-fns": "3.6.0", - "envalid": "7.3.1", + "countup.js": "2.8.2", + "date-fns": "4.1.0", + "envalid": "8.0.0", + "fuse.js": "7.1.0", "google-spreadsheet": "3.2.0", - "got": "11.8.6", "helmet": "7.0.0", "http-status-codes": "2.3.0", - "ionicons": "7.4.0", + "ionicons": "8.0.10", "jsonpath": "1.1.1", "lodash": "4.17.21", "marked": "15.0.4", "ms": "3.0.0-canary.1", - "ng-extract-i18n-merge": "2.13.1", - "ngx-device-detector": "9.0.0", - "ngx-markdown": "19.0.0", - "ngx-skeleton-loader": "9.0.0", - "ngx-stripe": "19.0.0", + "ng-extract-i18n-merge": "3.0.0", + "ngx-device-detector": "10.0.2", + "ngx-markdown": "20.0.0", + "ngx-skeleton-loader": "11.2.1", + "ngx-stripe": "20.7.0", "open-color": "1.9.1", "papaparse": "5.3.1", "passport": "0.7.0", "passport-google-oauth20": "2.0.0", "passport-headerapikey": "1.2.2", "passport-jwt": "4.0.1", - "reflect-metadata": "0.1.13", - "rxjs": "7.5.6", - "stripe": "17.3.0", - "svgmap": "2.6.0", - "twitter-api-v2": "1.14.2", - "uuid": "11.0.2", - "yahoo-finance2": "2.11.3", - "zone.js": "0.15.0" + "reflect-metadata": "0.2.2", + "rxjs": "7.8.1", + "stripe": "18.3.0", + "svgmap": "2.12.2", + "twitter-api-v2": "1.23.0", + "uuid": "11.1.0", + "yahoo-finance2": "3.4.1", + "zone.js": "0.15.1" }, "devDependencies": { - "@angular-devkit/build-angular": "19.0.6", - "@angular-devkit/core": "19.0.6", - "@angular-devkit/schematics": "19.0.6", - "@angular-eslint/eslint-plugin": "19.0.2", - "@angular-eslint/eslint-plugin-template": "19.0.2", - "@angular-eslint/template-parser": "19.0.2", - "@angular/cli": "19.0.6", - "@angular/compiler-cli": "19.0.5", - "@angular/language-service": "19.0.5", - "@angular/localize": "19.0.5", - "@angular/pwa": "19.0.6", - "@nestjs/schematics": "10.0.1", - "@nestjs/testing": "10.1.3", - "@nx/angular": "20.3.0", - "@nx/cypress": "20.3.0", - "@nx/eslint-plugin": "20.3.0", - "@nx/jest": "20.3.0", - "@nx/js": "20.3.0", - "@nx/module-federation": "20.3.0", - "@nx/nest": "20.3.0", - "@nx/node": "20.3.0", - "@nx/storybook": "20.3.0", - "@nx/web": "20.3.0", - "@nx/workspace": "20.3.0", - "@schematics/angular": "19.0.6", - "@simplewebauthn/types": "9.0.1", - "@storybook/addon-essentials": "8.4.7", - "@storybook/addon-interactions": "8.4.7", - "@storybook/angular": "8.4.7", - "@storybook/core-server": "8.4.7", - "@trivago/prettier-plugin-sort-imports": "4.3.0", + "@angular-devkit/build-angular": "20.1.3", + "@angular-devkit/core": "20.1.3", + "@angular-devkit/schematics": "20.1.3", + "@angular-eslint/eslint-plugin": "20.1.1", + "@angular-eslint/eslint-plugin-template": "20.1.1", + "@angular-eslint/template-parser": "20.1.1", + "@angular/cli": "20.1.3", + "@angular/compiler-cli": "20.1.3", + "@angular/language-service": "20.1.3", + "@angular/localize": "20.1.3", + "@angular/pwa": "20.1.3", + "@eslint/eslintrc": "3.3.1", + "@eslint/js": "9.24.0", + "@nestjs/schematics": "11.0.5", + "@nestjs/testing": "11.1.3", + "@nx/angular": "21.3.9", + "@nx/cypress": "21.3.9", + "@nx/eslint-plugin": "21.3.9", + "@nx/jest": "21.3.9", + "@nx/js": "21.3.9", + "@nx/module-federation": "21.3.9", + "@nx/nest": "21.3.9", + "@nx/node": "21.3.9", + "@nx/storybook": "21.3.9", + "@nx/web": "21.3.9", + "@nx/workspace": "21.3.9", + "@schematics/angular": "20.1.3", + "@storybook/addon-docs": "9.0.17", + "@storybook/angular": "9.0.17", + "@trivago/prettier-plugin-sort-imports": "5.2.2", "@types/big.js": "6.2.2", - "@types/cache-manager": "4.0.6", - "@types/color": "3.0.6", "@types/google-spreadsheet": "3.1.5", "@types/jest": "29.5.13", - "@types/lodash": "4.17.7", - "@types/node": "20.14.10", + "@types/lodash": "4.17.17", + "@types/node": "22.15.17", "@types/papaparse": "5.3.7", "@types/passport-google-oauth20": "2.0.16", - "@typescript-eslint/eslint-plugin": "6.21.0", - "@typescript-eslint/parser": "6.21.0", + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", "codelyzer": "6.0.1", "cypress": "6.2.1", - "eslint": "8.57.0", - "eslint-config-prettier": "9.1.0", - "eslint-plugin-cypress": "2.15.1", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-storybook": "0.6.15", + "eslint": "9.24.0", + "eslint-config-prettier": "10.1.1", + "eslint-plugin-cypress": "4.2.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-storybook": "9.0.17", "husky": "9.1.7", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "jest-preset-angular": "14.4.2", - "nx": "20.3.0", - "prettier": "3.4.2", + "jest-preset-angular": "14.6.0", + "nx": "21.3.9", + "prettier": "3.6.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.1.0", + "prisma": "6.12.0", "react": "18.2.0", "react-dom": "18.2.0", - "replace-in-file": "7.0.1", + "replace-in-file": "8.3.0", "shx": "0.3.4", - "storybook": "8.4.7", - "ts-jest": "29.1.0", + "storybook": "9.0.17", + "ts-jest": "29.4.0", "ts-node": "10.9.2", - "tslib": "2.6.0", - "typescript": "5.6.3", + "tslib": "2.8.1", + "typescript": "5.8.3", "webpack-bundle-analyzer": "4.10.2" }, "engines": { - "node": ">=20" + "node": ">=22" }, "prisma": { - "seed": "node prisma/seed.js" - }, - "resolutions": { - "rxjs": "7.5.6" + "seed": "npx ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" } } diff --git a/prisma/migrations/20250222084717_added_cusip_to_symbol_profile/migration.sql b/prisma/migrations/20250222084717_added_cusip_to_symbol_profile/migration.sql new file mode 100644 index 000000000..b60cebef6 --- /dev/null +++ b/prisma/migrations/20250222084717_added_cusip_to_symbol_profile/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "SymbolProfile" ADD COLUMN "cusip" TEXT; + +-- CreateIndex +CREATE INDEX "SymbolProfile_cusip_idx" ON "SymbolProfile"("cusip"); diff --git a/prisma/migrations/20250324072407_added_is_active_to_symbol_profile/migration.sql b/prisma/migrations/20250324072407_added_is_active_to_symbol_profile/migration.sql new file mode 100644 index 000000000..690f709df --- /dev/null +++ b/prisma/migrations/20250324072407_added_is_active_to_symbol_profile/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "SymbolProfile" ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true; + +-- CreateIndex +CREATE INDEX "SymbolProfile_isActive_idx" ON "SymbolProfile"("isActive"); diff --git a/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql b/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql new file mode 100644 index 000000000..03a4e7178 --- /dev/null +++ b/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +UPDATE "Order" SET "currency" = NULL; diff --git a/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql b/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql new file mode 100644 index 000000000..25fd35041 --- /dev/null +++ b/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "_UserWatchlist" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL, + + CONSTRAINT "_UserWatchlist_AB_pkey" PRIMARY KEY ("A","B") +); + +-- CreateIndex +CREATE INDEX "_UserWatchlist_B_index" ON "_UserWatchlist"("B"); + +-- AddForeignKey +ALTER TABLE "_UserWatchlist" ADD CONSTRAINT "_UserWatchlist_A_fkey" FOREIGN KEY ("A") REFERENCES "SymbolProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_UserWatchlist" ADD CONSTRAINT "_UserWatchlist_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20250704214021_changed_type_from_item_to_buy_in_order/migration.sql b/prisma/migrations/20250704214021_changed_type_from_item_to_buy_in_order/migration.sql new file mode 100644 index 000000000..4831beae1 --- /dev/null +++ b/prisma/migrations/20250704214021_changed_type_from_item_to_buy_in_order/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +UPDATE "Order" SET "type" = 'BUY' WHERE "type" = 'ITEM'; diff --git a/prisma/migrations/20250708090630_added_alternative_investment_to_asset_class/migration.sql b/prisma/migrations/20250708090630_added_alternative_investment_to_asset_class/migration.sql new file mode 100644 index 000000000..dceb644ff --- /dev/null +++ b/prisma/migrations/20250708090630_added_alternative_investment_to_asset_class/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AssetClass" ADD VALUE 'ALTERNATIVE_INVESTMENT'; diff --git a/prisma/migrations/20250708090631_added_collectible_to_asset_sub_class/migration.sql b/prisma/migrations/20250708090631_added_collectible_to_asset_sub_class/migration.sql new file mode 100644 index 000000000..ddfa2d9ee --- /dev/null +++ b/prisma/migrations/20250708090631_added_collectible_to_asset_sub_class/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AssetSubClass" ADD VALUE 'COLLECTIBLE'; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index fbffa92c2..044d57cdb 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index af9acebaf..609bede5c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,13 +12,13 @@ datasource db { model Access { alias String? createdAt DateTime @default(now()) + granteeUser User? @relation("accessGet", fields: [granteeUserId], onDelete: Cascade, references: [id]) granteeUserId String? id String @id @default(uuid()) permissions AccessPermission[] @default([READ_RESTRICTED]) updatedAt DateTime @updatedAt userId String - GranteeUser User? @relation("accessGet", fields: [granteeUserId], onDelete: Cascade, references: [id]) - User User @relation("accessGive", fields: [userId], onDelete: Cascade, references: [id]) + user User @relation("accessGive", fields: [userId], onDelete: Cascade, references: [id]) @@index([alias]) @@index([granteeUserId]) @@ -26,6 +26,7 @@ model Access { } model Account { + activities Order[] balance Float @default(0) balances AccountBalance[] comment String? @@ -34,12 +35,11 @@ model Account { id String @default(uuid()) isExcluded Boolean @default(false) name String? + platform Platform? @relation(fields: [platformId], references: [id]) platformId String? updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String - Platform Platform? @relation(fields: [platformId], references: [id]) - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) - Order Order[] @@id([id, userId]) @@index([currency]) @@ -50,6 +50,7 @@ model Account { } model AccountBalance { + account Account @relation(fields: [accountId, userId], onDelete: Cascade, references: [id, userId]) accountId String createdAt DateTime @default(now()) date DateTime @default(now()) @@ -57,7 +58,6 @@ model AccountBalance { updatedAt DateTime @updatedAt userId String value Float - Account Account @relation(fields: [accountId, userId], onDelete: Cascade, references: [id, userId]) @@unique([accountId, date]) @@index([accountId]) @@ -70,8 +70,8 @@ model Analytics { dataProviderGhostfolioDailyRequests Int @default(0) lastRequestAt DateTime @default(now()) updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String @id - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) @@index([lastRequestAt]) @@index([updatedAt]) @@ -82,8 +82,8 @@ model ApiKey { hashedKey String @unique id String @id @default(uuid()) updatedAt DateTime @updatedAt - userId String user User @relation(fields: [userId], onDelete: Cascade, references: [id]) + userId String @@index([userId]) } @@ -95,8 +95,8 @@ model AuthDevice { counter Int id String @id @default(uuid()) updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) @@index([userId]) } @@ -120,6 +120,7 @@ model MarketData { } model Order { + account Account? @relation(fields: [accountId, accountUserId], references: [id, userId]) accountId String? accountUserId String? comment String? @@ -131,14 +132,13 @@ model Order { isDraft Boolean @default(false) quantity Float symbolProfileId String + tags Tag[] type Type unitPrice Float updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String - Account Account? @relation(fields: [accountId, accountUserId], references: [id, userId]) SymbolProfile SymbolProfile @relation(fields: [symbolProfileId], references: [id]) - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) - tags Tag[] @@index([accountId]) @@index([date]) @@ -147,10 +147,10 @@ model Order { } model Platform { - id String @id @default(uuid()) - name String? - url String @unique - Account Account[] + accounts Account[] + id String @id @default(uuid()) + name String? + url String @unique @@index([name]) } @@ -163,23 +163,26 @@ model Property { model Settings { settings Json? updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String @id - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) } model SymbolProfile { + activities Order[] assetClass AssetClass? assetSubClass AssetSubClass? comment String? countries Json? createdAt DateTime @default(now()) currency String + cusip String? dataSource DataSource figi String? figiComposite String? figiShareClass String? holdings Json? @default("[]") id String @id @default(uuid()) + isActive Boolean @default(true) isin String? name String? updatedAt DateTime @updatedAt @@ -188,15 +191,17 @@ model SymbolProfile { symbol String symbolMapping Json? url String? + user User? @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String? - Order Order[] + watchedBy User[] @relation("UserWatchlist") SymbolProfileOverrides SymbolProfileOverrides? - User User? @relation(fields: [userId], onDelete: Cascade, references: [id]) @@unique([dataSource, symbol]) @@index([assetClass]) @@index([currency]) + @@index([cusip]) @@index([dataSource]) + @@index([isActive]) @@index([isin]) @@index([name]) @@index([symbol]) @@ -221,43 +226,44 @@ model Subscription { id String @id @default(uuid()) price Float? updatedAt DateTime @updatedAt + user User @relation(fields: [userId], onDelete: Cascade, references: [id]) userId String - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) @@index([userId]) } model Tag { - id String @id @default(uuid()) - name String - orders Order[] - userId String? - User User? @relation(fields: [userId], onDelete: Cascade, references: [id]) + activities Order[] + id String @id @default(uuid()) + name String + user User? @relation(fields: [userId], onDelete: Cascade, references: [id]) + userId String? @@unique([name, userId]) @@index([name]) } model User { + accessesGet Access[] @relation("accessGet") + accessesGive Access[] @relation("accessGive") accessToken String? + accounts Account[] + activities Order[] + analytics Analytics? + apiKeys ApiKey[] authChallenge String? + authDevices AuthDevice[] createdAt DateTime @default(now()) id String @id @default(uuid()) provider Provider @default(ANONYMOUS) role Role @default(USER) + settings Settings? + subscriptions Subscription[] + tags Tag[] thirdPartyId String? updatedAt DateTime @updatedAt - Access Access[] @relation("accessGet") - AccessGive Access[] @relation("accessGive") - Account Account[] - Analytics Analytics? - ApiKey ApiKey[] - AuthDevice AuthDevice[] - Order Order[] - Settings Settings? - Subscription Subscription[] + watchlist SymbolProfile[] @relation("UserWatchlist") SymbolProfile SymbolProfile[] - Tag Tag[] @@index([accessToken]) @@index([createdAt]) @@ -272,6 +278,7 @@ enum AccessPermission { } enum AssetClass { + ALTERNATIVE_INVESTMENT COMMODITY EQUITY FIXED_INCOME @@ -282,6 +289,7 @@ enum AssetClass { enum AssetSubClass { BOND CASH + COLLECTIBLE COMMODITY CRYPTOCURRENCY ETF diff --git a/prisma/seed.js b/prisma/seed.ts similarity index 87% rename from prisma/seed.js rename to prisma/seed.ts index beafbed44..f68f8375b 100644 --- a/prisma/seed.js +++ b/prisma/seed.ts @@ -1,4 +1,5 @@ -const { PrismaClient } = require('@prisma/client'); +import { PrismaClient } from '@prisma/client'; + const prisma = new PrismaClient(); async function main() { diff --git a/replace.build.js b/replace.build.mjs similarity index 66% rename from replace.build.js rename to replace.build.mjs index 0811fa969..1d714d7a4 100644 --- a/replace.build.js +++ b/replace.build.mjs @@ -1,9 +1,13 @@ -const dotenv = require('dotenv'); -const path = require('path'); -const replace = require('replace-in-file'); +import dotenv from 'dotenv'; +import { dirname, resolve } from 'path'; +import { replaceInFileSync } from 'replace-in-file'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); dotenv.config({ - path: path.resolve(__dirname, '.env') + path: resolve(__dirname, '.env') }); const now = new Date(); @@ -16,7 +20,7 @@ const buildTimestamp = `${formatWithTwoDigits( )}:${formatWithTwoDigits(now.getMinutes())}`; try { - const changedFiles = replace.sync({ + const changedFiles = replaceInFileSync({ files: './dist/apps/client/main.*.js', from: /{BUILD_TIMESTAMP}/g, to: buildTimestamp, diff --git a/test/import/invalid-currency.csv b/test/import/not-ok/invalid-currency.csv similarity index 100% rename from test/import/invalid-currency.csv rename to test/import/not-ok/invalid-currency.csv diff --git a/test/import/not-ok/invalid-data-source.json b/test/import/not-ok/invalid-data-source.json new file mode 100644 index 000000000..472e295ee --- /dev/null +++ b/test/import/not-ok/invalid-data-source.json @@ -0,0 +1,18 @@ +{ + "meta": { + "date": "2021-01-01T00:00:00.000Z", + "version": "dev" + }, + "activities": [ + { + "currency": "USD", + "dataSource": "", + "date": "2021-01-01T00:00:00.000Z", + "fee": 0, + "quantity": 20, + "symbol": "AAPL", + "type": "BUY", + "unitPrice": 100.0 + } + ] +} diff --git a/test/import/invalid-date-before-min.json b/test/import/not-ok/invalid-date-before-min.json similarity index 100% rename from test/import/invalid-date-before-min.json rename to test/import/not-ok/invalid-date-before-min.json diff --git a/test/import/invalid-date-yy.csv b/test/import/not-ok/invalid-date-yy.csv similarity index 100% rename from test/import/invalid-date-yy.csv rename to test/import/not-ok/invalid-date-yy.csv diff --git a/test/import/invalid-date.json b/test/import/not-ok/invalid-date.json similarity index 100% rename from test/import/invalid-date.json rename to test/import/not-ok/invalid-date.json diff --git a/test/import/invalid-fee.csv b/test/import/not-ok/invalid-fee.csv similarity index 100% rename from test/import/invalid-fee.csv rename to test/import/not-ok/invalid-fee.csv diff --git a/test/import/invalid-multi-line.csv b/test/import/not-ok/invalid-multi-line.csv similarity index 100% rename from test/import/invalid-multi-line.csv rename to test/import/not-ok/invalid-multi-line.csv diff --git a/test/import/not-ok/invalid-symbol-btc-usd.csv b/test/import/not-ok/invalid-symbol-btc-usd.csv new file mode 100644 index 000000000..d2c91be76 --- /dev/null +++ b/test/import/not-ok/invalid-symbol-btc-usd.csv @@ -0,0 +1,2 @@ +Date,Code,Currency,Price,Quantity,Action,Fee +12/12/2021,BTC-USD,USD,44558.42,1,buy,0 diff --git a/test/import/invalid-symbol.csv b/test/import/not-ok/invalid-symbol.csv similarity index 100% rename from test/import/invalid-symbol.csv rename to test/import/not-ok/invalid-symbol.csv diff --git a/test/import/invalid-symbol.json b/test/import/not-ok/invalid-symbol.json similarity index 100% rename from test/import/invalid-symbol.json rename to test/import/not-ok/invalid-symbol.json diff --git a/test/import/not-ok/invalid-type-deprecated.json b/test/import/not-ok/invalid-type-deprecated.json new file mode 100644 index 000000000..77572df85 --- /dev/null +++ b/test/import/not-ok/invalid-type-deprecated.json @@ -0,0 +1,20 @@ +{ + "meta": { + "date": "2023-02-05T00:00:00.000Z", + "version": "dev" + }, + "activities": [ + { + "accountId": null, + "comment": null, + "fee": 0, + "quantity": 1, + "type": "ITEM", + "unitPrice": 500000, + "currency": "USD", + "dataSource": "MANUAL", + "date": "2022-01-01T00:00:00.000Z", + "symbol": "Penthouse Apartment" + } + ] +} diff --git a/test/import/not-ok/invalid-type.json b/test/import/not-ok/invalid-type.json new file mode 100644 index 000000000..a23f72411 --- /dev/null +++ b/test/import/not-ok/invalid-type.json @@ -0,0 +1,18 @@ +{ + "meta": { + "date": "2021-01-01T00:00:00.000Z", + "version": "dev" + }, + "activities": [ + { + "currency": "USD", + "dataSource": "YAHOO", + "date": "2021-01-01T00:00:00.000Z", + "fee": 0, + "quantity": 20, + "symbol": "AAPL", + "type": "", + "unitPrice": 100.0 + } + ] +} diff --git a/test/import/unavailable-exchange-rate.json b/test/import/not-ok/unavailable-exchange-rate.json similarity index 100% rename from test/import/unavailable-exchange-rate.json rename to test/import/not-ok/unavailable-exchange-rate.json diff --git a/test/import/unexpected-format.json b/test/import/not-ok/unexpected-format.json similarity index 100% rename from test/import/unexpected-format.json rename to test/import/not-ok/unexpected-format.json diff --git a/test/import/ok.json b/test/import/ok.json deleted file mode 100644 index 4bce98ba2..000000000 --- a/test/import/ok.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "meta": { - "date": "2023-02-05T00:00:00.000Z", - "version": "dev" - }, - "accounts": [ - { - "balance": 2000, - "currency": "USD", - "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "isExcluded": false, - "name": "My Online Trading Account", - "platformId": null - } - ], - "activities": [ - { - "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "comment": null, - "fee": 0, - "quantity": 0, - "type": "BUY", - "unitPrice": 0, - "currency": "USD", - "dataSource": "YAHOO", - "date": "2050-06-06T00:00:00.000Z", - "symbol": "US5949181045" - }, - { - "accountId": null, - "comment": null, - "fee": 0, - "quantity": 1, - "type": "ITEM", - "unitPrice": 500000, - "currency": "USD", - "dataSource": "MANUAL", - "date": "2022-01-01T00:00:00.000Z", - "symbol": "Penthouse Apartment" - }, - { - "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "comment": null, - "fee": 0, - "quantity": 5, - "type": "DIVIDEND", - "unitPrice": 0.62, - "currency": "USD", - "dataSource": "YAHOO", - "date": "2021-11-17T00:00:00.000Z", - "symbol": "MSFT" - }, - { - "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "comment": "My first order 🤓", - "fee": 19, - "quantity": 5, - "type": "BUY", - "unitPrice": 298.58, - "currency": "USD", - "dataSource": "YAHOO", - "date": "2021-09-16T00:00:00.000Z", - "symbol": "MSFT" - }, - { - "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "comment": null, - "fee": 49, - "quantity": 0, - "type": "FEE", - "unitPrice": 0, - "currency": "USD", - "dataSource": "MANUAL", - "date": "2021-09-01T00:00:00.000Z", - "symbol": "Account Opening Fee" - } - ] -} diff --git a/test/import/ok-500-activities.json b/test/import/ok/500-activities.json similarity index 100% rename from test/import/ok-500-activities.json rename to test/import/ok/500-activities.json diff --git a/test/import/ok/btceur.json b/test/import/ok/btceur.json new file mode 100644 index 000000000..b370682f9 --- /dev/null +++ b/test/import/ok/btceur.json @@ -0,0 +1,29 @@ +{ + "meta": { + "date": "2021-12-12T00:00:00.000Z", + "version": "dev" + }, + "accounts": [], + "platforms": [], + "tags": [], + "activities": [ + { + "accountId": null, + "comment": null, + "fee": 3.94, + "quantity": 1, + "type": "BUY", + "unitPrice": 39378.5, + "currency": "EUR", + "dataSource": "YAHOO", + "date": "2021-12-12T00:00:00.000Z", + "symbol": "BTCUSD", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" + } + } +} diff --git a/test/import/ok/btcusd.csv b/test/import/ok/btcusd.csv new file mode 100644 index 000000000..8cddc1270 --- /dev/null +++ b/test/import/ok/btcusd.csv @@ -0,0 +1,2 @@ +Date,Code,Currency,Price,Quantity,Action,Fee +12/12/2021,BTCUSD,USD,44558.42,1,buy,0 diff --git a/test/import/ok/btcusd.json b/test/import/ok/btcusd.json new file mode 100644 index 000000000..fc2e1f66e --- /dev/null +++ b/test/import/ok/btcusd.json @@ -0,0 +1,29 @@ +{ + "meta": { + "date": "2021-12-12T00:00:00.000Z", + "version": "dev" + }, + "accounts": [], + "platforms": [], + "tags": [], + "activities": [ + { + "accountId": null, + "comment": null, + "fee": 4.46, + "quantity": 1, + "type": "BUY", + "unitPrice": 44558.42, + "currency": "USD", + "dataSource": "YAHOO", + "date": "2021-12-12T00:00:00.000Z", + "symbol": "BTCUSD", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" + } + } +} diff --git a/test/import/ok-derived-currency.json b/test/import/ok/derived-currency.json similarity index 100% rename from test/import/ok-derived-currency.json rename to test/import/ok/derived-currency.json diff --git a/test/import/ok-novn-buy-and-sell-partially.json b/test/import/ok/novn-buy-and-sell-partially.json similarity index 100% rename from test/import/ok-novn-buy-and-sell-partially.json rename to test/import/ok/novn-buy-and-sell-partially.json diff --git a/test/import/ok-novn-buy-and-sell.json b/test/import/ok/novn-buy-and-sell.json similarity index 100% rename from test/import/ok-novn-buy-and-sell.json rename to test/import/ok/novn-buy-and-sell.json diff --git a/test/import/ok.csv b/test/import/ok/sample.csv similarity index 81% rename from test/import/ok.csv rename to test/import/ok/sample.csv index 9f334da15..a22a4b89e 100644 --- a/test/import/ok.csv +++ b/test/import/ok/sample.csv @@ -2,5 +2,5 @@ Date,Code,DataSource,Currency,Price,Quantity,Action,Fee,Note 01-09-2021,Account Opening Fee,MANUAL,USD,0,0,fee,49, 16-09-2021,MSFT,YAHOO,USD,298.580,5,buy,19.00,My first order 🤓 17/11/2021,MSFT,YAHOO,USD,0.62,5,dividend,0.00, -01.01.2022,Penthouse Apartment,MANUAL,USD,500000.0,1,item,0.00, +01.01.2022,Penthouse Apartment,MANUAL,USD,500000.0,1,buy,0.00, 20500606,US5949181045,YAHOO,USD,0.00,0,buy,0.00, diff --git a/test/import/ok/sample.json b/test/import/ok/sample.json new file mode 100644 index 000000000..4ebb323de --- /dev/null +++ b/test/import/ok/sample.json @@ -0,0 +1,147 @@ +{ + "meta": { + "date": "2023-02-05T00:00:00.000Z", + "version": "dev" + }, + "accounts": [ + { + "balance": 2000, + "balances": [ + { + "date": "2024-12-31T00:00:00.000Z", + "value": 2000 + }, + { + "date": "2023-12-31T00:00:00.000Z", + "value": 1000 + } + ], + "comment": null, + "currency": "USD", + "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "isExcluded": false, + "name": "My Online Trading Account", + "platformId": null + } + ], + "assetProfiles": [ + { + "assetClass": null, + "assetSubClass": null, + "comment": null, + "countries": [], + "currency": "USD", + "cusip": null, + "dataSource": "MANUAL", + "figi": null, + "figiComposite": null, + "figiShareClass": null, + "holdings": [], + "isActive": true, + "isin": null, + "marketData": [], + "name": "Account Opening Fee", + "scraperConfiguration": null, + "sectors": [], + "symbol": "14a69cb9-1e31-43fa-b320-83703d8ed74b", + "symbolMapping": {}, + "url": null + }, + { + "assetClass": null, + "assetSubClass": null, + "comment": null, + "countries": [], + "currency": "USD", + "cusip": null, + "dataSource": "MANUAL", + "figi": null, + "figiComposite": null, + "figiShareClass": null, + "holdings": [], + "isActive": true, + "isin": null, + "marketData": [], + "name": "Penthouse Apartment", + "scraperConfiguration": null, + "sectors": [], + "symbol": "7e91b7d4-1430-4212-8380-289a06c9bbc1", + "symbolMapping": {}, + "url": null + } + ], + "platforms": [], + "tags": [], + "activities": [ + { + "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "comment": null, + "fee": 49, + "quantity": 0, + "type": "FEE", + "unitPrice": 0, + "currency": "USD", + "dataSource": "MANUAL", + "date": "2021-09-01T00:00:00.000Z", + "symbol": "14a69cb9-1e31-43fa-b320-83703d8ed74b", + "tags": [] + }, + { + "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "comment": "My first order 🤓", + "fee": 19, + "quantity": 5, + "type": "BUY", + "unitPrice": 298.58, + "currency": "USD", + "dataSource": "YAHOO", + "date": "2021-09-16T00:00:00.000Z", + "symbol": "MSFT", + "tags": [] + }, + { + "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "comment": null, + "fee": 0, + "quantity": 5, + "type": "DIVIDEND", + "unitPrice": 0.62, + "currency": "USD", + "dataSource": "YAHOO", + "date": "2021-11-17T00:00:00.000Z", + "symbol": "MSFT", + "tags": [] + }, + { + "accountId": null, + "comment": null, + "fee": 0, + "quantity": 1, + "type": "BUY", + "unitPrice": 500000, + "currency": "USD", + "dataSource": "MANUAL", + "date": "2022-01-01T00:00:00.000Z", + "symbol": "7e91b7d4-1430-4212-8380-289a06c9bbc1", + "tags": [] + }, + { + "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "comment": null, + "fee": 0, + "quantity": 0, + "type": "BUY", + "unitPrice": 0, + "currency": "USD", + "dataSource": "YAHOO", + "date": "2050-06-06T00:00:00.000Z", + "symbol": "MSFT", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" + } + } +} diff --git a/test/import/ok-vti-buy-long-history.json b/test/import/ok/vti-buy-long-history.json similarity index 100% rename from test/import/ok-vti-buy-long-history.json rename to test/import/ok/vti-buy-long-history.json diff --git a/test/import/ok-vti-buy-on-ibkr.csv b/test/import/ok/vti-buy-on-ibkr.csv similarity index 100% rename from test/import/ok-vti-buy-on-ibkr.csv rename to test/import/ok/vti-buy-on-ibkr.csv diff --git a/test/import/ok-without-accounts.json b/test/import/ok/without-accounts.json similarity index 97% rename from test/import/ok-without-accounts.json rename to test/import/ok/without-accounts.json index 2ba0925b1..3a5320741 100644 --- a/test/import/ok-without-accounts.json +++ b/test/import/ok/without-accounts.json @@ -17,7 +17,7 @@ { "fee": 0, "quantity": 1, - "type": "ITEM", + "type": "BUY", "unitPrice": 500000, "currency": "USD", "dataSource": "MANUAL",