diff --git a/apps/api-legacy/.env b/apps/api-legacy/.env deleted file mode 100644 index dfad708..0000000 --- a/apps/api-legacy/.env +++ /dev/null @@ -1,71 +0,0 @@ -# In all environments, the following files are loaded if they exist, -# the latter taking precedence over the former: -# -# * .env contains default values for the environment variables needed by the app -# * .env.local uncommitted file with local overrides -# * .env.$APP_ENV committed environment-specific defaults -# * .env.$APP_ENV.local uncommitted environment-specific overrides -# -# Real environment variables win over .env files. -# -# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. -# https://symfony.com/doc/current/configuration/secrets.html -# -# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). -# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration - -###> symfony/framework-bundle ### -APP_ENV=dev -APP_SECRET=f51bc23b4d778b25fcb9804bb9dfaf39 -###< symfony/framework-bundle ### - -BASANGO_CRAWLER_TOKEN=dev -BASANGO_NOTIFICATION_EMAIL= -BASANGO_TIMEZONE=Africa/Lubumbashi -BASANGO_GOOGLE_SEARCH_API_KEY= -BASANGO_NEWS_DATA_API_KEY= - -###> Devy ### -DEVY_TOKEN= -DEVY_CHANNEL= -DEVY_TOPIC=4919 -###< Devy ### - -###> symfony/mailer ### -MAILER_DSN=smtp://mailer:1025?encryption=null&auth_mode=null -###< symfony/mailer ### - -###> symfony/messenger ### -# Choose one of the transports below -# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages -# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages -MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 -###< symfony/messenger ### - -###> doctrine/doctrine-bundle ### -# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml -# -# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" -#DATABASE_URL="mysql://root:root@mariadb:3306/app?serverVersion=Mariadb-10.11.11&charset=utf8mb4" -DATABASE_URL="postgresql://postgres:postgres@postgres:5432/app?serverVersion=16&charset=utf8" -###< doctrine/doctrine-bundle ### - -###> lexik/jwt-authentication-bundle ### -JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem -JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem -JWT_PASSPHRASE=fa85ee5fac0b5ab29b4bd41927d12fd56420d28994be1738bb7e52dcf9dc163a -JWT_TTL=84600 -###< lexik/jwt-authentication-bundle ### - -###> sentry/sentry-symfony ### -SENTRY_DSN= -###< sentry/sentry-symfony ### - -###> blackfilre/blackfire ### -BLACKFIRE_SERVER_ID= -BLACKFIRE_SERVER_TOKEN= -BLACKFIRE_CLIENT_ID= -BLACKFIRE_CLIENT_TOKEN= -###< blackfire/blackfire ### diff --git a/apps/api-legacy/.env.test b/apps/api-legacy/.env.test deleted file mode 100644 index d680de7..0000000 --- a/apps/api-legacy/.env.test +++ /dev/null @@ -1,6 +0,0 @@ -# define your env variables for the test env here -KERNEL_CLASS='Basango\SharedKernel\Infrastructure\Framework\Symfony\Kernel' -APP_SECRET='$ecretf0rt3st' -SYMFONY_DEPRECATIONS_HELPER=999999 -PANTHER_APP_ENV=panther -PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots diff --git a/apps/api-legacy/.gitignore b/apps/api-legacy/.gitignore deleted file mode 100644 index 747d44e..0000000 --- a/apps/api-legacy/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -.idea -/data/ -.deptrac.cache -.nohup.out -.*.out -.DS_Store -###> symfony/framework-bundle ### -/.env.local -/.env.local.php -/.env.*.local -/config/secrets/prod/prod.decrypt.private.php -/public/bundles/ -/var/ -/vendor/ -###< symfony/framework-bundle ### - -###> phpstan/phpstan ### -phpstan.neon -###< phpstan/phpstan ### - -###> phpunit/phpunit ### -/phpunit.xml -.phpunit.result.cache -###< phpunit/phpunit ### - -###> lexik/jwt-authentication-bundle ### -/config/jwt/*.pem -###< lexik/jwt-authentication-bundle ### diff --git a/apps/api-legacy/.htaccess b/apps/api-legacy/.htaccess deleted file mode 100644 index 4ce02d0..0000000 --- a/apps/api-legacy/.htaccess +++ /dev/null @@ -1,68 +0,0 @@ - - - Header set Access-Control-Allow-Origin "*" - - - - - RewriteEngine on - RewriteOptions inherit - - # SSL and let's encrypt - RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/.+$ - RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ - RewriteRule ^.well-known/acme-challenge - [L] - - # redirect to no-www - RewriteBase / - RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] - RewriteRule ^(.*)$ http://%1/$1 [R=301,L] - - # https redirect - RewriteCond %{HTTPS} !=on - RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] - - # redirect all requests to public directory - RewriteCond %{REQUEST_URI} !public/ - RewriteRule (.*) /public/$1 [L] - - -# Enable Gzip Compression for page speed - - mod_gzip_on Yes - mod_gzip_dechunk Yes - mod_gzip_item_include file .(html?|txt|css|js|php|pl)$ - mod_gzip_item_include handler ^cgi-script$ - mod_gzip_item_include mime ^text/.* - mod_gzip_item_include mime ^application/x-javascript.* - mod_gzip_item_exclude mime ^image/.* - mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* - - -# Enable Deflate Comporession for page speed - - AddOutputFilterByType DEFLATE text/css - AddOutputFilterByType DEFLATE text/html - AddOutputFilterByType DEFLATE text/plain - AddOutputFilterByType DEFLATE text/xml - AddOutputFilterByType DEFLATE application/xml - AddOutputFilterByType DEFLATE application/xhtml+xml - AddOutputFilterByType DEFLATE application/rss+xml - AddOutputFilterByType DEFLATE application/javascript - AddOutputFilterByType DEFLATE application/x-javascript - AddOutputFilterByType DEFLATE application/vnd.ms-fontobject - AddOutputFilterByType DEFLATE application/x-font - AddOutputFilterByType DEFLATE application/x-font-opentype - AddOutputFilterByType DEFLATE application/x-font-otf - AddOutputFilterByType DEFLATE application/x-font-truetype - AddOutputFilterByType DEFLATE image/jpeg - AddOutputFilterByType DEFLATE image/png - AddOutputFilterByType DEFLATE image/gif - AddOutputFilterByType DEFLATE image/bmp - AddOutputFilterByType DEFLATE image/jpeg, - AddOutputFilterByType DEFLATE image/svg+xml - AddOutputFilterByType DEFLATE image/x-icon - AddOutputFilterByType DEFLATE audio/mpeg - AddOutputFilterByType DEFLATE audio/* - AddOutputFilterByType DEFLATE video/mp4 - diff --git a/apps/api-legacy/CHANGELOG.md b/apps/api-legacy/CHANGELOG.md deleted file mode 100644 index e6fff49..0000000 --- a/apps/api-legacy/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# CHANGELOG - -This changelog references the relevant changes (bug and security fixes) done - -## [Unreleased] -- Added: `app:stats' command to get the number of articles in the database -- Modified: use `hash` instead of `link` field as index in `articles` table -- Added: support for wp-json plugin via `WordPressJson` class -- Added: `getPagination` method to `Source` abstract class -- Added: `--parallel` option to `app:crawl` command to crawl multiple pages in parallel -- Added: `app:update` command to update the database with the latest articles -- Added: `$sep` parameter to `DateRange::from` method -- Added: support for mysql database -- Added: export to csv feature -- Removed: `--filename` option from `app:crawl` command - - -### 1.2.1 -- Added: '--page' option to 'app:crawl' command -- Added: '--date' option to 'app:crawl' command -- Added: notification by email when the crawl is finished - -### 1.0.0 -- Initial release diff --git a/apps/api-legacy/CITATION.cff b/apps/api-legacy/CITATION.cff deleted file mode 100644 index 749193f..0000000 --- a/apps/api-legacy/CITATION.cff +++ /dev/null @@ -1,38 +0,0 @@ -# This CITATION.cff file was generated with cffinit. -# Visit https://bit.ly/cffinit to generate yours today! - -cff-version: 1.2.0 -title: Basango -message: >- - If you use this software, please cite it using the - metadata from this file. -type: software -authors: - - given-names: Bernard - name-particle: Tshabu - family-names: Ngandu - email: bernard@devscast.tech - affiliation: Devscast Community - orcid: 'https://orcid.org/0009-0003-9777-6349' -repository-code: 'https://github.com/bernard-ng/basango' -repository: >- - https://www.huggingface.c0/datasets/bernard-ng/basango -abstract: >- - The "Basango" is a curated collection of news - articles sourced from major media outlets covering a wide - spectrum of topics related to the Democratic Republic of - Congo (DRC). This dataset encompasses a diverse range of - news stories, including but not limited to politics, - economy, social issues, culture, environment, and - international relations, providing comprehensive coverage - of events and developments within the country. -keywords: - - news - - datasets - - DRC - - politics - - NLP -license: CC-BY-NC-SA-4.0 -commit: b1d386986b196ae0ab637ec1a50fd992cf829d34 -version: 1.2.1 -date-released: '2024-03-31' diff --git a/apps/api-legacy/LICENSE.md b/apps/api-legacy/LICENSE.md deleted file mode 100644 index 42f5934..0000000 --- a/apps/api-legacy/LICENSE.md +++ /dev/null @@ -1,175 +0,0 @@ -## creative commons - -# Attribution-NonCommercial-ShareAlike 4.0 International - -Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. - -### Using Creative Commons Public Licenses - -Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. - -* __Considerations for licensors:__ Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors). - -* __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees). - -## Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License - -By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. - -### Section 1 – Definitions. - -a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. - -b. __Adapter's License__ means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. - -c. __BY-NC-SA Compatible License__ means a license listed at [creativecommons.org/compatiblelicenses](http://creativecommons.org/compatiblelicenses), approved by Creative Commons as essentially the equivalent of this Public License. - -d. __Copyright and Similar Rights__ means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. - -e. __Effective Technological Measures__ means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. - -f. __Exceptions and Limitations__ means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. - -g. __License Elements__ means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution, NonCommercial, and ShareAlike. - -h. __Licensed Material__ means the artistic or literary work, database, or other material to which the Licensor applied this Public License. - -i. __Licensed Rights__ means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. - -j. __Licensor__ means the individual(s) or entity(ies) granting rights under this Public License. - -k. __NonCommercial__ means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. - -l. __Share__ means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. - -m. __Sui Generis Database Rights__ means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. - -n. __You__ means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. - -### Section 2 – Scope. - -a. ___License grant.___ - -1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: - - A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and - - B. produce, reproduce, and Share Adapted Material for NonCommercial purposes only. - -2. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. - -3. __Term.__ The term of this Public License is specified in Section 6(a). - -4. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. - -5. __Downstream recipients.__ - - A. __Offer from the Licensor – Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. - - B. __Additional offer from the Licensor – Adapted Material.__ Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. - - C. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. - -6. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). - -b. ___Other rights.___ - -1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. - -2. Patent and trademark rights are not licensed under this Public License. - -3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. - -### Section 3 – License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the following conditions. - -a. ___Attribution.___ - -1. If You Share the Licensed Material (including in modified form), You must: - - A. retain the following if it is supplied by the Licensor with the Licensed Material: - - i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of warranties; - - v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; - - B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and - - C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. - -2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. - -3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. - -b. ___ShareAlike.___ - -In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. - -1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-NC-SA Compatible License. - -2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. - -3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. - -### Section 4 – Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: - -a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; - -b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and - -c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. - -### Section 5 – Disclaimer of Warranties and Limitation of Liability. - -a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__ - -b. __To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.__ - -c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. - -### Section 6 – Term and Termination. - -a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. - -b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: - -1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or - -2. upon express reinstatement by the Licensor. - -For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. - -c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. - -d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. - -### Section 7 – Other Terms and Conditions. - -a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. - -b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. - -### Section 8 – Interpretation. - -a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. - -b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. - -c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. - -d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. - -> Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. -> -> Creative Commons may be contacted at creativecommons.org diff --git a/apps/api-legacy/Makefile b/apps/api-legacy/Makefile deleted file mode 100644 index d8c1e63..0000000 --- a/apps/api-legacy/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -.PHONY: default -default: help - -# ----------------------------------- -# Variables -# ----------------------------------- -user := $(shell id -u) -group := $(shell id -g) -dc := USER_ID=$(user) GROUP_ID=$(group) docker compose -f ../../compose.yaml - -.PHONY: help -help: - @echo Tasks: - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) - -# ----------------------------------- -# Docker Compose -# ----------------------------------- -FORCE: -.PHONY: build -build: ## Build & start .docker containers for development - $(dc) build && \ - $(dc) up -d - $(dc) run --rm php composer install && \ - $(dc) run --rm php bin/console c:c - -.PHONY: ssh -ssh: ## SSH into container - $(dc) exec php bash - -.PHONY: start -start: ## Start .docker containers - $(dc) --env-file .env.local up -d - -.PHONY: restart -restart: ## Restart .docker containers - $(dc) restart - -.PHONY: stop -stop: ## Stop .docker containers - $(dc) stop - -.PHONY: logs -logs: ## Show logs of .docker containers - @$(dc) logs --tail=0 --follow - -.PHONY: destroy -destroy: ## Destroy .docker containers - $(dc) kill && \ - $(dc) rm -f - -# ----------------------------------- -# CI / CD -# ----------------------------------- -.PHONY: lint -lint: ## code quality analysis - $(dc) run --rm php composer app:cs - -.PHONY: test -test: ## unit and functional tests - $(dc) run --rm php composer app:test - #$(dc) run --rm php composer app:behat - -.PHONY: audit -audit: ## security audit - $(dc) run --rm php composer audit - -.PHONY: deploy -deploy: ## Deployment tasks - /usr/bin/php ~/composer.phar install --optimize-autoloader - /usr/bin/php bin/console doctrine:database:create --if-not-exists - /usr/bin/php bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration --all-or-nothing - /usr/bin/php bin/console cache:clear --env=prod - /usr/bin/php bin/console secrets:decrypt-to-local --env=prod - /usr/bin/php ~/composer.phar symfony:dump-env prod - -# ----------------------------------- -# Symfony -# ----------------------------------- -.PHONY: migrate -migrate: ## Run migrations - $(dc) run --rm php bin/console doctrine:databases:create --if-not-exists - $(dc) run --rm php bin/console doctrine:migrations:migrate --no-interaction - -.PHONY: cache -cache: ## Clear cache - $(dc) run --rm php bin/console cache:clear - $(dc) run --rm php bin/console cache:warmup - -# ----------------------------------- -# Dependencies -# ----------------------------------- -.PHONY: deps -deps: ## Install dependencies - $(dc) run --rm php composer install - $(dc) run --rm node yarn install --force - $(dc) run --rm node yarn build diff --git a/apps/api-legacy/README.md b/apps/api-legacy/README.md deleted file mode 100644 index 1d7590a..0000000 --- a/apps/api-legacy/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# Core and Backend - -![Deployed](https://github.com/bernard-ng/basango/actions/workflows/deploy.yaml/badge.svg) -![Coding Standard](https://github.com/bernard-ng/basango/actions/workflows/quality.yaml/badge.svg) -![Tests](https://github.com/bernard-ng/basango/actions/workflows/tests.yaml/badge.svg) -![Security](https://github.com/bernard-ng/basango/actions/workflows/audit.yaml/badge.svg) - -| Scope | Link | -|-------------------|------------------------------------------------------------| -| core and backend | https://github.com/bernard-ng/basango | -| ML models | https://github.com/bernard-ng/drc-news-ml | -| Mobile App | https://github.com/bernard-ng/basango | -| Dataset (partial) | https://huggingface.co/datasets/bernard-ng/basango | - ---- - -## Basango : Towards a scalable and intelligent system for Congolese News curation - -### Introduction - -The **"Basango"** is a structured and scalable dataset of news articles sourced from major media outlets covering diverse aspects of the Democratic Republic of Congo (DRC). Designed for efficiency, this system enables the automated collection, processing, and organization of news stories spanning politics, economy, society, culture, environment, and international affairs. - -### Scalability and Use Cases: - -This dataset is built to support large-scale text analysis, making it a valuable resource for researchers, journalists, policymakers, and data scientists. It facilitates tasks such as sentiment analysis, trend detection, entity recognition, and language modeling, providing deep insights into the evolving socio-political and economic landscape of the DRC. - -To ensure quality and reliability, the dataset prioritizes reputable news sources while maintaining an adaptable framework for continuous expansion. However, users are encouraged to critically assess the content, as journalistic standards and perspectives may vary. - -### Sources - -| Source | Articles | Link | -|----------------------|----------|--------------------------------------| -| radiookapi.net | +100k | https://www.radiookapi.net/actualite | -| mediacongo.cd | +100k | https://www.mediacongo.net/ | -| beto.cd | +30k | https://www.beto.cd/ | -| actualite.cd | +57k | https://actualite.cd/ | -| 7sur7.cd | +50k | https://7sur7.cd | -| newscd.net | +5k | https://newscd.net | -| congoindependant.com | +10k | https://www.congoindependant.com/ | -| congoactu.net | +10k | https://www.congoactu.net/ | - - -### Build the dataset -If you want to rebuild the dataset follow the steps bellow : - -#### Installation -```bash -git clone https://github.com/bernard-ng/basango.git && cd basango -make build -make start -``` - -#### Usage -See supported sources above. you can also add your own source by extending the `App/Aggregator/Infrastructure/Crawler/Source/Source` abstract class. -if you want to crawl `radiookapi.net` you can run the following command: - -##### 1. **Crawling** -```bash -php bin/console app:crawl radiookapi.net - -# You can specify a date range to crawl articles. -php bin/console app:crawl beto.cd --date="2022-01-01:2022-12-31" - -# You can specify a page range to crawl articles. -php bin/console app:crawl mediacongo.net --page="0:6" - -# You can specify both date and page range. -php bin/console app:crawl actualite.cd --date="2022-01-01:2022-12-31" --page="0:6" - -# some sources require a category to crawl articles. -php bin/console app:crawl 7sur7.cd --category=politique - -# You can crawl multiple pages in parallel (WIP - not stable). -php bin/console app:crawl radiookapi.net --parallel=20 -``` - -##### 2. **Updating** -```bash -# Update the database with the latest articles. -php bin/console app:update radiookapi.net -``` - -Notice that this can take a while depending on the number of articles you want to crawl and will store the articles in the database. -running this command in the background is recommended. by default no output is generated, you can add the `-v` option to see the progress. - -```bash -nohup php bin/console app:crawl radiookapi.net -v > crawling.log -``` - -##### 3. **Statistics** -```bash -# Get the number of articles in the database. -php bin/console app:stats -``` - -### Export the dataset -You can export the dataset to a CSV file by running the following command: - -```bash -php bin/console app:export radiookapi.net -``` - -a CSV file will be generated in the `data` directory. - - -### Acknowledgment: -The compilation and curation of the "Basango" were conducted by Tshabu Ngandu Bernard with the primary objective of facilitating research and analysis related to the Democratic Republic of Congo. -I do not own the content of the articles, and all rights belong to the respective publishers. The dataset is intended for non-commercial research purposes only. diff --git a/apps/api-legacy/api/aggregator/add-article.bru b/apps/api-legacy/api/aggregator/add-article.bru deleted file mode 100644 index 5296c3d..0000000 --- a/apps/api-legacy/api/aggregator/add-article.bru +++ /dev/null @@ -1,32 +0,0 @@ -meta { - name: add-article - type: http - seq: 1 -} - -post { - url: {{baseUrl}}/aggregator/articles?token=dev - body: json - auth: inherit -} - -params:query { - token: dev -} - -body:json { - { - "title": "test", - "body": "hello world", - "link": "https://devscast.tech", - "categories": ["a", "b"], - "source": "radiookapi.net", - "timestamp": 12, - "metadata": { - "title": "test", - "description": "some description", - "image": "https://devscast.tech/logo.svg", - "locale": "fr" - } - } -} diff --git a/apps/api-legacy/api/aggregator/folder.bru b/apps/api-legacy/api/aggregator/folder.bru deleted file mode 100644 index aaca22f..0000000 --- a/apps/api-legacy/api/aggregator/folder.bru +++ /dev/null @@ -1,8 +0,0 @@ -meta { - name: aggregator - seq: 3 -} - -auth { - mode: inherit -} diff --git a/apps/api-legacy/api/bruno.json b/apps/api-legacy/api/bruno.json deleted file mode 100644 index fc9f340..0000000 --- a/apps/api-legacy/api/bruno.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ignore": ["node_modules", ".git"], - "name": "basango", - "type": "collection", - "version": "1" -} diff --git a/apps/api-legacy/api/environments/dev.bru b/apps/api-legacy/api/environments/dev.bru deleted file mode 100644 index d6339c8..0000000 --- a/apps/api-legacy/api/environments/dev.bru +++ /dev/null @@ -1,7 +0,0 @@ -vars { - baseUrl: http://localhost:8000/api -} -vars:secret [ - token, - refreshToken -] diff --git a/apps/api-legacy/api/environments/prod.bru b/apps/api-legacy/api/environments/prod.bru deleted file mode 100644 index e326012..0000000 --- a/apps/api-legacy/api/environments/prod.bru +++ /dev/null @@ -1,7 +0,0 @@ -vars { - baseUrl: https://devscast.org/api -} -vars:secret [ - refreshToken, - token -] diff --git a/apps/api-legacy/api/feed-management/article/add-comment-to-article.bru b/apps/api-legacy/api/feed-management/article/add-comment-to-article.bru deleted file mode 100644 index acf1376..0000000 --- a/apps/api-legacy/api/feed-management/article/add-comment-to-article.bru +++ /dev/null @@ -1,25 +0,0 @@ -meta { - name: add-comment-to-article - type: http - seq: 2 -} - -post { - url: {{baseUrl}}/feed/articles/:articleId/comments - body: json - auth: bearer -} - -params:path { - articleId: 019589b9-7137-7156-9aeb-1e3f0f138a15 -} - -auth:bearer { - token: {{token}} -} - -body:json { - { - "content": "this is a comment !" - } -} diff --git a/apps/api-legacy/api/feed-management/article/article-comment-list.bru b/apps/api-legacy/api/feed-management/article/article-comment-list.bru deleted file mode 100644 index 0b566a5..0000000 --- a/apps/api-legacy/api/feed-management/article/article-comment-list.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: article-comment-list - type: http - seq: 5 -} - -get { - url: {{baseUrl}}/feed/articles/:articleId/comments - body: none - auth: bearer -} - -params:path { - articleId: 019589b9-7137-7156-9aeb-1e3f0f138a15 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/article/article-details.bru b/apps/api-legacy/api/feed-management/article/article-details.bru deleted file mode 100644 index ef18e1a..0000000 --- a/apps/api-legacy/api/feed-management/article/article-details.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: article-details - type: http - seq: 1 -} - -get { - url: {{baseUrl}}/feed/articles/:articleId - body: none - auth: bearer -} - -params:path { - articleId: 019589b9-7137-7156-9aeb-1e3f0f138a15 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/article/article-overview-list.bru b/apps/api-legacy/api/feed-management/article/article-overview-list.bru deleted file mode 100644 index f5d8883..0000000 --- a/apps/api-legacy/api/feed-management/article/article-overview-list.bru +++ /dev/null @@ -1,24 +0,0 @@ -meta { - name: article-overview-list - type: http - seq: 3 -} - -get { - url: {{baseUrl}}/feed/articles - body: none - auth: bearer -} - -params:query { - ~lastId: 019589b9-7137-7af1-96b3-9ff7427218fb - ~dateRange[start]: 1740614400 - ~dateRange[end]: 1740700800 - ~page: 22 - ~limit: 100 - ~search: Tshisekedi -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/article/folder.bru b/apps/api-legacy/api/feed-management/article/folder.bru deleted file mode 100644 index 7281727..0000000 --- a/apps/api-legacy/api/feed-management/article/folder.bru +++ /dev/null @@ -1,4 +0,0 @@ -meta { - name: article - seq: 3 -} diff --git a/apps/api-legacy/api/feed-management/article/remove-comment-from-article.bru b/apps/api-legacy/api/feed-management/article/remove-comment-from-article.bru deleted file mode 100644 index b095418..0000000 --- a/apps/api-legacy/api/feed-management/article/remove-comment-from-article.bru +++ /dev/null @@ -1,20 +0,0 @@ -meta { - name: remove-comment-from-article - type: http - seq: 4 -} - -delete { - url: {{baseUrl}}/feed/articles/:articleId/comments/:commentId - body: none - auth: bearer -} - -params:path { - commentId: 01971449-6f1b-724f-bb43-2bc0af698c5f - articleId: 019589b9-7137-7156-9aeb-1e3f0f138a15 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/add-article-to-bookmark.bru b/apps/api-legacy/api/feed-management/bookmark/add-article-to-bookmark.bru deleted file mode 100644 index b522b38..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/add-article-to-bookmark.bru +++ /dev/null @@ -1,20 +0,0 @@ -meta { - name: add-article-to-bookmark - type: http - seq: 3 -} - -post { - url: {{baseUrl}}/feed/bookmarks/:bookmarkId/articles/:articleId - body: none - auth: bearer -} - -params:path { - articleId: 01957834-0d68-7a45-9f77-39e66fd92b4f - bookmarkId: 0196d6e6-dd3b-7f46-8097-a8b260dcd2de -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/bookmark-list.bru b/apps/api-legacy/api/feed-management/bookmark/bookmark-list.bru deleted file mode 100644 index 6705ab1..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/bookmark-list.bru +++ /dev/null @@ -1,15 +0,0 @@ -meta { - name: bookmark-list - type: http - seq: 6 -} - -get { - url: {{baseUrl}}/feed/bookmarks - body: none - auth: bearer -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/bookmarked-articles-list.bru b/apps/api-legacy/api/feed-management/bookmark/bookmarked-articles-list.bru deleted file mode 100644 index 17bff3b..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/bookmarked-articles-list.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: bookmarked-articles-list - type: http - seq: 7 -} - -get { - url: {{baseUrl}}/feed/bookmarks/:bookmarkId/articles - body: none - auth: bearer -} - -params:path { - bookmarkId: 0196d6e6-dd3b-7f46-8097-a8b260dcd2de -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/create-bookmark.bru b/apps/api-legacy/api/feed-management/bookmark/create-bookmark.bru deleted file mode 100644 index d4a7096..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/create-bookmark.bru +++ /dev/null @@ -1,24 +0,0 @@ -meta { - name: create-bookmark - type: http - seq: 1 -} - -post { - url: {{baseUrl}}/feed/bookmarks - body: json - auth: bearer -} - -auth:bearer { - token: {{token}} -} - -body:json { - { - "name": "read later", - "description": null, - "isPublic": false - } - -} diff --git a/apps/api-legacy/api/feed-management/bookmark/delete-bookmark.bru b/apps/api-legacy/api/feed-management/bookmark/delete-bookmark.bru deleted file mode 100644 index 0dc0dfa..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/delete-bookmark.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: delete-bookmark - type: http - seq: 2 -} - -delete { - url: {{baseUrl}}/feed/bookmarks/:bookmarkId - body: none - auth: bearer -} - -params:path { - bookmarkId: 0196d1dc-eb76-7481-8ba5-90c73f838411 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/folder.bru b/apps/api-legacy/api/feed-management/bookmark/folder.bru deleted file mode 100644 index f8c4c91..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/folder.bru +++ /dev/null @@ -1,3 +0,0 @@ -meta { - name: bookmark -} diff --git a/apps/api-legacy/api/feed-management/bookmark/remove-article-from-bookmark.bru b/apps/api-legacy/api/feed-management/bookmark/remove-article-from-bookmark.bru deleted file mode 100644 index 784ec1b..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/remove-article-from-bookmark.bru +++ /dev/null @@ -1,20 +0,0 @@ -meta { - name: remove-article-from-bookmark - type: http - seq: 4 -} - -delete { - url: {{baseUrl}}/feed/bookmarks/:bookmarkId/articles/:articleId - body: none - auth: bearer -} - -params:path { - articleId: 019549f9-13d8-725b-81f6-3c7e75aa5a26 - bookmarkId: 0196d1dc-eb76-7481-8ba5-90c73f838411 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/bookmark/update-bookmark.bru b/apps/api-legacy/api/feed-management/bookmark/update-bookmark.bru deleted file mode 100644 index 2656c66..0000000 --- a/apps/api-legacy/api/feed-management/bookmark/update-bookmark.bru +++ /dev/null @@ -1,27 +0,0 @@ -meta { - name: update-bookmark - type: http - seq: 5 -} - -put { - url: {{baseUrl}}/feed/bookmarks/:bookmarkId - body: json - auth: bearer -} - -params:path { - bookmarkId: 0196d1dc-eb76-7481-8ba5-90c73f838411 -} - -auth:bearer { - token: {{token}} -} - -body:json { - { - "name": "updated name", - "description": "some description", - "isPublic": true - } -} diff --git a/apps/api-legacy/api/feed-management/folder.bru b/apps/api-legacy/api/feed-management/folder.bru deleted file mode 100644 index 9d9c68e..0000000 --- a/apps/api-legacy/api/feed-management/folder.bru +++ /dev/null @@ -1,3 +0,0 @@ -meta { - name: feed-management -} diff --git a/apps/api-legacy/api/feed-management/source/folder.bru b/apps/api-legacy/api/feed-management/source/folder.bru deleted file mode 100644 index a0c5603..0000000 --- a/apps/api-legacy/api/feed-management/source/folder.bru +++ /dev/null @@ -1,4 +0,0 @@ -meta { - name: source - seq: 2 -} diff --git a/apps/api-legacy/api/feed-management/source/follow-source.bru b/apps/api-legacy/api/feed-management/source/follow-source.bru deleted file mode 100644 index 11860c7..0000000 --- a/apps/api-legacy/api/feed-management/source/follow-source.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: follow-source - type: http - seq: 2 -} - -post { - url: {{baseUrl}}/feed/sources/:sourceId/follow - body: none - auth: bearer -} - -params:path { - sourceId: 01970f05-a945-7ef0-bfe3-4583491d58d2 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/source/source-article-overview-list.bru b/apps/api-legacy/api/feed-management/source/source-article-overview-list.bru deleted file mode 100644 index c6a44a4..0000000 --- a/apps/api-legacy/api/feed-management/source/source-article-overview-list.bru +++ /dev/null @@ -1,28 +0,0 @@ -meta { - name: source-article-overview-list - type: http - seq: 4 -} - -get { - url: {{baseUrl}}/feed/sources/:sourceId/articles - body: none - auth: bearer -} - -params:query { - ~lastId: 019549f9-0962-7fb5-9197-29b1754d13a5 - ~dateRange[start]: 1740614400 - ~dateRange[end]: 1740700800 - ~page: 22 - ~limit: 100 - ~search: Lubumbashi -} - -params:path { - sourceId: 01970f05-a945-7ef0-bfe3-4583491d58d2 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/source/source-details.bru b/apps/api-legacy/api/feed-management/source/source-details.bru deleted file mode 100644 index 1d11ab1..0000000 --- a/apps/api-legacy/api/feed-management/source/source-details.bru +++ /dev/null @@ -1,24 +0,0 @@ -meta { - name: source-details - type: http - seq: 1 -} - -get { - url: {{baseUrl}}/feed/sources/:sourceId - body: none - auth: bearer -} - -params:path { - sourceId: 01970f05-a945-7ef0-bfe3-4583491d58d2 -} - -headers { - accept: application/json - : -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/source/sources-overview-list.bru b/apps/api-legacy/api/feed-management/source/sources-overview-list.bru deleted file mode 100644 index 6d52801..0000000 --- a/apps/api-legacy/api/feed-management/source/sources-overview-list.bru +++ /dev/null @@ -1,26 +0,0 @@ -meta { - name: sources-overview-list - type: http - seq: 3 -} - -get { - url: {{baseUrl}}/feed/sources - body: none - auth: bearer -} - -params:query { - ~lastId: 01970f05-a945-7ef0-bfe3-45834b6bc40e - ~limit: 10 - ~page: 1 -} - -headers { - accept: application/json - : -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/feed-management/source/unfollow-source.bru b/apps/api-legacy/api/feed-management/source/unfollow-source.bru deleted file mode 100644 index 1c12ad9..0000000 --- a/apps/api-legacy/api/feed-management/source/unfollow-source.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: unfollow-source - type: http - seq: 5 -} - -delete { - url: {{baseUrl}}/feed/sources/:sourceId/unfollow - body: none - auth: bearer -} - -params:path { - sourceId: 01970f05-a945-7ef0-bfe3-4583491d58d2 -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/api/identity-and-access/account-confirm.bru b/apps/api-legacy/api/identity-and-access/account-confirm.bru deleted file mode 100644 index c037dad..0000000 --- a/apps/api-legacy/api/identity-and-access/account-confirm.bru +++ /dev/null @@ -1,15 +0,0 @@ -meta { - name: account-confirm - type: http - seq: 8 -} - -get { - url: {{baseUrl}}/account/confirm/:token - body: none - auth: none -} - -params:path { - token: WNg8QWMENL77hbCXXkrqyCtYLn5MV7ngEbSJledP9DB6V701LwDPfMJZdkn2 -} diff --git a/apps/api-legacy/api/identity-and-access/account-unlock.bru b/apps/api-legacy/api/identity-and-access/account-unlock.bru deleted file mode 100644 index b49b4fc..0000000 --- a/apps/api-legacy/api/identity-and-access/account-unlock.bru +++ /dev/null @@ -1,15 +0,0 @@ -meta { - name: account-unlock - type: http - seq: 7 -} - -get { - url: {{baseUrl}}/account/unlock/:token - body: none - auth: none -} - -params:path { - token: KFgBaXF4dxX4PtOMlrpjOoO6g1bkm6zAuvm8ocxC41LwJ27XQOHMn1J7V3kI -} diff --git a/apps/api-legacy/api/identity-and-access/login.bru b/apps/api-legacy/api/identity-and-access/login.bru deleted file mode 100644 index 3daae81..0000000 --- a/apps/api-legacy/api/identity-and-access/login.bru +++ /dev/null @@ -1,18 +0,0 @@ -meta { - name: login - type: http - seq: 1 -} - -post { - url: {{baseUrl}}/login_check - body: json - auth: none -} - -body:json { - { - "username": "bernard@devscast.tech", - "password": "#New--123pass@" - } -} diff --git a/apps/api-legacy/api/identity-and-access/logout.bru b/apps/api-legacy/api/identity-and-access/logout.bru deleted file mode 100644 index 86400c6..0000000 --- a/apps/api-legacy/api/identity-and-access/logout.bru +++ /dev/null @@ -1,15 +0,0 @@ -meta { - name: logout - type: http - seq: 10 -} - -post { - url: {{baseUrl}}/token/invalidate - body: none - auth: bearer -} - -auth:bearer { - token: -} diff --git a/apps/api-legacy/api/identity-and-access/password-request.bru b/apps/api-legacy/api/identity-and-access/password-request.bru deleted file mode 100644 index f81c66a..0000000 --- a/apps/api-legacy/api/identity-and-access/password-request.bru +++ /dev/null @@ -1,17 +0,0 @@ -meta { - name: password-request - type: http - seq: 3 -} - -post { - url: {{baseUrl}}/password/request - body: json - auth: none -} - -body:json { - { - "email": "bernard@devscast.tech" - } -} diff --git a/apps/api-legacy/api/identity-and-access/password-reset.bru b/apps/api-legacy/api/identity-and-access/password-reset.bru deleted file mode 100644 index 7a89ad7..0000000 --- a/apps/api-legacy/api/identity-and-access/password-reset.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: password-reset - type: http - seq: 4 -} - -post { - url: {{baseUrl}}/password/reset/:token - body: json - auth: none -} - -params:path { - token: qCdtZkciu7C82LVlnZhjpogfYfxUbApkHdSQmJuFQhqaINHjU2bro5uMzuY3 -} - -body:json { - { - "password": "#New--123pass@", - "confirm": "#New--123pass@" - } -} diff --git a/apps/api-legacy/api/identity-and-access/password-update.bru b/apps/api-legacy/api/identity-and-access/password-update.bru deleted file mode 100644 index a371ca6..0000000 --- a/apps/api-legacy/api/identity-and-access/password-update.bru +++ /dev/null @@ -1,23 +0,0 @@ -meta { - name: password-update - type: http - seq: 6 -} - -post { - url: {{baseUrl}}/password/update - body: json - auth: bearer -} - -auth:bearer { - token: {{token}} -} - -body:json { - { - "current": "#1231AZuu*---23213", - "password": "#New--123pass@", - "confirm": "#New--123pass@" - } -} diff --git a/apps/api-legacy/api/identity-and-access/refresh-token.bru b/apps/api-legacy/api/identity-and-access/refresh-token.bru deleted file mode 100644 index a7864b3..0000000 --- a/apps/api-legacy/api/identity-and-access/refresh-token.bru +++ /dev/null @@ -1,17 +0,0 @@ -meta { - name: refresh-token - type: http - seq: 2 -} - -post { - url: {{baseUrl}}/token/refresh - body: json - auth: none -} - -body:json { - { - "refresh_token": "{{refreshToken}}" - } -} diff --git a/apps/api-legacy/api/identity-and-access/register.bru b/apps/api-legacy/api/identity-and-access/register.bru deleted file mode 100644 index e50df27..0000000 --- a/apps/api-legacy/api/identity-and-access/register.bru +++ /dev/null @@ -1,19 +0,0 @@ -meta { - name: register - type: http - seq: 5 -} - -post { - url: {{baseUrl}}/register - body: json - auth: none -} - -body:json { - { - "name": "bernard", - "email": "bernard@devscast.org", - "password": "#New--123pass@" - } -} diff --git a/apps/api-legacy/api/identity-and-access/user-profile.bru b/apps/api-legacy/api/identity-and-access/user-profile.bru deleted file mode 100644 index 4452070..0000000 --- a/apps/api-legacy/api/identity-and-access/user-profile.bru +++ /dev/null @@ -1,15 +0,0 @@ -meta { - name: user-profile - type: http - seq: 9 -} - -get { - url: {{baseUrl}}/me - body: none - auth: bearer -} - -auth:bearer { - token: {{token}} -} diff --git a/apps/api-legacy/behat.yml b/apps/api-legacy/behat.yml deleted file mode 100644 index d1e4a34..0000000 --- a/apps/api-legacy/behat.yml +++ /dev/null @@ -1,16 +0,0 @@ -default: - suites: - default: - contexts: - - Tests\Behat\Hook\DatabasePurger - paths: - - tests/Behat/features - - formatters: - progress: true - - extensions: - FriendsOfBehat\SymfonyExtension: - bootstrap: tests/bootstrap.php - kernel: - class: Basango\SharedKernel\Infrastructure\Framework\Symfony\Kernel diff --git a/apps/api-legacy/bin/backup.sh b/apps/api-legacy/bin/backup.sh deleted file mode 100644 index 638c197..0000000 --- a/apps/api-legacy/bin/backup.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -# Get the script directory and define data directory -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -DATA_DIR="${SCRIPT_DIR}/../data" -DUMP_FILE="${DATA_DIR}/data.sql" -ARCHIVE_FILE="${DUMP_FILE}.gz" - -# Ensure data directory exists -mkdir -p "$DATA_DIR" - -# Load environment variables from .env.local -set -a -if [ -f "${SCRIPT_DIR}/../.env.local" ]; then - export "$(grep -v '^#' "${SCRIPT_DIR}/../.env.local" | grep '=' | xargs)" -fi -set +a - -# Parse DATABASE_URL into components -if [[ -z "$DATABASE_URL" ]]; then - echo "DATABASE_URL is not set in .env.local" - exit 1 -fi - -regex="^mysql:\/\/([^:]+):([^@]+)@([^:]+):([0-9]+)\/([^?]+)" -if [[ "$DATABASE_URL" =~ $regex ]]; then - DB_USER="${BASH_REMATCH[1]}" - DB_PASSWORD="${BASH_REMATCH[2]}" - DB_HOST="${BASH_REMATCH[3]}" - DB_PORT="${BASH_REMATCH[4]}" - DB_NAME="${BASH_REMATCH[5]}" -else - echo "Invalid DATABASE_URL format" - exit 1 -fi - -# Step 1: Dump the database -mysqldump --host="${DB_HOST}" --port="${DB_PORT}" \ - --user="${DB_USER}" --password="${DB_PASSWORD}" \ - --max_allowed-packet=1G --net-buffer-length=32704 --skip-extended-insert \ - "${DB_NAME}" > "$DUMP_FILE" - -gzip -f "$DUMP_FILE" - -# Step 2: Send the file to Telegram -curl -F "chat_id=${DEVY_CHANNEL}" \ - -F "message_thread_id=${DEVY_TOPIC}" \ - -F "document=@${ARCHIVE_FILE}" \ - "https://api.telegram.org/bot${DEVY_TOKEN}/sendDocument" - -# Step 3: Clean up -rm -f "$ARCHIVE_FILE" "$DUMP_FILE" diff --git a/apps/api-legacy/bin/console b/apps/api-legacy/bin/console deleted file mode 100644 index 2114f1f..0000000 --- a/apps/api-legacy/bin/console +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env php -=8.4", - "phpdocumentor/reflection-docblock": "^5.6", - "phpstan/phpdoc-parser": "^2.1", - "sentry/sentry-symfony": "^5.2", - "symfony/console": "7.2.*", - "symfony/css-selector": "7.2.*", - "symfony/dom-crawler": "7.2.*", - "symfony/dotenv": "7.2.*", - "symfony/flex": "^2.4.7", - "symfony/framework-bundle": "7.2.*", - "symfony/http-client": "7.2.*", - "symfony/mailer": "7.2.*", - "symfony/messenger": "7.2.*", - "symfony/monolog-bundle": "^3.10", - "symfony/property-access": "7.2.*", - "symfony/property-info": "7.2.*", - "symfony/runtime": "7.2.*", - "symfony/security-bundle": "7.2.*", - "symfony/serializer": "7.2.*", - "symfony/stopwatch": "7.2.*", - "symfony/twig-bundle": "7.2.*", - "symfony/uid": "7.2.*", - "symfony/validator": "7.2.*", - "symfony/yaml": "7.2.*", - "twig/extra-bundle": "^2.12|^3.19", - "twig/twig": "^2.12|^3.19", - "webmozart/assert": "^1.11" - }, - "require-dev": { - "behat/behat": "^3.22", - "deptrac/deptrac": "^2.0.7", - "doctrine/doctrine-fixtures-bundle": "^4.1", - "friends-of-behat/symfony-extension": "^2.6", - "phpstan/phpstan": "^2.1.12", - "phpstan/phpstan-doctrine": "^2.0", - "phpstan/phpstan-symfony": "^2.0", - "phpunit/phpunit": "^12.1.1", - "rector/rector": "^2.0.12", - "shipmonk/composer-dependency-analyser": "^1.8.2", - "symfony/maker-bundle": "^1.62.1", - "symfony/web-profiler-bundle": "7.2.*", - "symplify/easy-coding-standard": "^12.1.13", - "tomasvotruba/class-leak": "^1.2.7" - }, - "scripts": { - "app:behat": [ - "APP_ENV=test bin/console doctrine:database:create", - "APP_ENV=test bin/console doctrine:migration:migrate --no-interaction --allow-no-migration --all-or-nothing", - "APP_ENV=test ./vendor/bin/behat --format=progress --no-interaction" - ], - "app:cs": [ - "./vendor/bin/ecs check", - "bin/console lint:yaml config --parse-tags", - "bin/console lint:twig templates", - "bin/console lint:container", - "./vendor/bin/phpstan analyse --memory-limit=-1 --configuration=phpstan.dist.neon", - "./vendor/bin/rector --dry-run" - ], - "app:env": [ - "APP_RUNTIME_ENV=prod bin/console secrets:decrypt-to-local --force", - "bin/console dotenv:dump prod" - ], - "app:tests": ["APP_ENV=test ./vendor/bin/phpunit"], - "auto-scripts": { - "assets:install %PUBLIC_DIR%": "symfony-cmd", - "cache:clear": "symfony-cmd" - }, - "post-install-cmd": ["@auto-scripts"], - "post-update-cmd": ["@auto-scripts"] - }, - "type": "project" -} diff --git a/apps/api-legacy/composer.lock b/apps/api-legacy/composer.lock deleted file mode 100644 index 410fba7..0000000 --- a/apps/api-legacy/composer.lock +++ /dev/null @@ -1,11632 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "2629764bb519b7236ab2236acc4fee1d", - "packages": [ - { - "name": "composer/ca-bundle", - "version": "1.5.8", - "source": { - "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "719026bb30813accb68271fee7e39552a58e9f65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/719026bb30813accb68271fee7e39552a58e9f65", - "reference": "719026bb30813accb68271fee7e39552a58e9f65", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8 || ^9", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.8" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - } - ], - "time": "2025-08-20T18:49:47+00:00" - }, - { - "name": "cweagans/composer-patches", - "version": "1.7.3", - "source": { - "type": "git", - "url": "https://github.com/cweagans/composer-patches.git", - "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db", - "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3.0" - }, - "require-dev": { - "composer/composer": "~1.0 || ~2.0", - "phpunit/phpunit": "~4.6" - }, - "type": "composer-plugin", - "extra": { - "class": "cweagans\\Composer\\Patches" - }, - "autoload": { - "psr-4": { - "cweagans\\Composer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Cameron Eagans", - "email": "me@cweagans.net" - } - ], - "description": "Provides a way to patch Composer packages.", - "support": { - "issues": "https://github.com/cweagans/composer-patches/issues", - "source": "https://github.com/cweagans/composer-patches/tree/1.7.3" - }, - "time": "2022-12-20T22:53:13+00:00" - }, - { - "name": "doctrine/collections", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d", - "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1", - "php": "^8.1", - "symfony/polyfill-php84": "^1.30" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "ext-json": "*", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Collections\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", - "homepage": "https://www.doctrine-project.org/projects/collections.html", - "keywords": [ - "array", - "collections", - "iterators", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.3.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections", - "type": "tidelift" - } - ], - "time": "2025-03-22T10:17:19+00:00" - }, - { - "name": "doctrine/dbal", - "version": "3.10.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/c6c16cf787eaba3112203dfcd715fa2059c62282", - "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/deprecations": "^0.5.3|^1", - "doctrine/event-manager": "^1|^2", - "php": "^7.4 || ^8.0", - "psr/cache": "^1|^2|^3", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "doctrine/cache": "< 1.11" - }, - "require-dev": { - "doctrine/cache": "^1.11|^2.0", - "doctrine/coding-standard": "13.0.1", - "fig/log-test": "^1", - "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "2.1.22", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "9.6.23", - "slevomat/coding-standard": "8.16.2", - "squizlabs/php_codesniffer": "3.13.1", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", - "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlite", - "sqlserver", - "sqlsrv" - ], - "support": { - "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.10.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", - "type": "tidelift" - } - ], - "time": "2025-09-04T23:51:27+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", - "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", - "psr/log": "^1 || ^2 || ^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" - }, - "time": "2025-04-07T20:06:18+00:00" - }, - { - "name": "doctrine/doctrine-bundle", - "version": "2.16.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "1c10de0fe995f01eca6b073d1c2549ef0b603a7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/1c10de0fe995f01eca6b073d1c2549ef0b603a7f", - "reference": "1c10de0fe995f01eca6b073d1c2549ef0b603a7f", - "shasum": "" - }, - "require": { - "doctrine/dbal": "^3.7.0 || ^4.0", - "doctrine/persistence": "^3.1 || ^4", - "doctrine/sql-formatter": "^1.0.1", - "php": "^8.1", - "symfony/cache": "^6.4 || ^7.0", - "symfony/config": "^6.4 || ^7.0", - "symfony/console": "^6.4 || ^7.0", - "symfony/dependency-injection": "^6.4 || ^7.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3", - "symfony/framework-bundle": "^6.4 || ^7.0", - "symfony/service-contracts": "^2.5 || ^3" - }, - "conflict": { - "doctrine/annotations": ">=3.0", - "doctrine/cache": "< 1.11", - "doctrine/orm": "<2.17 || >=4.0", - "symfony/var-exporter": "< 6.4.1 || 7.0.0", - "twig/twig": "<2.13 || >=3.0 <3.0.4" - }, - "require-dev": { - "doctrine/annotations": "^1 || ^2", - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^13", - "doctrine/deprecations": "^1.0", - "doctrine/orm": "^2.17 || ^3.1", - "friendsofphp/proxy-manager-lts": "^1.0", - "phpstan/phpstan": "2.1.1", - "phpstan/phpstan-phpunit": "2.0.3", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^10.5.53", - "psr/log": "^1.1.4 || ^2.0 || ^3.0", - "symfony/doctrine-messenger": "^6.4 || ^7.0", - "symfony/expression-language": "^6.4 || ^7.0", - "symfony/messenger": "^6.4 || ^7.0", - "symfony/property-info": "^6.4 || ^7.0", - "symfony/security-bundle": "^6.4 || ^7.0", - "symfony/stopwatch": "^6.4 || ^7.0", - "symfony/string": "^6.4 || ^7.0", - "symfony/twig-bridge": "^6.4 || ^7.0", - "symfony/validator": "^6.4 || ^7.0", - "symfony/var-exporter": "^6.4.1 || ^7.0.1", - "symfony/web-profiler-bundle": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0", - "twig/twig": "^2.13 || ^3.0.4" - }, - "suggest": { - "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", - "ext-pdo": "*", - "symfony/web-profiler-bundle": "To use the data collector." - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\DoctrineBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Doctrine Project", - "homepage": "https://www.doctrine-project.org/" - } - ], - "description": "Symfony DoctrineBundle", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "orm", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.16.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", - "type": "tidelift" - } - ], - "time": "2025-09-10T19:14:48+00:00" - }, - { - "name": "doctrine/doctrine-migrations-bundle", - "version": "3.4.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/5a6ac7120c2924c4c070a869d08b11ccf9e277b9", - "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9", - "shasum": "" - }, - "require": { - "doctrine/doctrine-bundle": "^2.4", - "doctrine/migrations": "^3.2", - "php": "^7.2 || ^8.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" - }, - "require-dev": { - "composer/semver": "^3.0", - "doctrine/coding-standard": "^12", - "doctrine/orm": "^2.6 || ^3", - "phpstan/phpstan": "^1.4 || ^2", - "phpstan/phpstan-deprecation-rules": "^1 || ^2", - "phpstan/phpstan-phpunit": "^1 || ^2", - "phpstan/phpstan-strict-rules": "^1.1 || ^2", - "phpstan/phpstan-symfony": "^1.3 || ^2", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/phpunit-bridge": "^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6 || ^7" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\MigrationsBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Doctrine Project", - "homepage": "https://www.doctrine-project.org" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DoctrineMigrationsBundle", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "dbal", - "migrations", - "schema" - ], - "support": { - "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.4.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", - "type": "tidelift" - } - ], - "time": "2025-03-11T17:36:26+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", - "type": "tidelift" - } - ], - "time": "2024-05-22T20:47:39+00:00" - }, - { - "name": "doctrine/inflector", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^12.0 || ^13.0", - "phpstan/phpstan": "^1.12 || ^2.0", - "phpstan/phpstan-phpunit": "^1.4 || ^2.0", - "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", - "phpunit/phpunit": "^8.5 || ^12.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Inflector\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", - "homepage": "https://www.doctrine-project.org/projects/inflector.html", - "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", - "php", - "plural", - "singular", - "strings", - "uppercase", - "words" - ], - "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", - "type": "tidelift" - } - ], - "time": "2025-08-10T19:31:58+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, - { - "name": "doctrine/lexer", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2024-02-05T11:56:58+00:00" - }, - { - "name": "doctrine/migrations", - "version": "3.9.4", - "source": { - "type": "git", - "url": "https://github.com/doctrine/migrations.git", - "reference": "1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c", - "reference": "1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/dbal": "^3.6 || ^4", - "doctrine/deprecations": "^0.5.3 || ^1", - "doctrine/event-manager": "^1.2 || ^2.0", - "php": "^8.1", - "psr/log": "^1.1.3 || ^2 || ^3", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^6.2 || ^7.0" - }, - "conflict": { - "doctrine/orm": "<2.12 || >=4" - }, - "require-dev": { - "doctrine/coding-standard": "^13", - "doctrine/orm": "^2.13 || ^3", - "doctrine/persistence": "^2 || ^3 || ^4", - "doctrine/sql-formatter": "^1.0", - "ext-pdo_sqlite": "*", - "fig/log-test": "^1", - "phpstan/phpstan": "^2", - "phpstan/phpstan-deprecation-rules": "^2", - "phpstan/phpstan-phpunit": "^2", - "phpstan/phpstan-strict-rules": "^2", - "phpstan/phpstan-symfony": "^2", - "phpunit/phpunit": "^10.3 || ^11.0 || ^12.0", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" - }, - "suggest": { - "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", - "symfony/yaml": "Allows the use of yaml for migration configuration files." - }, - "bin": [ - "bin/doctrine-migrations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Migrations\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Michael Simonson", - "email": "contact@mikesimonson.com" - } - ], - "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", - "homepage": "https://www.doctrine-project.org/projects/migrations.html", - "keywords": [ - "database", - "dbal", - "migrations" - ], - "support": { - "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.4" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", - "type": "tidelift" - } - ], - "time": "2025-08-19T06:41:07+00:00" - }, - { - "name": "doctrine/orm", - "version": "3.5.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/orm.git", - "reference": "5a541b8b3a327ab1ea5f93b1615b4ff67a34e109" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/5a541b8b3a327ab1ea5f93b1615b4ff67a34e109", - "reference": "5a541b8b3a327ab1ea5f93b1615b4ff67a34e109", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/collections": "^2.2", - "doctrine/dbal": "^3.8.2 || ^4", - "doctrine/deprecations": "^0.5.3 || ^1", - "doctrine/event-manager": "^1.2 || ^2", - "doctrine/inflector": "^1.4 || ^2.0", - "doctrine/instantiator": "^1.3 || ^2", - "doctrine/lexer": "^3", - "doctrine/persistence": "^3.3.1 || ^4", - "ext-ctype": "*", - "php": "^8.1", - "psr/cache": "^1 || ^2 || ^3", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^6.3.9 || ^7.0" - }, - "require-dev": { - "doctrine/coding-standard": "^13.0", - "phpbench/phpbench": "^1.0", - "phpdocumentor/guides-cli": "^1.4", - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "2.0.3", - "phpstan/phpstan-deprecation-rules": "^2", - "phpunit/phpunit": "^10.4.0", - "psr/log": "^1 || ^2 || ^3", - "squizlabs/php_codesniffer": "3.12.0", - "symfony/cache": "^5.4 || ^6.2 || ^7.0" - }, - "suggest": { - "ext-dom": "Provides support for XSD validation for XML mapping files", - "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\ORM\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Object-Relational-Mapper for PHP", - "homepage": "https://www.doctrine-project.org/projects/orm.html", - "keywords": [ - "database", - "orm" - ], - "support": { - "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.5.2" - }, - "time": "2025-08-08T17:00:40+00:00" - }, - { - "name": "doctrine/persistence", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "dcbdfe4b211ae09478e192289cae7ab0987b29a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/dcbdfe4b211ae09478e192289cae7ab0987b29a4", - "reference": "dcbdfe4b211ae09478e192289cae7ab0987b29a4", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "^1 || ^2", - "php": "^8.1", - "psr/cache": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "1.12.7", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "^9.6", - "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0", - "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Persistence\\": "src/Persistence" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://www.doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/4.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", - "type": "tidelift" - } - ], - "time": "2025-08-21T16:00:31+00:00" - }, - { - "name": "doctrine/sql-formatter", - "version": "1.5.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8", - "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "ergebnis/phpunit-slow-test-detector": "^2.14", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5" - }, - "bin": [ - "bin/sql-formatter" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\SqlFormatter\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "https://jeremydorn.com/" - } - ], - "description": "a PHP SQL highlighting library", - "homepage": "https://github.com/doctrine/sql-formatter/", - "keywords": [ - "highlight", - "sql" - ], - "support": { - "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2" - }, - "time": "2025-01-24T11:45:48+00:00" - }, - { - "name": "egulias/email-validator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/egulias/EmailValidator.git", - "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", - "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2.0 || ^3.0", - "php": ">=8.1", - "symfony/polyfill-intl-idn": "^1.26" - }, - "require-dev": { - "phpunit/phpunit": "^10.2", - "vimeo/psalm": "^5.12" - }, - "suggest": { - "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Egulias\\EmailValidator\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Eduardo Gulias Davis" - } - ], - "description": "A library for validating emails against several RFCs", - "homepage": "https://github.com/egulias/EmailValidator", - "keywords": [ - "email", - "emailvalidation", - "emailvalidator", - "validation", - "validator" - ], - "support": { - "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/egulias", - "type": "github" - } - ], - "time": "2025-03-06T22:45:56+00:00" - }, - { - "name": "geoip2/geoip2", - "version": "v3.2.0", - "source": { - "type": "git", - "url": "https://github.com/maxmind/GeoIP2-php.git", - "reference": "b7aa58760a6bf89a608dd92ee2d9436b52557ce2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/b7aa58760a6bf89a608dd92ee2d9436b52557ce2", - "reference": "b7aa58760a6bf89a608dd92ee2d9436b52557ce2", - "shasum": "" - }, - "require": { - "ext-json": "*", - "maxmind-db/reader": "^1.12.1", - "maxmind/web-service-common": "~0.10", - "php": ">=8.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "3.*", - "phpstan/phpstan": "*", - "phpunit/phpunit": "^10.0", - "squizlabs/php_codesniffer": "3.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "GeoIp2\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Gregory J. Oschwald", - "email": "goschwald@maxmind.com", - "homepage": "https://www.maxmind.com/" - } - ], - "description": "MaxMind GeoIP2 PHP API", - "homepage": "https://github.com/maxmind/GeoIP2-php", - "keywords": [ - "IP", - "geoip", - "geoip2", - "geolocation", - "maxmind" - ], - "support": { - "issues": "https://github.com/maxmind/GeoIP2-php/issues", - "source": "https://github.com/maxmind/GeoIP2-php/tree/v3.2.0" - }, - "time": "2025-05-05T21:18:27+00:00" - }, - { - "name": "gesdinet/jwt-refresh-token-bundle", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/markitosgv/JWTRefreshTokenBundle.git", - "reference": "8706b0d8dcb26610358ba3328ec412315b55c3cd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/markitosgv/JWTRefreshTokenBundle/zipball/8706b0d8dcb26610358ba3328ec412315b55c3cd", - "reference": "8706b0d8dcb26610358ba3328ec412315b55c3cd", - "shasum": "" - }, - "require": { - "doctrine/persistence": "^1.3.3|^2.0|^3.0|^4.0", - "lexik/jwt-authentication-bundle": "^2.0|^3.0", - "php": ">=7.4", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/deprecation-contracts": "^2.1|^3.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/polyfill-php80": "^1.15", - "symfony/property-access": "^5.4|^6.0|^7.0", - "symfony/security-bundle": "^5.4|^6.0|^7.0", - "symfony/security-core": "^5.4|^6.0|^7.0", - "symfony/security-http": "^5.4|^6.0|^7.0" - }, - "conflict": { - "doctrine/mongodb-odm": "<2.2", - "doctrine/orm": "<2.7" - }, - "require-dev": { - "doctrine/annotations": "^1.13|^2.0", - "doctrine/cache": "^1.11|^2.0", - "doctrine/mongodb-odm": "^2.2", - "doctrine/orm": "^2.7|^3.0", - "matthiasnoback/symfony-config-test": "^4.2|^5.0", - "matthiasnoback/symfony-dependency-injection-test": "^4.2|^5.0", - "phpunit/phpunit": "^9.5", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/security-guard": "^5.4" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Gesdinet\\JWTRefreshTokenBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marcos Gómez Vilches", - "email": "marcos@gesdinet.com" - } - ], - "description": "Implements a refresh token system over Json Web Tokens in Symfony", - "keywords": [ - "jwt refresh token bundle symfony json web" - ], - "support": { - "issues": "https://github.com/markitosgv/JWTRefreshTokenBundle/issues", - "source": "https://github.com/markitosgv/JWTRefreshTokenBundle/tree/v1.5.0" - }, - "time": "2025-06-24T13:08:37+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "time": "2025-08-23T21:21:41+00:00" - }, - { - "name": "jean85/pretty-package-versions", - "version": "2.1.1", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1.0", - "php": "^7.4|^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^7.5|^8.5|^9.6", - "rector/rector": "^2.0", - "vimeo/psalm": "^4.3 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A library to get pretty versions strings of installed dependencies", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "support": { - "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1" - }, - "time": "2025-03-19T14:43:43+00:00" - }, - { - "name": "knplabs/knp-components", - "version": "v5.2.0", - "source": { - "type": "git", - "url": "https://github.com/KnpLabs/knp-components.git", - "reference": "eabf39263fff305c0024820c3736e5b03e7edf50" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/eabf39263fff305c0024820c3736e5b03e7edf50", - "reference": "eabf39263fff305c0024820c3736e5b03e7edf50", - "shasum": "" - }, - "require": { - "php": "^8.1", - "symfony/event-dispatcher-contracts": "^3.0" - }, - "conflict": { - "doctrine/dbal": "<3.8" - }, - "require-dev": { - "doctrine/dbal": "^3.8 || ^4.0", - "doctrine/mongodb-odm": "^2.5.5", - "doctrine/orm": "^2.13 || ^3.0", - "doctrine/phpcr-odm": "^1.8 || ^2.0", - "ext-pdo_sqlite": "*", - "jackalope/jackalope-doctrine-dbal": "^1.12 || ^2.0", - "phpunit/phpunit": "^10.5 || ^11.3", - "propel/propel1": "^1.7", - "ruflin/elastica": "^7.0", - "solarium/solarium": "^6.0", - "symfony/http-foundation": "^5.4.38 || ^6.4.4 || ^7.0", - "symfony/http-kernel": "^5.4.38 || ^6.4.4 || ^7.0", - "symfony/property-access": "^5.4.38 || ^6.4.4 || ^7.0" - }, - "suggest": { - "doctrine/common": "to allow usage pagination with Doctrine ArrayCollection", - "doctrine/mongodb-odm": "to allow usage pagination with Doctrine ODM MongoDB", - "doctrine/orm": "to allow usage pagination with Doctrine ORM", - "doctrine/phpcr-odm": "to allow usage pagination with Doctrine ODM PHPCR", - "propel/propel1": "to allow usage pagination with Propel ORM", - "ruflin/elastica": "to allow usage pagination with ElasticSearch Client", - "solarium/solarium": "to allow usage pagination with Solarium Client", - "symfony/http-foundation": "to retrieve arguments from Request", - "symfony/property-access": "to allow sorting arrays" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Knp\\Component\\": "src/Knp/Component" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "KnpLabs Team", - "homepage": "https://knplabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://github.com/KnpLabs/knp-components/contributors" - } - ], - "description": "Knplabs component library", - "homepage": "https://github.com/KnpLabs/knp-components", - "keywords": [ - "components", - "knp", - "knplabs", - "pager", - "paginator" - ], - "support": { - "issues": "https://github.com/KnpLabs/knp-components/issues", - "source": "https://github.com/KnpLabs/knp-components/tree/v5.2.0" - }, - "time": "2025-03-20T07:35:37+00:00" - }, - { - "name": "knplabs/knp-paginator-bundle", - "version": "v6.9.1", - "source": { - "type": "git", - "url": "https://github.com/KnpLabs/KnpPaginatorBundle.git", - "reference": "9bf5212f01ca316ef8fe42208e00685e8b6ffa69" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpPaginatorBundle/zipball/9bf5212f01ca316ef8fe42208e00685e8b6ffa69", - "reference": "9bf5212f01ca316ef8fe42208e00685e8b6ffa69", - "shasum": "" - }, - "require": { - "knplabs/knp-components": "^4.4 || ^5.0", - "php": "^8.1", - "symfony/config": "^6.4 || ^7.0", - "symfony/dependency-injection": "^6.4 || ^7.0", - "symfony/event-dispatcher": "^6.4 || ^7.0", - "symfony/http-foundation": "^6.4 || ^7.0", - "symfony/http-kernel": "^6.4 || ^7.0", - "symfony/routing": "^6.4 || ^7.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.12", - "phpunit/phpunit": "^10.5 || ^11.5 || ^12.0", - "symfony/templating": "^6.4 || ^7.0", - "symfony/translation": "^6.4 || ^7.0", - "twig/twig": "^3.0" - }, - "suggest": { - "symfony/translation": "To use the templates", - "twig/twig": "To use the templates" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Knp\\Bundle\\PaginatorBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "KnpLabs Team", - "homepage": "https://knplabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://github.com/KnpLabs/KnpPaginatorBundle/contributors" - } - ], - "description": "Paginator bundle for Symfony to automate pagination and simplify sorting and other features", - "homepage": "https://github.com/KnpLabs/KnpPaginatorBundle", - "keywords": [ - "bundle", - "knp", - "knplabs", - "pager", - "pagination", - "paginator", - "symfony" - ], - "support": { - "issues": "https://github.com/KnpLabs/KnpPaginatorBundle/issues", - "source": "https://github.com/KnpLabs/KnpPaginatorBundle/tree/v6.9.1" - }, - "time": "2025-07-25T07:53:13+00:00" - }, - { - "name": "lcobucci/clock", - "version": "3.3.1", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "shasum": "" - }, - "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.29", - "lcobucci/coding-standard": "^11.1.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.10.25", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^11.3.6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.3.1" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2024-09-24T20:45:14+00:00" - }, - { - "name": "lcobucci/jwt", - "version": "5.5.0", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/jwt.git", - "reference": "a835af59b030d3f2967725697cf88300f579088e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", - "reference": "a835af59b030d3f2967725697cf88300f579088e", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-sodium": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "psr/clock": "^1.0" - }, - "require-dev": { - "infection/infection": "^0.29", - "lcobucci/clock": "^3.2", - "lcobucci/coding-standard": "^11.0", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.10.7", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.10", - "phpstan/phpstan-strict-rules": "^1.5.0", - "phpunit/phpunit": "^11.1" - }, - "suggest": { - "lcobucci/clock": ">= 3.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com", - "role": "Developer" - } - ], - "description": "A simple library to work with JSON Web Token and JSON Web Signature", - "keywords": [ - "JWS", - "jwt" - ], - "support": { - "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.5.0" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2025-01-26T21:29:45+00:00" - }, - { - "name": "league/csv", - "version": "9.26.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/csv.git", - "reference": "7fce732754d043f3938899e5183e2d0f3d31b571" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/7fce732754d043f3938899e5183e2d0f3d31b571", - "reference": "7fce732754d043f3938899e5183e2d0f3d31b571", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^8.1.2" - }, - "require-dev": { - "ext-dom": "*", - "ext-xdebug": "*", - "friendsofphp/php-cs-fixer": "^3.75.0", - "phpbench/phpbench": "^1.4.1", - "phpstan/phpstan": "^1.12.27", - "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.2", - "phpstan/phpstan-strict-rules": "^1.6.2", - "phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.3.6", - "symfony/var-dumper": "^6.4.8 || ^7.3.0" - }, - "suggest": { - "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", - "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters", - "ext-mbstring": "Needed to ease transcoding CSV using mb stream filters", - "ext-mysqli": "Requiered to use the package with the MySQLi extension", - "ext-pdo": "Required to use the package with the PDO extension", - "ext-pgsql": "Requiered to use the package with the PgSQL extension", - "ext-sqlite3": "Required to use the package with the SQLite3 extension" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "League\\Csv\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://github.com/nyamsprod/", - "role": "Developer" - } - ], - "description": "CSV data manipulation made easy in PHP", - "homepage": "https://csv.thephpleague.com", - "keywords": [ - "convert", - "csv", - "export", - "filter", - "import", - "read", - "transform", - "write" - ], - "support": { - "docs": "https://csv.thephpleague.com", - "issues": "https://github.com/thephpleague/csv/issues", - "rss": "https://github.com/thephpleague/csv/releases.atom", - "source": "https://github.com/thephpleague/csv" - }, - "funding": [ - { - "url": "https://github.com/sponsors/nyamsprod", - "type": "github" - } - ], - "time": "2025-10-01T11:24:54+00:00" - }, - { - "name": "lexik/jwt-authentication-bundle", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/lexik/LexikJWTAuthenticationBundle.git", - "reference": "ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lexik/LexikJWTAuthenticationBundle/zipball/ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61", - "reference": "ebe0e2c6a0ae17b4702feffc89e32e3aaba6cb61", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "lcobucci/clock": "^3.0", - "lcobucci/jwt": "^5.0", - "php": ">=8.2", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.4|^3.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/security-bundle": "^6.4|^7.0", - "symfony/translation-contracts": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "api-platform/core": "^3.0|^4.0", - "rector/rector": "^1.2", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "suggest": { - "gesdinet/jwt-refresh-token-bundle": "Implements a refresh token system over Json Web Tokens in Symfony", - "spomky-labs/lexik-jose-bridge": "Provides a JWT Token encoder with encryption support" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Lexik\\Bundle\\JWTAuthenticationBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Barthe", - "email": "j.barthe@lexik.fr", - "homepage": "https://github.com/jeremyb" - }, - { - "name": "Nicolas Cabot", - "email": "n.cabot@lexik.fr", - "homepage": "https://github.com/slashfan" - }, - { - "name": "Cedric Girard", - "email": "c.girard@lexik.fr", - "homepage": "https://github.com/cedric-g" - }, - { - "name": "Dev Lexik", - "email": "dev@lexik.fr", - "homepage": "https://github.com/lexik" - }, - { - "name": "Robin Chalas", - "email": "robin.chalas@gmail.com", - "homepage": "https://github.com/chalasr" - }, - { - "name": "Lexik Community", - "homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle/graphs/contributors" - } - ], - "description": "This bundle provides JWT authentication for your Symfony REST API", - "homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle", - "keywords": [ - "Authentication", - "JWS", - "api", - "bundle", - "jwt", - "rest", - "symfony" - ], - "support": { - "issues": "https://github.com/lexik/LexikJWTAuthenticationBundle/issues", - "source": "https://github.com/lexik/LexikJWTAuthenticationBundle/tree/v3.1.1" - }, - "funding": [ - { - "url": "https://github.com/chalasr", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/lexik/jwt-authentication-bundle", - "type": "tidelift" - } - ], - "time": "2025-01-06T16:34:57+00:00" - }, - { - "name": "martin-georgiev/postgresql-for-doctrine", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/martin-georgiev/postgresql-for-doctrine.git", - "reference": "5d1621e48edd7c7306cf2b9e73e374727867d6af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/martin-georgiev/postgresql-for-doctrine/zipball/5d1621e48edd7c7306cf2b9e73e374727867d6af", - "reference": "5d1621e48edd7c7306cf2b9e73e374727867d6af", - "shasum": "" - }, - "require": { - "doctrine/dbal": "~2.10||~3.0||~4.0", - "ext-ctype": "*", - "ext-json": "*", - "ext-mbstring": "*", - "php": "^8.1" - }, - "require-dev": { - "deptrac/deptrac": "^4.0", - "doctrine/orm": "~2.14||~3.0", - "ekino/phpstan-banned-code": "^3.0", - "friendsofphp/php-cs-fixer": "^3.87.1", - "phpstan/phpstan": "^2.1.22", - "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-doctrine": "^2.0.4", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpunit/phpunit": "^10.5.53", - "rector/rector": "^2.1.5", - "symfony/cache": "^6.4||^7.0" - }, - "suggest": { - "doctrine/orm": "~2.14||~3.0", - "php": "^8.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "MartinGeorgiev\\": "src/MartinGeorgiev/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Martin Georgiev", - "email": "martin.georgiev@gmail.com", - "role": "author" - } - ], - "description": "Adds PostgreSQL enhancements to Doctrine. Provides support for JSON, JSONB and some array data types. Provides functions, operators and common expressions used when working with JSON data, arrays and features related to text search.", - "keywords": [ - "array data types", - "dbal", - "doctrine", - "json", - "jsonb", - "martin georgiev", - "postgres", - "postgresql", - "text search", - "tsvector" - ], - "support": { - "issues": "https://github.com/martin-georgiev/postgresql-for-doctrine/issues", - "source": "https://github.com/martin-georgiev/postgresql-for-doctrine/tree/v3.5.1" - }, - "funding": [ - { - "url": "https://github.com/sponsors/martin-georgiev", - "type": "custom" - }, - { - "url": "https://github.com/martin-georgiev", - "type": "github" - } - ], - "time": "2025-09-12T10:54:26+00:00" - }, - { - "name": "masterminds/html5", - "version": "2.10.0", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "fcf91eb64359852f00d921887b219479b4f21251" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", - "reference": "fcf91eb64359852f00d921887b219479b4f21251", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ], - "support": { - "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" - }, - "time": "2025-07-25T09:04:22+00:00" - }, - { - "name": "matomo/device-detector", - "version": "6.4.7", - "source": { - "type": "git", - "url": "https://github.com/matomo-org/device-detector.git", - "reference": "e53eed31bb1530851feebe52bd64c3451da19e77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/e53eed31bb1530851feebe52bd64c3451da19e77", - "reference": "e53eed31bb1530851feebe52bd64c3451da19e77", - "shasum": "" - }, - "require": { - "mustangostang/spyc": "*", - "php": "^7.2|^8.0" - }, - "replace": { - "piwik/device-detector": "self.version" - }, - "require-dev": { - "matthiasmullie/scrapbook": "^1.4.7", - "mayflower/mo4-coding-standard": "^v9.0.0", - "phpstan/phpstan": "^1.10.44", - "phpunit/phpunit": "^8.5.8", - "psr/cache": "^1.0.1", - "psr/simple-cache": "^1.0.1", - "slevomat/coding-standard": "<8.16.0", - "symfony/yaml": "^5.1.7" - }, - "suggest": { - "doctrine/cache": "Can directly be used for caching purpose", - "ext-yaml": "Necessary for using the Pecl YAML parser" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeviceDetector\\": "" - }, - "exclude-from-classmap": [ - "Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "The Matomo Team", - "email": "hello@matomo.org", - "homepage": "https://matomo.org/team/" - } - ], - "description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.", - "homepage": "https://matomo.org", - "keywords": [ - "devicedetection", - "parser", - "useragent" - ], - "support": { - "forum": "https://forum.matomo.org/", - "issues": "https://github.com/matomo-org/device-detector/issues", - "source": "https://github.com/matomo-org/matomo", - "wiki": "https://dev.matomo.org/" - }, - "time": "2025-08-20T17:20:16+00:00" - }, - { - "name": "maxmind-db/reader", - "version": "v1.12.1", - "source": { - "type": "git", - "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", - "reference": "815939e006b7e68062b540ec9e86aaa8be2b6ce4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/815939e006b7e68062b540ec9e86aaa8be2b6ce4", - "reference": "815939e006b7e68062b540ec9e86aaa8be2b6ce4", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "conflict": { - "ext-maxminddb": "<1.11.1 || >=2.0.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "3.*", - "phpstan/phpstan": "*", - "phpunit/phpunit": ">=8.0.0,<10.0.0", - "squizlabs/php_codesniffer": "3.*" - }, - "suggest": { - "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", - "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", - "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" - }, - "type": "library", - "autoload": { - "psr-4": { - "MaxMind\\Db\\": "src/MaxMind/Db" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Gregory J. Oschwald", - "email": "goschwald@maxmind.com", - "homepage": "https://www.maxmind.com/" - } - ], - "description": "MaxMind DB Reader API", - "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", - "keywords": [ - "database", - "geoip", - "geoip2", - "geolocation", - "maxmind" - ], - "support": { - "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", - "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.12.1" - }, - "time": "2025-05-05T20:56:32+00:00" - }, - { - "name": "maxmind/web-service-common", - "version": "v0.10.0", - "source": { - "type": "git", - "url": "https://github.com/maxmind/web-service-common-php.git", - "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", - "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", - "shasum": "" - }, - "require": { - "composer/ca-bundle": "^1.0.3", - "ext-curl": "*", - "ext-json": "*", - "php": ">=8.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "3.*", - "phpstan/phpstan": "*", - "phpunit/phpunit": "^8.0 || ^9.0", - "squizlabs/php_codesniffer": "3.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "MaxMind\\Exception\\": "src/Exception", - "MaxMind\\WebService\\": "src/WebService" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Gregory Oschwald", - "email": "goschwald@maxmind.com" - } - ], - "description": "Internal MaxMind Web Service API", - "homepage": "https://github.com/maxmind/web-service-common-php", - "support": { - "issues": "https://github.com/maxmind/web-service-common-php/issues", - "source": "https://github.com/maxmind/web-service-common-php/tree/v0.10.0" - }, - "time": "2024-11-14T23:14:52+00:00" - }, - { - "name": "monolog/monolog", - "version": "3.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" - }, - "provide": { - "psr/log-implementation": "3.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^3.0", - "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^7 || ^8", - "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2.0", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", - "php-amqplib/php-amqplib": "~2.4 || ^3", - "php-console/php-console": "^3.1.8", - "phpstan/phpstan": "^2", - "phpstan/phpstan-deprecation-rules": "^2", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^10.5.17 || ^11.0.7", - "predis/predis": "^1.1 || ^2", - "rollbar/rollbar": "^4.0", - "ruflin/elastica": "^7 || ^8", - "symfony/mailer": "^5.4 || ^6", - "symfony/mime": "^5.4 || ^6" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", - "ext-mbstring": "Allow to work properly with unicode symbols", - "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", - "ext-openssl": "Required to send log messages using SSL", - "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "https://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "support": { - "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.9.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", - "type": "tidelift" - } - ], - "time": "2025-03-24T10:02:05+00:00" - }, - { - "name": "mustangostang/spyc", - "version": "0.6.3", - "source": { - "type": "git", - "url": "https://github.com/mustangostang/spyc.git", - "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0", - "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0", - "shasum": "" - }, - "require": { - "php": ">=5.3.1" - }, - "require-dev": { - "phpunit/phpunit": "4.3.*@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.5.x-dev" - } - }, - "autoload": { - "files": [ - "Spyc.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "mustangostang", - "email": "vlad.andersen@gmail.com" - } - ], - "description": "A simple YAML loader/dumper class for PHP", - "homepage": "https://github.com/mustangostang/spyc/", - "keywords": [ - "spyc", - "yaml", - "yml" - ], - "support": { - "issues": "https://github.com/mustangostang/spyc/issues", - "source": "https://github.com/mustangostang/spyc/tree/0.6.3" - }, - "time": "2019-09-10T13:16:29+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.6.3", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.1", - "ext-filter": "*", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.5 || ~1.6.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" - }, - "time": "2025-08-01T19:43:32+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" - }, - "time": "2024-11-09T15:12:26+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" - }, - "time": "2025-08-30T15:50:23+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/clock", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/clock.git", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Clock\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for reading the clock.", - "homepage": "https://github.com/php-fig/clock", - "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" - ], - "support": { - "issues": "https://github.com/php-fig/clock/issues", - "source": "https://github.com/php-fig/clock/tree/1.0.0" - }, - "time": "2022-11-25T14:36:26+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/http-factory", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, - "time": "2024-04-15T12:06:14+00:00" - }, - { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" - }, - { - "name": "sentry/sentry", - "version": "4.16.0", - "source": { - "type": "git", - "url": "https://github.com/getsentry/sentry-php.git", - "reference": "c5b086e4235762da175034bc463b0d31cbb38d2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/c5b086e4235762da175034bc463b0d31cbb38d2e", - "reference": "c5b086e4235762da175034bc463b0d31cbb38d2e", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "guzzlehttp/psr7": "^1.8.4|^2.1.1", - "jean85/pretty-package-versions": "^1.5|^2.0.4", - "php": "^7.2|^8.0", - "psr/log": "^1.0|^2.0|^3.0", - "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0" - }, - "conflict": { - "raven/raven": "*" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.4", - "guzzlehttp/promises": "^2.0.3", - "guzzlehttp/psr7": "^1.8.4|^2.1.1", - "monolog/monolog": "^1.6|^2.0|^3.0", - "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^8.5|^9.6", - "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", - "vimeo/psalm": "^4.17" - }, - "suggest": { - "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler." - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Sentry\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sentry", - "email": "accounts@sentry.io" - } - ], - "description": "PHP SDK for Sentry (http://sentry.io)", - "homepage": "http://sentry.io", - "keywords": [ - "crash-reporting", - "crash-reports", - "error-handler", - "error-monitoring", - "log", - "logging", - "profiling", - "sentry", - "tracing" - ], - "support": { - "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.16.0" - }, - "funding": [ - { - "url": "https://sentry.io/", - "type": "custom" - }, - { - "url": "https://sentry.io/pricing/", - "type": "custom" - } - ], - "time": "2025-09-22T13:38:03+00:00" - }, - { - "name": "sentry/sentry-symfony", - "version": "5.6.0", - "source": { - "type": "git", - "url": "https://github.com/getsentry/sentry-symfony.git", - "reference": "9867751f5091b55d7e3a223f48d88e228132e073" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/9867751f5091b55d7e3a223f48d88e228132e073", - "reference": "9867751f5091b55d7e3a223f48d88e228132e073", - "shasum": "" - }, - "require": { - "guzzlehttp/psr7": "^2.1.1", - "jean85/pretty-package-versions": "^1.5||^2.0", - "php": "^7.2||^8.0", - "sentry/sentry": "^4.16.0", - "symfony/cache-contracts": "^1.1||^2.4||^3.0", - "symfony/config": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/console": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/dependency-injection": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/event-dispatcher": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/http-kernel": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/polyfill-php80": "^1.22", - "symfony/psr-http-message-bridge": "^1.2||^2.0||^6.4||^7.0" - }, - "require-dev": { - "doctrine/dbal": "^2.13||^3.3||^4.0", - "doctrine/doctrine-bundle": "^2.6", - "friendsofphp/php-cs-fixer": "^2.19||^3.40", - "masterminds/html5": "^2.8", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "1.12.5", - "phpstan/phpstan-phpunit": "1.4.0", - "phpstan/phpstan-symfony": "1.4.10", - "phpunit/phpunit": "^8.5.40||^9.6.21", - "symfony/browser-kit": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/cache": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/dom-crawler": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/framework-bundle": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/http-client": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/messenger": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/monolog-bundle": "^3.4", - "symfony/phpunit-bridge": "^5.2.6||^6.0||^7.0", - "symfony/process": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/security-core": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/security-http": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/twig-bundle": "^4.4.20||^5.0.11||^6.0||^7.0", - "symfony/yaml": "^4.4.20||^5.0.11||^6.0||^7.0", - "vimeo/psalm": "^4.3||^5.16.0" - }, - "suggest": { - "doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry.", - "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler.", - "symfony/cache": "Allow distributed tracing of cache pools using Sentry.", - "symfony/twig-bundle": "Allow distributed tracing of Twig template rendering using Sentry." - }, - "type": "symfony-bundle", - "autoload": { - "files": [ - "src/aliases.php" - ], - "psr-4": { - "Sentry\\SentryBundle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sentry", - "email": "accounts@sentry.io" - } - ], - "description": "Symfony integration for Sentry (http://getsentry.com)", - "homepage": "http://getsentry.com", - "keywords": [ - "errors", - "logging", - "sentry", - "symfony" - ], - "support": { - "issues": "https://github.com/getsentry/sentry-symfony/issues", - "source": "https://github.com/getsentry/sentry-symfony/tree/5.6.0" - }, - "funding": [ - { - "url": "https://sentry.io/", - "type": "custom" - }, - { - "url": "https://sentry.io/pricing/", - "type": "custom" - } - ], - "time": "2025-09-24T13:41:01+00:00" - }, - { - "name": "symfony/cache", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "e874746cea6893d4b91943eab8376a0fe7528de6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/e874746cea6893d4b91943eab8376a0fe7528de6", - "reference": "e874746cea6893d4b91943eab8376a0fe7528de6", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/cache": "^2.0|^3.0", - "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^2.5|^3", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.4|^7.0" - }, - "conflict": { - "doctrine/dbal": "<3.6", - "symfony/dependency-injection": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/var-dumper": "<6.4" - }, - "provide": { - "psr/cache-implementation": "2.0|3.0", - "psr/simple-cache-implementation": "1.0|2.0|3.0", - "symfony/cache-implementation": "1.1|2.0|3.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "classmap": [ - "Traits/ValueWrapper.php" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], - "support": { - "source": "https://github.com/symfony/cache/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-30T17:03:27+00:00" - }, - { - "name": "symfony/cache-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", - "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/cache": "^3.0" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-03-13T15:25:07+00:00" - }, - { - "name": "symfony/clock", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/now.php" - ], - "psr-4": { - "Symfony\\Component\\Clock\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Decouples applications from the system clock", - "homepage": "https://symfony.com", - "keywords": [ - "clock", - "psr20", - "time" - ], - "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/config", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "4cfed7041ac389c242122e60884d4a9fc5376cb3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4cfed7041ac389c242122e60884d4a9fc5376cb3", - "reference": "4cfed7041ac389c242122e60884d4a9fc5376cb3", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<6.4", - "symfony/service-contracts": "<2.5" - }, - "require-dev": { - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/config/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-26T13:54:51+00:00" - }, - { - "name": "symfony/console", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "93518c2ff7ce9c1818224c6effed3cf2429c63d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/93518c2ff7ce9c1818224c6effed3cf2429c63d7", - "reference": "93518c2ff7ce9c1818224c6effed3cf2429c63d7", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-30T17:03:27+00:00" - }, - { - "name": "symfony/css-selector", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Converts CSS selectors to XPath expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "fae0971f518e81fd1ccbfb6218aef410392ac701" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fae0971f518e81fd1ccbfb6218aef410392ac701", - "reference": "fae0971f518e81fd1ccbfb6218aef410392ac701", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^3.5", - "symfony/var-exporter": "^6.4.20|^7.2.5" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.4", - "symfony/finder": "<6.4", - "symfony/yaml": "<6.4" - }, - "provide": { - "psr/container-implementation": "1.1|2.0", - "symfony/service-implementation": "1.1|2.0|3.0" - }, - "require-dev": { - "symfony/config": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-30T17:31:35+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/doctrine-bridge", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "ef8b21518615585e91ae7ab552265f04fcfa9dcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/ef8b21518615585e91ae7ab552265f04fcfa9dcf", - "reference": "ef8b21518615585e91ae7ab552265f04fcfa9dcf", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "^2", - "doctrine/persistence": "^3.1|^4", - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/collections": "<1.8", - "doctrine/dbal": "<3.6", - "doctrine/lexer": "<1.1", - "doctrine/orm": "<2.15", - "symfony/cache": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/form": "<6.4.6|>=7,<7.0.6", - "symfony/http-foundation": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/lock": "<6.4", - "symfony/messenger": "<6.4", - "symfony/property-info": "<6.4", - "symfony/security-bundle": "<6.4", - "symfony/security-core": "<6.4", - "symfony/validator": "<6.4" - }, - "require-dev": { - "doctrine/collections": "^1.8|^2.0", - "doctrine/data-fixtures": "^1.1|^2", - "doctrine/dbal": "^3.6|^4", - "doctrine/orm": "^2.15|^3", - "psr/log": "^1|^2|^3", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/doctrine-messenger": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4.6|^7.0.6", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Doctrine\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Doctrine with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T09:47:02+00:00" - }, - { - "name": "symfony/dom-crawler", - "version": "v7.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "a7473767124513e4099186dba43403dbc45f26dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a7473767124513e4099186dba43403dbc45f26dc", - "reference": "a7473767124513e4099186dba43403dbc45f26dc", - "shasum": "" - }, - "require": { - "masterminds/html5": "^2.6", - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases DOM navigation for HTML and XML documents", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v7.2.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-15T10:06:57+00:00" - }, - { - "name": "symfony/dotenv", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/dotenv.git", - "reference": "2192790a11f9e22cbcf9dc705a3ff22a5503923a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/2192790a11f9e22cbcf9dc705a3ff22a5503923a", - "reference": "2192790a11f9e22cbcf9dc705a3ff22a5503923a", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "conflict": { - "symfony/console": "<6.4", - "symfony/process": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Dotenv\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Registers environment variables from a .env file", - "homepage": "https://symfony.com", - "keywords": [ - "dotenv", - "env", - "environment" - ], - "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/error-handler", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "df98c90e43fa8267da4a64a88dd9427e0277773a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/df98c90e43fa8267da4a64a88dd9427e0277773a", - "reference": "df98c90e43fa8267da4a64a88dd9427e0277773a", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" - }, - "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" - }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to manage errors and ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-07T08:17:47+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/event-dispatcher-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-07T08:17:47+00:00" - }, - { - "name": "symfony/finder", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T13:41:35+00:00" - }, - { - "name": "symfony/flex", - "version": "v2.8.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/flex.git", - "reference": "f356aa35f3cf3d2f46c31d344c1098eb2d260426" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/f356aa35f3cf3d2f46c31d344c1098eb2d260426", - "reference": "f356aa35f3cf3d2f46c31d344c1098eb2d260426", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.1", - "php": ">=8.0" - }, - "conflict": { - "composer/semver": "<1.7.2" - }, - "require-dev": { - "composer/composer": "^2.1", - "symfony/dotenv": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/phpunit-bridge": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Symfony\\Flex\\Flex" - }, - "autoload": { - "psr-4": { - "Symfony\\Flex\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien.potencier@gmail.com" - } - ], - "description": "Composer plugin for Symfony", - "support": { - "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.8.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-08-22T07:17:23+00:00" - }, - { - "name": "symfony/framework-bundle", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "42ac8bbbf10d3113c335ba8af39fad63db96e4e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/42ac8bbbf10d3113c335ba8af39fad63db96e4e2", - "reference": "42ac8bbbf10d3113c335ba8af39fad63db96e4e2", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.2", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^7.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/filesystem": "^7.1", - "symfony/finder": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^7.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^6.4|^7.0" - }, - "conflict": { - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<6.4", - "symfony/asset-mapper": "<6.4", - "symfony/clock": "<6.4", - "symfony/console": "<6.4", - "symfony/dom-crawler": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/lock": "<6.4", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/mime": "<6.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", - "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/security-core": "<6.4", - "symfony/security-csrf": "<7.2", - "symfony/serializer": "<7.2.5", - "symfony/stopwatch": "<6.4", - "symfony/translation": "<6.4", - "symfony/twig-bridge": "<6.4", - "symfony/twig-bundle": "<6.4", - "symfony/validator": "<6.4", - "symfony/web-profiler-bundle": "<6.4", - "symfony/webhook": "<7.2", - "symfony/workflow": "<6.4" - }, - "require-dev": { - "doctrine/persistence": "^1.3|^2|^3", - "dragonmantank/cron-expression": "^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "seld/jsonlint": "^1.10", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/dotenv": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/notifier": "^6.4|^7.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4.4|^7.0.4", - "symfony/security-bundle": "^6.4|^7.0", - "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^7.2.5", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/webhook": "^7.2", - "symfony/workflow": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-30T17:03:27+00:00" - }, - { - "name": "symfony/http-client", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "e26182d286135dad99f58ad57c56eef41362d452" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/e26182d286135dad99f58ad57c56eef41362d452", - "reference": "e26182d286135dad99f58ad57c56eef41362d452", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "~3.4.4|^3.5.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "amphp/amp": "<2.5", - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.4" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/http-client": "^4.2.1|^5.0", - "amphp/http-tunnel": "^1.0|^2.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/amphp-http-client-meta": "^1.0|^2.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "75d7043853a42837e68111812f4d964b01e5101c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", - "reference": "75d7043853a42837e68111812f4d964b01e5101c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-04-29T11:18:49+00:00" - }, - { - "name": "symfony/http-foundation", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "7d81b8184601176dff995cf959d3def142309049" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7d81b8184601176dff995cf959d3def142309049", - "reference": "7d81b8184601176dff995cf959d3def142309049", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" - }, - "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" - }, - "require-dev": { - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/http-kernel", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c", - "reference": "d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a structured process for converting a Request into a Response", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-31T09:36:38+00:00" - }, - { - "name": "symfony/mailer", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/mailer.git", - "reference": "aa8d1d5df027626c3cbe2f5f185118cc461fe4ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/aa8d1d5df027626c3cbe2f5f185118cc461fe4ea", - "reference": "aa8d1d5df027626c3cbe2f5f185118cc461fe4ea", - "shasum": "" - }, - "require": { - "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.2", - "psr/event-dispatcher": "^1", - "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^7.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/messenger": "<6.4", - "symfony/mime": "<6.4", - "symfony/twig-bridge": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mailer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps sending emails", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/mailer/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/messenger", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/messenger.git", - "reference": "3fd1638aa11ef6f342ed6b10b930a1757c25417c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/3fd1638aa11ef6f342ed6b10b930a1757c25417c", - "reference": "3fd1638aa11ef6f342ed6b10b930a1757c25417c", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/clock": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/console": "<7.2", - "symfony/event-dispatcher": "<6.4", - "symfony/event-dispatcher-contracts": "<2.5", - "symfony/framework-bundle": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/serializer": "<6.4" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/console": "^7.2", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Messenger\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Samuel Roze", - "email": "samuel.roze@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps applications send and receive messages to/from other applications or via message queues", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/messenger/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/mime", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/mime.git", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", - "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "conflict": { - "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<6.4", - "symfony/serializer": "<6.4.3|>7.0,<7.0.3" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mime\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows manipulating MIME messages", - "homepage": "https://symfony.com", - "keywords": [ - "mime", - "mime-type" - ], - "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T13:41:35+00:00" - }, - { - "name": "symfony/monolog-bridge", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d", - "reference": "bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d", - "shasum": "" - }, - "require": { - "monolog/monolog": "^3", - "php": ">=8.2", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/console": "<6.4", - "symfony/http-foundation": "<6.4", - "symfony/security-core": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Monolog\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Monolog with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-14T18:16:08+00:00" - }, - { - "name": "symfony/monolog-bundle", - "version": "v3.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/monolog-bundle.git", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", - "shasum": "" - }, - "require": { - "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", - "php": ">=7.2.5", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", - "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0" - }, - "require-dev": { - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/phpunit-bridge": "^6.3 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MonologBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony MonologBundle", - "homepage": "https://symfony.com", - "keywords": [ - "log", - "logging" - ], - "support": { - "issues": "https://github.com/symfony/monolog-bundle/issues", - "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-06T17:08:13+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "b48517d1cef0d533e241cb03801014f1bb832775" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b48517d1cef0d533e241cb03801014f1bb832775", - "reference": "b48517d1cef0d533e241cb03801014f1bb832775", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/password-hasher", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/password-hasher.git", - "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", - "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "conflict": { - "symfony/security-core": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PasswordHasher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Robin Chalas", - "email": "robin.chalas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides password hashing utilities", - "homepage": "https://symfony.com", - "keywords": [ - "hashing", - "password" - ], - "support": { - "source": "https://github.com/symfony/password-hasher/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-27T09:58:17+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", - "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", - "shasum": "" - }, - "require": { - "php": ">=7.2", - "symfony/polyfill-intl-normalizer": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-10T14:38:51+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-12-23T08:48:59+00:00" - }, - { - "name": "symfony/polyfill-php83", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-08T02:45:35+00:00" - }, - { - "name": "symfony/polyfill-php84", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php84\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-24T13:30:11+00:00" - }, - { - "name": "symfony/polyfill-uuid", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-uuid": "*" - }, - "suggest": { - "ext-uuid": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Uuid\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Grégoire Pineau", - "email": "lyrixx@lyrixx.info" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for uuid functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "uuid" - ], - "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/property-access", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-access.git", - "reference": "9858acdf18abac17b9ab254706454d0cc0de7641" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/9858acdf18abac17b9ab254706454d0cc0de7641", - "reference": "9858acdf18abac17b9ab254706454d0cc0de7641", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/property-info": "^6.4|^7.0" - }, - "require-dev": { - "symfony/cache": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyAccess\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides functions to read and write from/to an object or array using a simple string notation", - "homepage": "https://symfony.com", - "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property-path", - "reflection" - ], - "support": { - "source": "https://github.com/symfony/property-access/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T13:41:35+00:00" - }, - { - "name": "symfony/property-info", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-info.git", - "reference": "16bb9e15292f9f07c28a6f955d4f14c680d1e0b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/16bb9e15292f9f07c28a6f955d4f14c680d1e0b5", - "reference": "16bb9e15292f9f07c28a6f955d4f14c680d1e0b5", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/string": "^6.4|^7.0", - "symfony/type-info": "~7.2.8|^7.3.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/cache": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/serializer": "<6.4" - }, - "require-dev": { - "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0|^2.0", - "symfony/cache": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts information about PHP class' properties using metadata of popular sources", - "homepage": "https://symfony.com", - "keywords": [ - "doctrine", - "phpdoc", - "property", - "symfony", - "type", - "validator" - ], - "support": { - "source": "https://github.com/symfony/property-info/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/psr-http-message-bridge", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" - }, - "require-dev": { - "nyholm/psr7": "^1.1", - "php-http/discovery": "^1.15", - "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "PSR HTTP message bridge", - "homepage": "https://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-17", - "psr-7" - ], - "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-26T08:57:56+00:00" - }, - { - "name": "symfony/routing", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "d5a038e972be748e3f057c884897a41b1111e4a0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/d5a038e972be748e3f057c884897a41b1111e4a0", - "reference": "d5a038e972be748e3f057c884897a41b1111e4a0", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "support": { - "source": "https://github.com/symfony/routing/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-15T11:30:57+00:00" - }, - { - "name": "symfony/runtime", - "version": "v7.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/runtime.git", - "reference": "40d1c481c2370362010a4da64af14dec62a9ec68" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/40d1c481c2370362010a4da64af14dec62a9ec68", - "reference": "40d1c481c2370362010a4da64af14dec62a9ec68", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0|^2.0", - "php": ">=8.2" - }, - "conflict": { - "symfony/dotenv": "<6.4" - }, - "require-dev": { - "composer/composer": "^2.6", - "symfony/console": "^6.4|^7.0", - "symfony/dotenv": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Runtime\\": "", - "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Enables decoupling PHP applications from global state", - "homepage": "https://symfony.com", - "keywords": [ - "runtime" - ], - "support": { - "source": "https://github.com/symfony/runtime/tree/v7.2.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-13T07:47:28+00:00" - }, - { - "name": "symfony/security-bundle", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-bundle.git", - "reference": "4661890f7d2571e9ef58431401a390c2dde68c78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/4661890f7d2571e9ef58431401a390c2dde68c78", - "reference": "4661890f7d2571e9ef58431401a390c2dde68c78", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.2", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4.11|^7.1.4", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/password-hasher": "^6.4|^7.0", - "symfony/security-core": "^7.2", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/security-http": "^7.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/console": "<6.4", - "symfony/framework-bundle": "<6.4", - "symfony/http-client": "<6.4", - "symfony/ldap": "<6.4", - "symfony/serializer": "<6.4", - "symfony/twig-bundle": "<6.4", - "symfony/validator": "<6.4" - }, - "require-dev": { - "symfony/asset": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/ldap": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "twig/twig": "^3.12", - "web-token/jwt-library": "^3.3.2|^4.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\SecurityBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-bundle/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-22T07:39:44+00:00" - }, - { - "name": "symfony/security-core", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-core.git", - "reference": "28ec042a6aff580693cce7aa820778e6dfa5e5ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/28ec042a6aff580693cce7aa820778e6dfa5e5ef", - "reference": "28ec042a6aff580693cce7aa820778e6dfa5e5ef", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/password-hasher": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/http-foundation": "<6.4", - "symfony/ldap": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", - "symfony/validator": "<6.4" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "psr/container": "^1.1|^2.0", - "psr/log": "^1|^2|^3", - "symfony/cache": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/ldap": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/validator": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Core\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - Core Library", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-core/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-22T08:39:58+00:00" - }, - { - "name": "symfony/security-csrf", - "version": "v7.2.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-csrf.git", - "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/2b4b0c46c901729e4e90719eacd980381f53e0a3", - "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/security-core": "^6.4|^7.0" - }, - "conflict": { - "symfony/http-foundation": "<6.4" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Csrf\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - CSRF Library", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-csrf/tree/v7.2.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-01-02T18:42:10+00:00" - }, - { - "name": "symfony/security-http", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-http.git", - "reference": "972dd874c2ce65e4c58dbf59054d2bf7ad70ec54" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/972dd874c2ce65e4c58dbf59054d2bf7ad70ec54", - "reference": "972dd874c2ce65e4c58dbf59054d2bf7ad70ec54", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/security-core": "^7.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/clock": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/http-client-contracts": "<3.0", - "symfony/security-bundle": "<6.4", - "symfony/security-csrf": "<6.4" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/cache": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/http-client-contracts": "^3.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "web-token/jwt-library": "^3.3.2|^4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Http\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - HTTP Integration", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-http/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/serializer", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/serializer.git", - "reference": "91b01d65b553a6687c7b13432da1c0f4af1bf875" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/91b01d65b553a6687c7b13432da1c0f4af1bf875", - "reference": "91b01d65b553a6687c7b13432da1c0f4af1bf875", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<6.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/uid": "<6.4", - "symfony/validator": "<6.4", - "symfony/yaml": "<6.4" - }, - "require-dev": { - "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", - "phpstan/phpdoc-parser": "^1.0|^2.0", - "seld/jsonlint": "^1.10", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^7.2", - "symfony/error-handler": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Serializer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/serializer/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-26T12:59:07+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-04-25T09:37:31+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v7.2.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-02-24T10:49:57+00:00" - }, - { - "name": "symfony/string", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "de5189e4def141dbdca2f2ce7a653cc6364f58e6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/de5189e4def141dbdca2f2ce7a653cc6364f58e6", - "reference": "de5189e4def141dbdca2f2ce7a653cc6364f58e6", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/translation-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to translation", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-27T08:32:26+00:00" - }, - { - "name": "symfony/twig-bridge", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bridge.git", - "reference": "e62144411b277877d0e8583b48202673c36941d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/e62144411b277877d0e8583b48202673c36941d7", - "reference": "e62144411b277877d0e8583b48202673c36941d7", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/translation-contracts": "^2.5|^3", - "twig/twig": "^3.12" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<6.4", - "symfony/form": "<6.4", - "symfony/http-foundation": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/mime": "<6.4", - "symfony/serializer": "<6.4", - "symfony/translation": "<6.4", - "symfony/workflow": "<6.4" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10|^3|^4", - "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/emoji": "^7.1", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/form": "^6.4.20|^7.2.5", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/security-http": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/workflow": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "twig/cssinliner-extra": "^2.12|^3", - "twig/inky-extra": "^2.12|^3", - "twig/markdown-extra": "^2.12|^3" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Twig\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Twig with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-26T14:12:01+00:00" - }, - { - "name": "symfony/twig-bundle", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bundle.git", - "reference": "157de579a9ec25d5dfeb7ee3b3e9b57d2e635c39" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/157de579a9ec25d5dfeb7ee3b3e9b57d2e635c39", - "reference": "157de579a9ec25d5dfeb7ee3b3e9b57d2e635c39", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "php": ">=8.2", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "conflict": { - "symfony/framework-bundle": "<6.4", - "symfony/translation": "<6.4" - }, - "require-dev": { - "symfony/asset": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\TwigBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of Twig into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/type-info", - "version": "v7.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/type-info.git", - "reference": "ec311f6f16ce2dffdffb6db6f89cdd1533723e42" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/ec311f6f16ce2dffdffb6db6f89cdd1533723e42", - "reference": "ec311f6f16ce2dffdffb6db6f89cdd1533723e42", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/container": "^1.1|^2.0" - }, - "require-dev": { - "phpstan/phpdoc-parser": "^1.0|^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\TypeInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mathias Arlaud", - "email": "mathias.arlaud@gmail.com" - }, - { - "name": "Baptiste LEDUC", - "email": "baptiste.leduc@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts PHP types information.", - "homepage": "https://symfony.com", - "keywords": [ - "PHPStan", - "phpdoc", - "symfony", - "type" - ], - "support": { - "source": "https://github.com/symfony/type-info/tree/v7.2.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-27T15:23:16+00:00" - }, - { - "name": "symfony/uid", - "version": "v7.2.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/uid.git", - "reference": "41aced5ddb593c9c6c81ac9828320448caa02444" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/41aced5ddb593c9c6c81ac9828320448caa02444", - "reference": "41aced5ddb593c9c6c81ac9828320448caa02444", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-uuid": "^1.15" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Uid\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Grégoire Pineau", - "email": "lyrixx@lyrixx.info" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to generate and represent UIDs", - "homepage": "https://symfony.com", - "keywords": [ - "UID", - "ulid", - "uuid" - ], - "support": { - "source": "https://github.com/symfony/uid/tree/v7.2.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-27T19:53:16+00:00" - }, - { - "name": "symfony/validator", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/validator.git", - "reference": "b5410782f69892acf828e0eec7943a2caca46ed6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/b5410782f69892acf828e0eec7943a2caca46ed6", - "reference": "b5410782f69892acf828e0eec7943a2caca46ed6", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php83": "^1.27", - "symfony/translation-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<7.0", - "symfony/expression-language": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/intl": "<6.4", - "symfony/property-info": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", - "symfony/yaml": "<6.4" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10|^3|^4", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/type-info": "^7.1.8", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Validator\\": "" - }, - "exclude-from-classmap": [ - "/Tests/", - "/Resources/bin/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to validate values", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/validator/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-29T19:57:35+00:00" - }, - { - "name": "symfony/var-dumper", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "67ad2a16e50f052c80fe03ccb6a8721bbeffe032" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/67ad2a16e50f052c80fe03ccb6a8721bbeffe032", - "reference": "67ad2a16e50f052c80fe03ccb6a8721bbeffe032", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides mechanisms for walking through any arbitrary PHP variable", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], - "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-29T19:57:35+00:00" - }, - { - "name": "symfony/var-exporter", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "1aab3e8e2e63f7586dd9951746eababe339d3978" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1aab3e8e2e63f7586dd9951746eababe339d3978", - "reference": "1aab3e8e2e63f7586dd9951746eababe339d3978", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "lazy-loading", - "proxy", - "serialize" - ], - "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/yaml", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "0df1031b6a03b9bef3cd052a59e270e006731e90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0df1031b6a03b9bef3cd052a59e270e006731e90", - "reference": "0df1031b6a03b9bef3cd052a59e270e006731e90", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "twig/extra-bundle", - "version": "v3.21.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/62d1cf47a1aa009cbd07b21045b97d3d5cb79896", - "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896", - "shasum": "" - }, - "require": { - "php": ">=8.1.0", - "symfony/framework-bundle": "^5.4|^6.4|^7.0", - "symfony/twig-bundle": "^5.4|^6.4|^7.0", - "twig/twig": "^3.2|^4.0" - }, - "require-dev": { - "league/commonmark": "^1.0|^2.0", - "symfony/phpunit-bridge": "^6.4|^7.0", - "twig/cache-extra": "^3.0", - "twig/cssinliner-extra": "^3.0", - "twig/html-extra": "^3.0", - "twig/inky-extra": "^3.0", - "twig/intl-extra": "^3.0", - "twig/markdown-extra": "^3.0", - "twig/string-extra": "^3.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Twig\\Extra\\TwigExtraBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - } - ], - "description": "A Symfony bundle for extra Twig extensions", - "homepage": "https://twig.symfony.com", - "keywords": [ - "bundle", - "extra", - "twig" - ], - "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.21.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2025-02-19T14:29:33+00:00" - }, - { - "name": "twig/twig", - "version": "v3.21.1", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", - "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", - "shasum": "" - }, - "require": { - "php": ">=8.1.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "phpstan/phpstan": "^2.0", - "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/Resources/core.php", - "src/Resources/debug.php", - "src/Resources/escaper.php", - "src/Resources/string_loader.php" - ], - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.21.1" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2025-05-03T07:21:55+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - } - ], - "packages-dev": [ - { - "name": "behat/behat", - "version": "v3.25.0", - "source": { - "type": "git", - "url": "https://github.com/Behat/Behat.git", - "reference": "bc7f149dde1cd0da82616e6b280e1c9be2ee53e1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/bc7f149dde1cd0da82616e6b280e1c9be2ee53e1", - "reference": "bc7f149dde1cd0da82616e6b280e1c9be2ee53e1", - "shasum": "" - }, - "require": { - "behat/gherkin": "^4.12.0", - "composer-runtime-api": "^2.2", - "composer/xdebug-handler": "^1.4 || ^2.0 || ^3.0", - "ext-mbstring": "*", - "nikic/php-parser": "^4.19.2 || ^5.2", - "php": "8.1.* || 8.2.* || 8.3.* || 8.4.* ", - "psr/container": "^1.0 || ^2.0", - "symfony/config": "^5.4 || ^6.4 || ^7.0", - "symfony/console": "^5.4 || ^6.4 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", - "symfony/translation": "^5.4 || ^6.4 || ^7.0", - "symfony/yaml": "^5.4 || ^6.4 || ^7.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.68", - "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^9.6", - "rector/rector": "2.1.7", - "sebastian/diff": "^4.0", - "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", - "symfony/polyfill-php84": "^1.31", - "symfony/process": "^5.4 || ^6.4 || ^7.0" - }, - "suggest": { - "ext-dom": "Needed to output test results in JUnit format." - }, - "bin": [ - "bin/behat" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Behat\\Hook\\": "src/Behat/Hook/", - "Behat\\Step\\": "src/Behat/Step/", - "Behat\\Behat\\": "src/Behat/Behat/", - "Behat\\Config\\": "src/Behat/Config/", - "Behat\\Testwork\\": "src/Behat/Testwork/", - "Behat\\Transformation\\": "src/Behat/Transformation/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Scenario-oriented BDD framework for PHP", - "homepage": "https://behat.org/", - "keywords": [ - "Agile", - "BDD", - "ScenarioBDD", - "Scrum", - "StoryBDD", - "User story", - "business", - "development", - "documentation", - "examples", - "symfony", - "testing" - ], - "support": { - "issues": "https://github.com/Behat/Behat/issues", - "source": "https://github.com/Behat/Behat/tree/v3.25.0" - }, - "time": "2025-10-03T20:14:49+00:00" - }, - { - "name": "behat/gherkin", - "version": "v4.14.0", - "source": { - "type": "git", - "url": "https://github.com/Behat/Gherkin.git", - "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", - "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.2", - "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*" - }, - "require-dev": { - "cucumber/gherkin-monorepo": "dev-gherkin-v32.1.1", - "friendsofphp/php-cs-fixer": "^3.65", - "mikey179/vfsstream": "^1.6", - "phpstan/extension-installer": "^1", - "phpstan/phpstan": "^2", - "phpstan/phpstan-phpunit": "^2", - "phpunit/phpunit": "^10.5", - "symfony/yaml": "^5.4 || ^6.4 || ^7.0" - }, - "suggest": { - "symfony/yaml": "If you want to parse features, represented in YAML files" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "autoload": { - "psr-4": { - "Behat\\Gherkin\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "https://everzet.com" - } - ], - "description": "Gherkin DSL parser for PHP", - "homepage": "https://behat.org/", - "keywords": [ - "BDD", - "Behat", - "Cucumber", - "DSL", - "gherkin", - "parser" - ], - "support": { - "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.14.0" - }, - "time": "2025-05-23T15:06:40+00:00" - }, - { - "name": "composer/pcre", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" - }, - "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" - }, - "type": "library", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - }, - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-11-12T16:29:46+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-06T16:37:16+00:00" - }, - { - "name": "deptrac/deptrac", - "version": "2.0.7", - "source": { - "type": "git", - "url": "https://github.com/deptrac/deptrac.git", - "reference": "815c349a027ed4f0c866405b783f4d4623f1960c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/deptrac/deptrac/zipball/815c349a027ed4f0c866405b783f4d4623f1960c", - "reference": "815c349a027ed4f0c866405b783f4d4623f1960c", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^8.1" - }, - "suggest": { - "ext-dom": "For using the JUnit output formatter" - }, - "bin": [ - "bin/deptrac", - "deptrac.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Qossmic\\Deptrac\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Deptrac is a static code analysis tool that helps to enforce rules for dependencies between software layers.", - "keywords": [ - "static analysis" - ], - "support": { - "issues": "https://github.com/deptrac/deptrac/issues", - "source": "https://github.com/deptrac/deptrac/tree/2.0.7" - }, - "time": "2025-03-07T14:29:19+00:00" - }, - { - "name": "doctrine/data-fixtures", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "f161e20f04ba5440a09330e156b40f04dd70d47f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/f161e20f04ba5440a09330e156b40f04dd70d47f", - "reference": "f161e20f04ba5440a09330e156b40f04dd70d47f", - "shasum": "" - }, - "require": { - "doctrine/persistence": "^3.1 || ^4.0", - "php": "^8.1", - "psr/log": "^1.1 || ^2 || ^3" - }, - "conflict": { - "doctrine/dbal": "<3.5 || >=5", - "doctrine/orm": "<2.14 || >=4", - "doctrine/phpcr-odm": "<1.3.0" - }, - "require-dev": { - "doctrine/coding-standard": "^13", - "doctrine/dbal": "^3.5 || ^4", - "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", - "doctrine/orm": "^2.14 || ^3", - "ext-sqlite3": "*", - "fig/log-test": "^1", - "phpstan/phpstan": "2.1.17", - "phpunit/phpunit": "10.5.45", - "symfony/cache": "^6.4 || ^7", - "symfony/var-exporter": "^6.4 || ^7" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", - "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", - "doctrine/orm": "For loading ORM fixtures", - "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\DataFixtures\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Data Fixtures for all Doctrine Object Managers", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "database" - ], - "support": { - "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", - "type": "tidelift" - } - ], - "time": "2025-07-08T17:48:20+00:00" - }, - { - "name": "doctrine/doctrine-fixtures-bundle", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", - "reference": "a06db6b81ff20a2980bf92063d80c013bb8b4b7c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/a06db6b81ff20a2980bf92063d80c013bb8b4b7c", - "reference": "a06db6b81ff20a2980bf92063d80c013bb8b4b7c", - "shasum": "" - }, - "require": { - "doctrine/data-fixtures": "^2.0", - "doctrine/doctrine-bundle": "^2.2", - "doctrine/orm": "^2.14.0 || ^3.0", - "doctrine/persistence": "^2.4 || ^3.0 || ^4.0", - "php": "^8.1", - "psr/log": "^2 || ^3", - "symfony/config": "^6.4 || ^7.0", - "symfony/console": "^6.4 || ^7.0", - "symfony/dependency-injection": "^6.4 || ^7.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^6.4.16 || ^7.1.9", - "symfony/http-kernel": "^6.4 || ^7.0" - }, - "conflict": { - "doctrine/dbal": "< 3" - }, - "require-dev": { - "doctrine/coding-standard": "13.0.0", - "phpstan/phpstan": "2.1.11", - "phpunit/phpunit": "^10.5.38 || 11.4.14" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\FixturesBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Doctrine Project", - "homepage": "https://www.doctrine-project.org" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DoctrineFixturesBundle", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "Fixture", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", - "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/4.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-fixtures-bundle", - "type": "tidelift" - } - ], - "time": "2025-03-26T10:56:26+00:00" - }, - { - "name": "friends-of-behat/symfony-extension", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfBehat/SymfonyExtension.git", - "reference": "3ed86d77923be089d67d952e7b75af48fec42e22" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfBehat/SymfonyExtension/zipball/3ed86d77923be089d67d952e7b75af48fec42e22", - "reference": "3ed86d77923be089d67d952e7b75af48fec42e22", - "shasum": "" - }, - "require": { - "behat/behat": "^3.22", - "php": "^8.1", - "symfony/dependency-injection": "^6.4 || ^7.0", - "symfony/http-kernel": "^6.4 || ^7.0" - }, - "require-dev": { - "behat/mink": "^1.9", - "behat/mink-browserkit-driver": "^2.0", - "behat/mink-selenium2-driver": "^1.3", - "friends-of-behat/mink-extension": "^2.5", - "friends-of-behat/page-object-extension": "^0.3.2", - "friends-of-behat/service-container-extension": "^1.1", - "sylius-labs/coding-standard": ">=4.1.1, <=4.2.1", - "symfony/browser-kit": "^6.4 || ^7.0", - "symfony/framework-bundle": "^6.4 || ^7.0", - "symfony/process": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0", - "vimeo/psalm": "^6.0" - }, - "suggest": { - "behat/mink": "^1.9", - "behat/mink-browserkit-driver": "^2.0", - "friends-of-behat/mink-extension": "^2.5" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "FriendsOfBehat\\SymfonyExtension\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kamil Kokot", - "email": "kamil@kokot.me", - "homepage": "https://kamilkokot.com" - } - ], - "description": "Integrates Behat with Symfony.", - "support": { - "issues": "https://github.com/FriendsOfBehat/SymfonyExtension/issues", - "source": "https://github.com/FriendsOfBehat/SymfonyExtension/tree/v2.6.2" - }, - "time": "2025-06-03T13:32:20+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.13.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-08-01T08:46:24+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.6.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" - }, - "time": "2025-08-13T20:13:15+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.30", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d", - "reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2025-10-02T16:07:52+00:00" - }, - { - "name": "phpstan/phpstan-doctrine", - "version": "2.0.10", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-doctrine.git", - "reference": "5eaf37b87288474051469aee9f937fc9d862f330" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/5eaf37b87288474051469aee9f937fc9d862f330", - "reference": "5eaf37b87288474051469aee9f937fc9d862f330", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.13" - }, - "conflict": { - "doctrine/collections": "<1.0", - "doctrine/common": "<2.7", - "doctrine/mongodb-odm": "<1.2", - "doctrine/orm": "<2.5", - "doctrine/persistence": "<1.3" - }, - "require-dev": { - "cache/array-adapter": "^1.1", - "composer/semver": "^3.3.2", - "cweagans/composer-patches": "^1.7.3", - "doctrine/annotations": "^2.0", - "doctrine/collections": "^1.6 || ^2.1", - "doctrine/common": "^2.7 || ^3.0", - "doctrine/dbal": "^3.3.8", - "doctrine/lexer": "^2.0 || ^3.0", - "doctrine/mongodb-odm": "^2.4.3", - "doctrine/orm": "^2.16.0", - "doctrine/persistence": "^2.2.1 || ^3.2", - "gedmo/doctrine-extensions": "^3.8", - "nesbot/carbon": "^2.49", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^2.0.2", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6.20", - "ramsey/uuid": "^4.2", - "symfony/cache": "^5.4", - "symfony/uid": "^5.4 || ^6.4 || ^7.3" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Doctrine extensions for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-doctrine/issues", - "source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.10" - }, - "time": "2025-10-06T10:01:02+00:00" - }, - { - "name": "phpstan/phpstan-symfony", - "version": "2.0.8", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "8820c22d785c235f69bb48da3d41e688bc8a1796" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/8820c22d785c235f69bb48da3d41e688bc8a1796", - "reference": "8820c22d785c235f69bb48da3d41e688bc8a1796", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.13" - }, - "conflict": { - "symfony/framework-bundle": "<3.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "psr/container": "1.1.2", - "symfony/config": "^5.4 || ^6.1", - "symfony/console": "^5.4 || ^6.1", - "symfony/dependency-injection": "^5.4 || ^6.1", - "symfony/form": "^5.4 || ^6.1", - "symfony/framework-bundle": "^5.4 || ^6.1", - "symfony/http-foundation": "^5.4 || ^6.1", - "symfony/messenger": "^5.4", - "symfony/polyfill-php80": "^1.24", - "symfony/serializer": "^5.4", - "symfony/service-contracts": "^2.2.0" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Lukáš Unger", - "email": "looky.msc@gmail.com", - "homepage": "https://lookyman.net" - } - ], - "description": "Symfony Framework extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-symfony/issues", - "source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.8" - }, - "time": "2025-09-07T06:55:50+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "12.4.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c", - "reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.6.1", - "php": ">=8.3", - "phpunit/php-file-iterator": "^6.0", - "phpunit/php-text-template": "^5.0", - "sebastian/complexity": "^5.0", - "sebastian/environment": "^8.0.3", - "sebastian/lines-of-code": "^4.0", - "sebastian/version": "^6.0", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.3.7" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "12.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.4.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", - "type": "tidelift" - } - ], - "time": "2025-09-24T13:44:41+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "961bc913d42fe24a257bfff826a5068079ac7782" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", - "reference": "961bc913d42fe24a257bfff826a5068079ac7782", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:58:37+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", - "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^12.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:58:58+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:59:16+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "8.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", - "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:59:38+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "12.4.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f62aab5794e36ccd26860db2d1bbf89ac19028d9", - "reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.3", - "phpunit/php-code-coverage": "^12.4.0", - "phpunit/php-file-iterator": "^6.0.0", - "phpunit/php-invoker": "^6.0.0", - "phpunit/php-text-template": "^5.0.0", - "phpunit/php-timer": "^8.0.0", - "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.3", - "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.3", - "sebastian/exporter": "^7.0.2", - "sebastian/global-state": "^8.0.2", - "sebastian/object-enumerator": "^7.0.0", - "sebastian/type": "^6.0.3", - "sebastian/version": "^6.0.0", - "staabm/side-effects-detector": "^1.0.5" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "12.4-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.0" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2025-10-03T04:28:03+00:00" - }, - { - "name": "rector/rector", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/rectorphp/rector.git", - "reference": "e1aaf3061e9ae9342ed0824865e3a3360defddeb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/e1aaf3061e9ae9342ed0824865e3a3360defddeb", - "reference": "e1aaf3061e9ae9342ed0824865e3a3360defddeb", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.26" - }, - "conflict": { - "rector/rector-doctrine": "*", - "rector/rector-downgrade-php": "*", - "rector/rector-phpunit": "*", - "rector/rector-symfony": "*" - }, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" - }, - "bin": [ - "bin/rector" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Instant Upgrade and Automated Refactoring of any PHP code", - "homepage": "https://getrector.com/", - "keywords": [ - "automation", - "dev", - "migration", - "refactoring" - ], - "support": { - "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.1" - }, - "funding": [ - { - "url": "https://github.com/tomasvotruba", - "type": "github" - } - ], - "time": "2025-10-06T21:25:14+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "4.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", - "type": "tidelift" - } - ], - "time": "2025-09-14T09:36:45+00:00" - }, - { - "name": "sebastian/comparator", - "version": "7.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.3", - "sebastian/diff": "^7.0", - "sebastian/exporter": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^12.2" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2025-08-20T11:27:00+00:00" - }, - { - "name": "sebastian/complexity", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", - "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:55:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "7.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7ab1ea946c012266ca32390913653d844ecd085f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", - "reference": "7ab1ea946c012266ca32390913653d844ecd085f", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0", - "symfony/process": "^7.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:55:46+00:00" - }, - { - "name": "sebastian/environment", - "version": "8.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", - "type": "tidelift" - } - ], - "time": "2025-08-12T14:11:56+00:00" - }, - { - "name": "sebastian/exporter", - "version": "7.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.3", - "sebastian/recursion-context": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" - } - ], - "time": "2025-09-24T06:16:11+00:00" - }, - { - "name": "sebastian/global-state", - "version": "8.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ef1377171613d09edd25b7816f05be8313f9115d", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d", - "shasum": "" - }, - "require": { - "php": ">=8.3", - "sebastian/object-reflector": "^5.0", - "sebastian/recursion-context": "^7.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", - "type": "tidelift" - } - ], - "time": "2025-08-29T11:29:25+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:57:28+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "7.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", - "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", - "shasum": "" - }, - "require": { - "php": ">=8.3", - "sebastian/object-reflector": "^5.0", - "sebastian/recursion-context": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:57:48+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "4bfa827c969c98be1e527abd576533293c634f6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", - "reference": "4bfa827c969c98be1e527abd576533293c634f6a", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T04:58:17+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "7.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", - "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" - } - ], - "time": "2025-08-13T04:44:59+00:00" - }, - { - "name": "sebastian/type", - "version": "6.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "require-dev": { - "phpunit/phpunit": "^12.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/6.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" - } - ], - "time": "2025-08-09T06:57:12+00:00" - }, - { - "name": "sebastian/version", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", - "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", - "shasum": "" - }, - "require": { - "php": ">=8.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-02-07T05:00:38+00:00" - }, - { - "name": "shipmonk/composer-dependency-analyser", - "version": "1.8.3", - "source": { - "type": "git", - "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", - "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/ca6b2725cd4854d97c1ce08e6954a74fbdd25372", - "reference": "ca6b2725cd4854d97c1ce08e6954a74fbdd25372", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.6.0", - "ergebnis/composer-normalize": "^2.19.0", - "ext-dom": "*", - "ext-libxml": "*", - "phpcompatibility/php-compatibility": "^9.3.5", - "phpstan/phpstan": "^1.12.3", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", - "shipmonk/name-collision-detector": "^2.1.1", - "slevomat/coding-standard": "^8.15.0" - }, - "bin": [ - "bin/composer-dependency-analyser" - ], - "type": "library", - "autoload": { - "psr-4": { - "ShipMonk\\ComposerDependencyAnalyser\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Fast detection of composer dependency issues (dead dependencies, shadow dependencies, misplaced dependencies)", - "keywords": [ - "analyser", - "composer", - "composer dependency", - "dead code", - "dead dependency", - "detector", - "dev", - "misplaced dependency", - "shadow dependency", - "static analysis", - "unused code", - "unused dependency" - ], - "support": { - "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", - "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.3" - }, - "time": "2025-02-10T13:31:57+00:00" - }, - { - "name": "staabm/side-effects-detector", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" - ], - "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" - }, - "funding": [ - { - "url": "https://github.com/staabm", - "type": "github" - } - ], - "time": "2024-10-20T05:08:20+00:00" - }, - { - "name": "symfony/maker-bundle", - "version": "v1.64.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/maker-bundle.git", - "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c86da84640b0586e92aee2b276ee3638ef2f425a", - "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a", - "shasum": "" - }, - "require": { - "doctrine/inflector": "^2.0", - "nikic/php-parser": "^5.0", - "php": ">=8.1", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0" - }, - "conflict": { - "doctrine/doctrine-bundle": "<2.10", - "doctrine/orm": "<2.15" - }, - "require-dev": { - "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.5.0", - "doctrine/orm": "^2.15|^3", - "symfony/http-client": "^6.4|^7.0", - "symfony/phpunit-bridge": "^6.4.1|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/security-http": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "twig/twig": "^3.0|^4.x-dev" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MakerBundle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", - "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", - "keywords": [ - "code generator", - "dev", - "generator", - "scaffold", - "scaffolding" - ], - "support": { - "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.64.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-23T16:12:08+00:00" - }, - { - "name": "symfony/process", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "e0a87c9a60045a354b041db2ea3cf047bf0b15f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e0a87c9a60045a354b041db2ea3cf047bf0b15f5", - "reference": "e0a87c9a60045a354b041db2ea3cf047bf0b15f5", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:29:33+00:00" - }, - { - "name": "symfony/translation", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "00b927b4948d49afbf5013411c0a91a1cea8b087" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/00b927b4948d49afbf5013411c0a91a1cea8b087", - "reference": "00b927b4948d49afbf5013411c0a91a1cea8b087", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" - }, - "conflict": { - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" - }, - "provide": { - "symfony/translation-implementation": "2.3|3.0" - }, - "require-dev": { - "nikic/php-parser": "^4.18|^5.0", - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to internationalize your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-30T17:31:35+00:00" - }, - { - "name": "symfony/web-profiler-bundle", - "version": "v7.2.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "ac9d18238b37e7855ef1b0267b3540565cc95f5d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/ac9d18238b37e7855ef1b0267b3540565cc95f5d", - "reference": "ac9d18238b37e7855ef1b0267b3540565cc95f5d", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/config": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/twig-bundle": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "conflict": { - "symfony/form": "<6.4", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/serializer": "<7.2" - }, - "require-dev": { - "symfony/browser-kit": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\WebProfilerBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a development tool that gives detailed information about the execution of any request", - "homepage": "https://symfony.com", - "keywords": [ - "dev" - ], - "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.2.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-26T14:12:01+00:00" - }, - { - "name": "symplify/easy-coding-standard", - "version": "12.6.0", - "source": { - "type": "git", - "url": "https://github.com/easy-coding-standard/easy-coding-standard.git", - "reference": "781e6124dc7e14768ae999a8f5309566bbe62004" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/781e6124dc7e14768ae999a8f5309566bbe62004", - "reference": "781e6124dc7e14768ae999a8f5309566bbe62004", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "conflict": { - "friendsofphp/php-cs-fixer": "<3.46", - "phpcsstandards/php_codesniffer": "<3.8", - "symplify/coding-standard": "<12.1" - }, - "suggest": { - "ext-dom": "Needed to support checkstyle output format in class CheckstyleOutputFormatter" - }, - "bin": [ - "bin/ecs" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer", - "keywords": [ - "Code style", - "automation", - "fixer", - "static analysis" - ], - "support": { - "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", - "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.6.0" - }, - "funding": [ - { - "url": "https://www.paypal.me/rectorphp", - "type": "custom" - }, - { - "url": "https://github.com/tomasvotruba", - "type": "github" - } - ], - "time": "2025-09-10T14:21:58+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:36:25+00:00" - }, - { - "name": "tomasvotruba/class-leak", - "version": "1.2.7", - "source": { - "type": "git", - "url": "https://github.com/TomasVotruba/class-leak.git", - "reference": "119d9fb16d4a90114d335b5e7a48cba32d0f30b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/TomasVotruba/class-leak/zipball/119d9fb16d4a90114d335b5e7a48cba32d0f30b4", - "reference": "119d9fb16d4a90114d335b5e7a48cba32d0f30b4", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "bin": [ - "bin/class-leak", - "bin/class-leak.php" - ], - "type": "library", - "autoload": { - "psr-4": { - "TomasVotruba\\ClassLeak\\": "app" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Detect leaking classes", - "support": { - "issues": "https://github.com/TomasVotruba/class-leak/issues", - "source": "https://github.com/TomasVotruba/class-leak/tree/1.2.7" - }, - "funding": [ - { - "url": "https://www.paypal.me/rectorphp", - "type": "custom" - }, - { - "url": "https://github.com/tomasvotruba", - "type": "github" - } - ], - "time": "2024-12-09T11:29:49+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": ">=8.4", - "ext-ctype": "*", - "ext-dom": "*", - "ext-iconv": "*" - }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" -} diff --git a/apps/api-legacy/config/bundles.php b/apps/api-legacy/config/bundles.php deleted file mode 100644 index 9366ef9..0000000 --- a/apps/api-legacy/config/bundles.php +++ /dev/null @@ -1,19 +0,0 @@ - ['all' => true], - Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], - Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], - Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], - Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], - Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], - Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], - Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], - Gesdinet\JWTRefreshTokenBundle\GesdinetJWTRefreshTokenBundle::class => ['all' => true], - Sentry\SentryBundle\SentryBundle::class => ['prod' => true], - Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], - FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true], - Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], -]; diff --git a/apps/api-legacy/config/doctrine/Aggregator/Entity.Article.orm.xml b/apps/api-legacy/config/doctrine/Aggregator/Entity.Article.orm.xml deleted file mode 100644 index 3608637..0000000 --- a/apps/api-legacy/config/doctrine/Aggregator/Entity.Article.orm.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/Aggregator/Entity.Source.orm.xml b/apps/api-legacy/config/doctrine/Aggregator/Entity.Source.orm.xml deleted file mode 100644 index e410c11..0000000 --- a/apps/api-legacy/config/doctrine/Aggregator/Entity.Source.orm.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Link.orm.xml b/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Link.orm.xml deleted file mode 100644 index c54e426..0000000 --- a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Link.orm.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.ReadingTime.orm.xml b/apps/api-legacy/config/doctrine/Aggregator/ValueObject.ReadingTime.orm.xml deleted file mode 100644 index 5012976..0000000 --- a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.ReadingTime.orm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Scoring.Credibility.orm.xml b/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Scoring.Credibility.orm.xml deleted file mode 100644 index b0af076..0000000 --- a/apps/api-legacy/config/doctrine/Aggregator/ValueObject.Scoring.Credibility.orm.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/FeedManagement/Entity.Bookmark.orm.xml b/apps/api-legacy/config/doctrine/FeedManagement/Entity.Bookmark.orm.xml deleted file mode 100644 index 1155df7..0000000 --- a/apps/api-legacy/config/doctrine/FeedManagement/Entity.Bookmark.orm.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/FeedManagement/Entity.Comment.orm.xml b/apps/api-legacy/config/doctrine/FeedManagement/Entity.Comment.orm.xml deleted file mode 100644 index ce86c1e..0000000 --- a/apps/api-legacy/config/doctrine/FeedManagement/Entity.Comment.orm.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/FeedManagement/Entity.FollowedSource.orm.xml b/apps/api-legacy/config/doctrine/FeedManagement/Entity.FollowedSource.orm.xml deleted file mode 100644 index 85d5b42..0000000 --- a/apps/api-legacy/config/doctrine/FeedManagement/Entity.FollowedSource.orm.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginAttempt.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginAttempt.orm.xml deleted file mode 100644 index 4727a29..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginAttempt.orm.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginHistory.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginHistory.orm.xml deleted file mode 100644 index 2be3bcf..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.LoginHistory.orm.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.RefreshToken.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.RefreshToken.orm.xml deleted file mode 100644 index 79f1b3a..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.RefreshToken.orm.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.User.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.User.orm.xml deleted file mode 100644 index 8d458e6..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.User.orm.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.VerificationToken.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.VerificationToken.orm.xml deleted file mode 100644 index 3680159..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/Entity.VerificationToken.orm.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Roles.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Roles.orm.xml deleted file mode 100644 index 634d0e8..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Roles.orm.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Secret.GeneratedToken.orm.xml b/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Secret.GeneratedToken.orm.xml deleted file mode 100644 index 0a2068b..0000000 --- a/apps/api-legacy/config/doctrine/IdentityAndAccess/ValueObject.Secret.GeneratedToken.orm.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.Device.orm.xml b/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.Device.orm.xml deleted file mode 100644 index ea43c28..0000000 --- a/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.Device.orm.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.GeoLocation.orm.xml b/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.GeoLocation.orm.xml deleted file mode 100644 index 81beb76..0000000 --- a/apps/api-legacy/config/doctrine/SharedKernel/ValueObject.Tracking.GeoLocation.orm.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - diff --git a/apps/api-legacy/config/migrations/Version20251019151441.php b/apps/api-legacy/config/migrations/Version20251019151441.php deleted file mode 100644 index 7fc86f3..0000000 --- a/apps/api-legacy/config/migrations/Version20251019151441.php +++ /dev/null @@ -1,291 +0,0 @@ - - */ -final class Version20251019151441 extends AbstractMigration -{ - public function getDescription(): string - { - return 'initial postgresql schema'; - } - - public function up(Schema $schema): void - { - $this->addSql("CREATE EXTENSION IF NOT EXISTS pg_trgm;"); // for trigram indexes (links, titles, etc.) - $this->addSql("SET SESSION TIME ZONE 'UTC';"); - - // -- ---------- TABLE: article ---------- - $this->addSql(<<>'image')) STORED, - excerpt VARCHAR(255) GENERATED ALWAYS AS ((LEFT(body, 200) || '...')) STORED, - published_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, - crawled_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, - updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, - link VARCHAR(1024) NOT NULL, - bias VARCHAR(30) DEFAULT 'neutral' NOT NULL, - reliability VARCHAR(30) DEFAULT 'reliable' NOT NULL, - transparency VARCHAR(30) DEFAULT 'medium' NOT NULL, - reading_time INT DEFAULT 1, - CONSTRAINT CHK_ARTICLE_READING_TIME CHECK (reading_time >= 0), - CONSTRAINT CHK_ARTICLE_SENTIMENT CHECK (sentiment IN ('positive','neutral','negative')), - CONSTRAINT CHK_ARTICLE_METADATA_JSON CHECK (metadata IS NULL OR JSONB_TYPEOF(metadata) IN ('object','array')), - PRIMARY KEY (id) - ) - SQL - ); - $this->addSql('CREATE INDEX IDX_23A0E66953C1C61 ON article (source_id)'); - $this->addSql('CREATE INDEX IDX_ARTICLE_PUBLISHED_AT ON article (published_at DESC)'); - $this->addSql('CREATE INDEX IDX_ARTICLE_PUBLISHED_ID ON article (published_at DESC, id DESC)'); - $this->addSql('CREATE UNIQUE INDEX UNQ_ARTICLE_HASH ON article (hash)'); - $this->addSql(<<addSql('CREATE INDEX GIN_ARTICLE_TSV ON article USING GIN(tsv)'); - $this->addSql('CREATE INDEX GIN_ARTICLE_LINK_TRGM ON article USING GIN (link gin_trgm_ops)'); - $this->addSql('CREATE INDEX GIN_ARTICLE_TITLE_TRGM ON article USING GIN (title gin_trgm_ops)'); - $this->addSql('CREATE INDEX GIN_ARTICLE_CATEGORIES ON article USING GIN (categories)'); - $this->addSql("COMMENT ON COLUMN article.id IS '(DC2Type:article_id)';"); - $this->addSql("COMMENT ON COLUMN article.source_id IS '(DC2Type:source_id)';"); - $this->addSql("COMMENT ON COLUMN article.published_at IS '(DC2Type:datetime_immutable)'"); - $this->addSql("COMMENT ON COLUMN article.crawled_at IS '(DC2Type:datetime_immutable)'"); - $this->addSql("COMMENT ON COLUMN article.updated_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: bookmark ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_DA62921DA76ED395 ON bookmark (user_id)'); - $this->addSql('CREATE INDEX IDX_BOOKMARK_USER_CREATED ON bookmark (user_id, created_at DESC)'); - $this->addSql("COMMENT ON COLUMN bookmark.id IS '(DC2Type:bookmark_id)'"); - $this->addSql("COMMENT ON COLUMN bookmark.user_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN bookmark.created_at IS '(DC2Type:datetime_immutable)'"); - $this->addSql("COMMENT ON COLUMN bookmark.updated_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: bookmark_article ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_6FE2655D92741D25 ON bookmark_article (bookmark_id)'); - $this->addSql('CREATE INDEX IDX_6FE2655D7294869C ON bookmark_article (article_id)'); - $this->addSql("COMMENT ON COLUMN bookmark_article.bookmark_id IS '(DC2Type:bookmark_id)'"); - $this->addSql("COMMENT ON COLUMN bookmark_article.article_id IS '(DC2Type:article_id)'"); - - // -- ---------- TABLE: comment ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_9474526CA76ED395 ON comment (user_id)'); - $this->addSql('CREATE INDEX IDX_9474526C7294869C ON comment (article_id)'); - $this->addSql('CREATE INDEX IDX_COMMENT_ARTICLE_CREATED ON comment (article_id, created_at DESC)'); - $this->addSql("COMMENT ON COLUMN comment.id IS '(DC2Type:comment_id)'"); - $this->addSql("COMMENT ON COLUMN comment.user_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN comment.article_id IS '(DC2Type:article_id)'"); - $this->addSql("COMMENT ON COLUMN comment.created_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: followed_source ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_7A763A3EAC24F853 ON followed_source (follower_id)'); - $this->addSql('CREATE INDEX IDX_7A763A3E953C1C61 ON followed_source (source_id)'); - $this->addSql('CREATE INDEX IDX_FOLLOWED_SOURCE_FOLLOWER_CREATED ON followed_source (follower_id, created_at DESC)'); - $this->addSql("COMMENT ON COLUMN followed_source.id IS '(DC2Type:followed_source_id)'"); - $this->addSql("COMMENT ON COLUMN followed_source.follower_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN followed_source.source_id IS '(DC2Type:source_id)'"); - $this->addSql("COMMENT ON COLUMN followed_source.created_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: login_attempt ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_8C11C1BA76ED395 ON login_attempt (user_id)'); - $this->addSql('CREATE INDEX IDX_LOGIN_ATTEMPT_CREATED_AT ON login_attempt (created_at DESC)'); - $this->addSql("COMMENT ON COLUMN login_attempt.id IS '(DC2Type:login_attempt_id)'"); - $this->addSql("COMMENT ON COLUMN login_attempt.user_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN login_attempt.created_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: login_history ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_37976E36A76ED395 ON login_history (user_id)'); - $this->addSql('CREATE INDEX IDX_LOGIN_HISTORY_CREATED_AT ON login_history (user_id, created_at DESC)'); - $this->addSql('CREATE INDEX IDX_LOGIN_HISTORY_IP_ADDRESS ON login_history (ip_address)'); - $this->addSql("COMMENT ON COLUMN login_history.id IS '(DC2Type:login_history_id)'"); - $this->addSql("COMMENT ON COLUMN login_history.user_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN login_history.created_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: refresh_tokens ---------- - $this->addSql('CREATE SEQUENCE refresh_tokens_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); - $this->addSql(<<addSql('CREATE UNIQUE INDEX UNIQ_9BACE7E1C74F2195 ON refresh_tokens (refresh_token)'); - - // -- ---------- TABLE: source ---------- - $this->addSql(<<addSql('CREATE UNIQUE INDEX UNQ_SOURCE_NAME ON source (LOWER(name))'); - $this->addSql('CREATE UNIQUE INDEX UNQ_SOURCE_URL ON source (LOWER(url))'); - $this->addSql("COMMENT ON COLUMN source.id IS '(DC2Type:source_id)'"); - $this->addSql("COMMENT ON COLUMN source.updated_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: user ---------- - $this->addSql(<<addSql(<<addSql("COMMENT ON COLUMN \"user\".id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN \"user\".created_at IS '(DC2Type:datetime_immutable)'"); - $this->addSql("COMMENT ON COLUMN \"user\".updated_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- TABLE: verification_token ---------- - $this->addSql(<<addSql('CREATE INDEX IDX_C1CC006BA76ED395 ON verification_token (user_id)'); - $this->addSql('CREATE INDEX IDX_VERIF_TOKEN_CREATED_AT ON verification_token (created_at DESC)'); - $this->addSql('CREATE UNIQUE INDEX UNQ_VERIF_USER_PURPOSE_TOKEN ON verification_token (user_id, purpose) WHERE token IS NOT NULL'); - $this->addSql("COMMENT ON COLUMN verification_token.id IS '(DC2Type:verification_token_id)'"); - $this->addSql("COMMENT ON COLUMN verification_token.user_id IS '(DC2Type:user_id)'"); - $this->addSql("COMMENT ON COLUMN verification_token.created_at IS '(DC2Type:datetime_immutable)'"); - - // -- ---------- FOREIGN KEY CONSTRAINTS ---------- - $this->addSql('ALTER TABLE article ADD CONSTRAINT FK_23A0E66953C1C61 FOREIGN KEY (source_id) REFERENCES source (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE bookmark ADD CONSTRAINT FK_DA62921DA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE bookmark_article ADD CONSTRAINT FK_6FE2655D92741D25 FOREIGN KEY (bookmark_id) REFERENCES bookmark (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE bookmark_article ADD CONSTRAINT FK_6FE2655D7294869C FOREIGN KEY (article_id) REFERENCES article (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526CA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C7294869C FOREIGN KEY (article_id) REFERENCES article (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE followed_source ADD CONSTRAINT FK_7A763A3EAC24F853 FOREIGN KEY (follower_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE followed_source ADD CONSTRAINT FK_7A763A3E953C1C61 FOREIGN KEY (source_id) REFERENCES source (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE login_attempt ADD CONSTRAINT FK_8C11C1BA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE login_history ADD CONSTRAINT FK_37976E36A76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE verification_token ADD CONSTRAINT FK_C1CC006BA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } - - public function down(Schema $schema): void - { - throw new IrreversibleMigration('Sometimes in life you have to accept that you can\'t go back.'); - } -} diff --git a/apps/api-legacy/config/migrations/Version20251024234318.php b/apps/api-legacy/config/migrations/Version20251024234318.php deleted file mode 100644 index a4aedec..0000000 --- a/apps/api-legacy/config/migrations/Version20251024234318.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final class Version20251024234318 extends AbstractMigration -{ - public function getDescription(): string - { - return 'add token statistics to article'; - } - - public function up(Schema $schema): void - { - $this->addSql('ALTER TABLE article ADD token_statistics JSONB DEFAULT NULL'); - } - - public function down(Schema $schema): void - { - $this->addSql('ALTER TABLE article DROP token_statistics'); - } -} diff --git a/apps/api-legacy/config/packages/cache.yaml b/apps/api-legacy/config/packages/cache.yaml deleted file mode 100644 index 7f85014..0000000 --- a/apps/api-legacy/config/packages/cache.yaml +++ /dev/null @@ -1,5 +0,0 @@ -framework: - cache: - pools: - cache.dbal: - adapter: cache.adapter.filesystem diff --git a/apps/api-legacy/config/packages/dev/maker.yaml b/apps/api-legacy/config/packages/dev/maker.yaml deleted file mode 100644 index d899628..0000000 --- a/apps/api-legacy/config/packages/dev/maker.yaml +++ /dev/null @@ -1,2 +0,0 @@ -maker: - root_namespace: Basango diff --git a/apps/api-legacy/config/packages/doctrine.yaml b/apps/api-legacy/config/packages/doctrine.yaml deleted file mode 100644 index 0f47178..0000000 --- a/apps/api-legacy/config/packages/doctrine.yaml +++ /dev/null @@ -1,338 +0,0 @@ -doctrine: - dbal: - connections: - default: - url: '%env(resolve:DATABASE_URL)%' - server_version: '16' - profiling_collect_backtrace: false - idle_connection_ttl: 172800 - use_savepoints: true - result_cache: 'cache.dbal' - mapping_types: - # Array type mappings - 'bool[]': 'bool[]' - _bool: 'bool[]' - 'smallint[]': 'smallint[]' - _int2: 'smallint[]' - 'integer[]': 'integer[]' - _int4: 'integer[]' - 'bigint[]': 'bigint[]' - _int8: 'bigint[]' - 'double precision[]': 'double precision[]' - _float8: 'double precision[]' - 'real[]': 'real[]' - _float4: 'real[]' - 'text[]': 'text[]' - _text: 'text[]' - - # JSON type mappings - jsonb: jsonb - 'jsonb[]': 'jsonb[]' - _jsonb: 'jsonb[]' - - # Network type mappings - cidr: cidr - 'cidr[]': 'cidr[]' - _cidr: 'cidr[]' - inet: inet - 'inet[]': 'inet[]' - _inet: 'inet[]' - macaddr: macaddr - 'macaddr[]': 'macaddr[]' - _macaddr: 'macaddr[]' - - # Spatial type mappings - point: point - 'point[]': 'point[]' - _point: 'point[]' - geometry: geometry - 'geometry[]': 'geometry[]' - _geometry: 'geometry[]' - geography: geography - 'geography[]': 'geography[]' - _geography: 'geography[]' - - # Range type mappings - daterange: daterange - int4range: int4range - int8range: int8range - numrange: numrange - tsrange: tsrange - tstzrange: tstzrange - - # Hierarchical type mappings - ltree: ltree - types: - # Shared Kernel - email: Basango\SharedKernel\Infrastructure\Persistence\Doctrine\DBAL\Types\EmailType - - # Aggregator - article_id: Basango\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\ArticleIdType - source_id: Basango\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\SourceIdType - open_graph: Basango\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\OpenGraphType - token_statistics: Basango\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\TokenStatisticsType - - # Identity and Access - user_id: Basango\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\UserIdType - login_attempt_id: Basango\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\LoginAttemptIdType - login_history_id: Basango\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\LoginHistoryIdType - verification_token_id: Basango\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\VerificationTokenIdType - - # FeedManagement - bookmark_id: Basango\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\BookmarkIdType - followed_source_id: Basango\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\FollowedSourceIdType - comment_id: Basango\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\CommentIdType - - # PostgreSQL Specific Types - # Array types - 'bool[]': MartinGeorgiev\Doctrine\DBAL\Types\BooleanArray - 'smallint[]': MartinGeorgiev\Doctrine\DBAL\Types\SmallIntArray - 'integer[]': MartinGeorgiev\Doctrine\DBAL\Types\IntegerArray - 'bigint[]': MartinGeorgiev\Doctrine\DBAL\Types\BigIntArray - 'double precision[]': MartinGeorgiev\Doctrine\DBAL\Types\DoublePrecisionArray - 'real[]': MartinGeorgiev\Doctrine\DBAL\Types\RealArray - 'text[]': MartinGeorgiev\Doctrine\DBAL\Types\TextArray - - # JSON types - jsonb: MartinGeorgiev\Doctrine\DBAL\Types\Jsonb - 'jsonb[]': MartinGeorgiev\Doctrine\DBAL\Types\JsonbArray - - # Network types - cidr: MartinGeorgiev\Doctrine\DBAL\Types\Cidr - 'cidr[]': MartinGeorgiev\Doctrine\DBAL\Types\CidrArray - inet: MartinGeorgiev\Doctrine\DBAL\Types\Inet - 'inet[]': MartinGeorgiev\Doctrine\DBAL\Types\InetArray - macaddr: MartinGeorgiev\Doctrine\DBAL\Types\Macaddr - 'macaddr[]': MartinGeorgiev\Doctrine\DBAL\Types\MacaddrArray - - # Spatial types - point: MartinGeorgiev\Doctrine\DBAL\Types\Point - 'point[]': MartinGeorgiev\Doctrine\DBAL\Types\PointArray - geometry: MartinGeorgiev\Doctrine\DBAL\Types\Geometry - 'geometry[]': MartinGeorgiev\Doctrine\DBAL\Types\GeometryArray - geography: MartinGeorgiev\Doctrine\DBAL\Types\Geography - 'geography[]': MartinGeorgiev\Doctrine\DBAL\Types\GeographyArray - - # Range types - daterange: MartinGeorgiev\Doctrine\DBAL\Types\DateRange - int4range: MartinGeorgiev\Doctrine\DBAL\Types\Int4Range - int8range: MartinGeorgiev\Doctrine\DBAL\Types\Int8Range - numrange: MartinGeorgiev\Doctrine\DBAL\Types\NumRange - tsrange: MartinGeorgiev\Doctrine\DBAL\Types\TsRange - tstzrange: MartinGeorgiev\Doctrine\DBAL\Types\TstzRange - - # Hierarchical types - ltree: MartinGeorgiev\Doctrine\DBAL\Types\Ltree - orm: - auto_generate_proxy_classes: true - enable_lazy_ghost_objects: true - enable_native_lazy_objects: true - entity_managers: - default: - validate_xml_mapping: false - report_fields_where_declared: true - naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware - auto_mapping: true - dql: - string_functions: - # alternative implementation of ALL() and ANY() where subquery is not required, useful for arrays - ALL_OF: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\All - ANY_OF: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Any - - # operators for working with array and json(b) data - GREATEST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest - LEAST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least - CONTAINS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Contains # @> - IS_CONTAINED_BY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IsContainedBy # <@ - OVERLAPS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Overlaps # && - RIGHT_EXISTS_ON_LEFT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TheRightExistsOnTheLeft # ? - ALL_ON_RIGHT_EXIST_ON_LEFT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AllOnTheRightExistOnTheLeft # ?& - ANY_ON_RIGHT_EXISTS_ON_LEFT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AnyOnTheRightExistsOnTheLeft # ?| - RETURNS_VALUE_FOR_JSON_VALUE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ReturnsValueForJsonValue # @? - DELETE_AT_PATH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DeleteAtPath # #- - - # array and string specific functions - IN_ARRAY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\InArray - ANY_VALUE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AnyValue - ARRAY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Arr - ARRAY_APPEND: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAppend - ARRAY_CARDINALITY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayCardinality - ARRAY_CAT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayCat - ARRAY_DIMENSIONS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayDimensions - ARRAY_LENGTH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayLength - ARRAY_NUMBER_OF_DIMENSIONS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayNumberOfDimensions - ARRAY_POSITION: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPosition - ARRAY_POSITIONS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPositions - ARRAY_PREPEND: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPrepend - ARRAY_REMOVE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayRemove - ARRAY_REPLACE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayReplace - ARRAY_SHUFFLE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayShuffle - ARRAY_TO_JSON: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToJson - ARRAY_TO_STRING: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToString - SPLIT_PART: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart - STARTS_WITH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StartsWith - STRING_TO_ARRAY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringToArray - UNNEST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unnest - - # json specific functions - JSON_ARRAY_LENGTH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonArrayLength - JSON_BUILD_OBJECT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonBuildObject - JSON_EACH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonEach - JSON_EACH_TEXT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonEachText - JSON_EXISTS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonExists - JSON_GET_FIELD: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetField - JSON_GET_FIELD_AS_INTEGER: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetFieldAsInteger - JSON_GET_FIELD_AS_TEXT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetFieldAsText - JSON_GET_OBJECT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetObject - JSON_GET_OBJECT_AS_TEXT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetObjectAsText - JSON_OBJECT_KEYS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonObjectKeys - JSON_QUERY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonQuery - JSON_SCALAR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonScalar - JSON_SERIALIZE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonSerialize - JSON_STRIP_NULLS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonStripNulls - JSON_TYPEOF: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonTypeof - JSON_VALUE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonValue - TO_JSON: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToJson - ROW_TO_JSON: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson - - # jsonb specific functions - JSONB_ARRAY_ELEMENTS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayElements - JSONB_ARRAY_ELEMENTS_TEXT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayElementsText - JSONB_ARRAY_LENGTH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayLength - JSONB_BUILD_OBJECT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbBuildObject - JSONB_EACH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbEach - JSONB_EACH_TEXT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbEachText - JSONB_EXISTS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbExists - JSONB_INSERT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbInsert - JSONB_OBJECT_KEYS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectKeys - JSONB_PATH_EXISTS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathExists - JSONB_PATH_MATCH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathMatch - JSONB_PATH_QUERY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQuery - JSONB_PATH_QUERY_ARRAY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryArray - JSONB_PATH_QUERY_FIRST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryFirst - JSONB_PRETTY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPretty - JSONB_SET: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbSet - JSONB_SET_LAX: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbSetLax - JSONB_STRIP_NULLS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbStripNulls - TO_JSONB: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToJsonb - - # text search specific - TO_TSQUERY: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery - TO_TSVECTOR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsvector - TSMATCH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsmatch - - # date specific functions - DATE_ADD: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateAdd - DATE_BIN: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateBin - DATE_EXTRACT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateExtract - DATE_OVERLAPS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateOverlaps - DATE_SUBTRACT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateSubtract - - # range functions - DATERANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Daterange - INT4RANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int4range - INT8RANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int8range - NUMRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange - TSRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange - TSTZRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange - - # Arithmetic functions - CBRT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cbrt - CEIL: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil - DEGREES: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Degrees - EXP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exp - FLOOR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor - LN: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ln - LOG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Log - PI: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Pi - POWER: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Power - RADIANS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Radians - RANDOM: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Random - ROUND: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round - SIGN: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sign - TRUNC: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc - WIDTH_BUCKET: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WidthBucket - - # other operators - CAST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast - ILIKE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ilike - SIMILAR_TO: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SimilarTo - NOT_SIMILAR_TO: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotSimilarTo - UNACCENT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unaccent - REGEXP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Regexp - IREGEXP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IRegexp - NOT_REGEXP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotRegexp - NOT_IREGEXP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotIRegexp - REGEXP_COUNT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpCount - REGEXP_INSTR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpInstr - REGEXP_LIKE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike - REGEXP_MATCH: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch - REGEXP_REPLACE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace - REGEXP_SUBSTR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr - ROW: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row - STRCONCAT: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat - DISTANCE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance - - # aggregation functions - ARRAY_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAgg - JSON_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonAgg - JSON_OBJECT_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonObjectAgg - JSONB_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbAgg - JSONB_OBJECT_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectAgg - STRING_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringAgg - XML_AGG: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlAgg - - # data type formatting functions - TO_CHAR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToChar - TO_DATE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToDate - TO_NUMBER: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToNumber - TO_TIMESTAMP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTimestamp - mappings: - Aggregator: - is_bundle: false - type: xml - dir: '%kernel.project_dir%/config/doctrine/Aggregator' - prefix: 'Basango\Aggregator\Domain\Model' - IdentityAndAccess: - is_bundle: false - type: xml - dir: '%kernel.project_dir%/config/doctrine/IdentityAndAccess' - prefix: 'Basango\IdentityAndAccess\Domain\Model' - FeedManagement: - is_bundle: false - type: xml - dir: '%kernel.project_dir%/config/doctrine/FeedManagement' - prefix: 'Basango\FeedManagement\Domain\Model' - SharedKernel: - is_bundle: false - type: xml - dir: '%kernel.project_dir%/config/doctrine/SharedKernel' - prefix: 'Basango\SharedKernel\Domain\Model' - controller_resolver: - auto_mapping: false - -when@test: - doctrine: - dbal: - # "TEST_TOKEN" is typically set by ParaTest - dbname_suffix: '_test%env(default::TEST_TOKEN)%' - -when@prod: - doctrine: - orm: - auto_generate_proxy_classes: false - proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' - query_cache_driver: - type: pool - pool: doctrine.system_cache_pool - result_cache_driver: - type: pool - pool: doctrine.result_cache_pool - - framework: - cache: - pools: - doctrine.result_cache_pool: - adapter: cache.app - doctrine.system_cache_pool: - adapter: cache.system diff --git a/apps/api-legacy/config/packages/doctrine_migrations.yaml b/apps/api-legacy/config/packages/doctrine_migrations.yaml deleted file mode 100644 index 6577cf6..0000000 --- a/apps/api-legacy/config/packages/doctrine_migrations.yaml +++ /dev/null @@ -1,6 +0,0 @@ -doctrine_migrations: - migrations_paths: - # namespace is arbitrary but should be different from Basango\Migrations - # as migrations classes should NOT be autoloaded - 'DoctrineMigrations': '%kernel.project_dir%/config/migrations' - enable_profiler: false diff --git a/apps/api-legacy/config/packages/framework.yaml b/apps/api-legacy/config/packages/framework.yaml deleted file mode 100644 index 6d85c29..0000000 --- a/apps/api-legacy/config/packages/framework.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# see https://symfony.com/doc/current/reference/configuration/framework.html -framework: - secret: '%env(APP_SECRET)%' - #csrf_protection: true - http_method_override: false - handle_all_throwables: true - - # Enables session support. Note that the session will ONLY be started if you read or write from it. - # Remove or comment this section to explicitly disable session support. - session: - handler_id: null - cookie_secure: auto - cookie_samesite: lax - storage_factory_id: session.storage.factory.native - - #esi: true - #fragments: true - php_errors: - log: true - -when@test: - framework: - test: true - session: - storage_factory_id: session.storage.factory.mock_file diff --git a/apps/api-legacy/config/packages/gesdinet_jwt_refresh_token.yaml b/apps/api-legacy/config/packages/gesdinet_jwt_refresh_token.yaml deleted file mode 100644 index afd2a71..0000000 --- a/apps/api-legacy/config/packages/gesdinet_jwt_refresh_token.yaml +++ /dev/null @@ -1,4 +0,0 @@ -gesdinet_jwt_refresh_token: - refresh_token_class: Basango\IdentityAndAccess\Domain\Model\Entity\RefreshToken - ttl: 2592000 # 1 month - ttl_update: true diff --git a/apps/api-legacy/config/packages/lexik_jwt_authentication.yaml b/apps/api-legacy/config/packages/lexik_jwt_authentication.yaml deleted file mode 100644 index 89dbe96..0000000 --- a/apps/api-legacy/config/packages/lexik_jwt_authentication.yaml +++ /dev/null @@ -1,5 +0,0 @@ -lexik_jwt_authentication: - secret_key: '%env(resolve:JWT_SECRET_KEY)%' - public_key: '%env(resolve:JWT_PUBLIC_KEY)%' - pass_phrase: '%env(JWT_PASSPHRASE)%' - token_ttl: '%env(resolve:JWT_TTL)%' diff --git a/apps/api-legacy/config/packages/mailer.yaml b/apps/api-legacy/config/packages/mailer.yaml deleted file mode 100644 index 56a650d..0000000 --- a/apps/api-legacy/config/packages/mailer.yaml +++ /dev/null @@ -1,3 +0,0 @@ -framework: - mailer: - dsn: '%env(MAILER_DSN)%' diff --git a/apps/api-legacy/config/packages/messenger.yaml b/apps/api-legacy/config/packages/messenger.yaml deleted file mode 100644 index 56435ee..0000000 --- a/apps/api-legacy/config/packages/messenger.yaml +++ /dev/null @@ -1,39 +0,0 @@ -framework: - messenger: - # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling. - failure_transport: failed - - transports: - # https://symfony.com/doc/current/messenger.html#transport-configuration - async: - dsn: '%env(MESSENGER_TRANSPORT_DSN)%' - retry_strategy: - max_retries: 3 - delay: 1000 - multiplier: 2 - max_delay: 0 - options: - auto_setup: true - failed: - dsn: 'doctrine://default?queue_name=failed' - options: - auto_setup: true - sync: 'sync://' - - routing: - Basango\SharedKernel\Application\Messaging\AsyncMessage: async - Symfony\Component\Mailer\Messenger\SendEmailMessage: sync - - default_bus: command.bus - buses: - command.bus: ~ - query.bus: ~ - message.bus: ~ - -when@test: - framework: - messenger: - transports: - # replace with your transport name here (e.g., my_transport: 'in-memory://') - # For more Messenger testing tools, see https://github.com/zenstruck/messenger-test - async: 'in-memory://' \ No newline at end of file diff --git a/apps/api-legacy/config/packages/monolog.yaml b/apps/api-legacy/config/packages/monolog.yaml deleted file mode 100644 index c33fc5f..0000000 --- a/apps/api-legacy/config/packages/monolog.yaml +++ /dev/null @@ -1,72 +0,0 @@ -monolog: - channels: - - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists - -when@dev: - monolog: - handlers: - main: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - channels: ["!app"] - app: - type: stream - path: "%kernel.logs_dir%/app.%kernel.environment%.log" - level: debug - channels: ["app"] - console: - type: console - level: debug - process_psr_3_messages: false - channels: ["app"] - -when@test: - monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - excluded_http_codes: [404, 405] - channels: ["!event"] - nested: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - -when@prod: - monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - excluded_http_codes: [404, 405] - buffer_size: 50 # How many messages should be saved? Prevent memory leaks - telegram: - type: telegram - level: critical - channels: [ "!event" ] - token: "%env(DEVY_TOKEN)%" - channel: "%env(DEVY_CHANNEL)%" - topic: "%env(int:DEVY_TOPIC)%" - parse_mode: "MarkdownV2" - disable_webpage_preview: true - disable_notification: false - split_long_messages: false - formatter: Basango\SharedKernel\Infrastructure\Framework\Symfony\Logging\TelegramFormatter - nested: - type: rotating_file - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: error - max_files: 10 - console: - type: console - level: info - process_psr_3_messages: false - channels: ["!event", "!doctrine"] - deprecation: - type: stream - channels: [deprecation] - path: "%kernel.logs_dir%/deprecation.log" diff --git a/apps/api-legacy/config/packages/routing.yaml b/apps/api-legacy/config/packages/routing.yaml deleted file mode 100644 index 4b766ce..0000000 --- a/apps/api-legacy/config/packages/routing.yaml +++ /dev/null @@ -1,12 +0,0 @@ -framework: - router: - utf8: true - - # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. - # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands - #default_uri: http://localhost - -when@prod: - framework: - router: - strict_requirements: null diff --git a/apps/api-legacy/config/packages/security.yaml b/apps/api-legacy/config/packages/security.yaml deleted file mode 100644 index 7c32f79..0000000 --- a/apps/api-legacy/config/packages/security.yaml +++ /dev/null @@ -1,62 +0,0 @@ -security: - # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords - password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' - # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider - providers: - app_user_provider: - id: Basango\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\SecurityUserProvider - - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: - - login: - pattern: ^/api/login - stateless: true - json_login: - check_path: /api/login_check - success_handler: lexik_jwt_authentication.handler.authentication_success - failure_handler: lexik_jwt_authentication.handler.authentication_failure - user_checker: Basango\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker - - api: - pattern: ^/api - stateless: true - entry_point: jwt - jwt: ~ - refresh_jwt: - check_path: /api/token/refresh - logout: - path: api_token_invalidate - user_checker: Basango\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker - - main: - lazy: true - provider: app_user_provider - user_checker: Basango\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker - - # Easy way to control access for large sections of your site - # Note: Only the *first* access control that matches will be used - access_control: - - { path: ^/api/register, roles: PUBLIC_ACCESS } - - { path: ^/api/login, roles: PUBLIC_ACCESS } - - { path: ^/api/token/refresh, roles: PUBLIC_ACCESS } - - { path: ^/api/password/(request|reset), roles: PUBLIC_ACCESS } - - { path: ^/api/account/(unlock|confirm), roles: PUBLIC_ACCESS } - - { path: ^/api/aggregator/articles, roles: PUBLIC_ACCESS } - - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } - -when@test: - security: - password_hashers: - # By default, password hashers are resource intensive and take time. This is - # important to generate secure password hashes. In tests however, secure hashes - # are not important, waste resources and increase test times. The following - # reduces the work factor to the lowest possible values. - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: - algorithm: auto - cost: 4 # Lowest possible value for bcrypt - time_cost: 3 # Lowest possible value for argon - memory_cost: 10 # Lowest possible value for argon diff --git a/apps/api-legacy/config/packages/sentry.yaml b/apps/api-legacy/config/packages/sentry.yaml deleted file mode 100644 index edff7ba..0000000 --- a/apps/api-legacy/config/packages/sentry.yaml +++ /dev/null @@ -1,24 +0,0 @@ -when@prod: - sentry: - dsn: "%env(SENTRY_DSN)%" - register_error_listener: false - register_error_handler: false - options: - traces_sample_rate: 0.1 - ignore_exceptions: - - 'Symfony\Component\ErrorHandler\Error\FatalError' - - 'Symfony\Component\Debug\Exception\FatalErrorException' - monolog: - handlers: - sentry_fingers_crossed: - type: fingers_crossed - action_level: error - handler: sentry - excluded_http_codes: [404, 405] - buffer_size: 50 - sentry: - type: sentry - level: !php/const Monolog\Logger::ERROR - hub_id: Sentry\State\HubInterface - fill_extra_context: true - process_psr_3_messages: false diff --git a/apps/api-legacy/config/packages/translation.yaml b/apps/api-legacy/config/packages/translation.yaml deleted file mode 100644 index 0af682d..0000000 --- a/apps/api-legacy/config/packages/translation.yaml +++ /dev/null @@ -1,7 +0,0 @@ -framework: - default_locale: fr - translator: - default_path: '%kernel.project_dir%/translations' - fallbacks: - - en - providers: diff --git a/apps/api-legacy/config/packages/twig.yaml b/apps/api-legacy/config/packages/twig.yaml deleted file mode 100644 index c3f5500..0000000 --- a/apps/api-legacy/config/packages/twig.yaml +++ /dev/null @@ -1,16 +0,0 @@ -twig: - file_name_pattern: '*.twig' - date: - format: 'd M Y' - interval_format: '%d days' - timezone: null - number_format: - decimals: 2 - decimal_point: ',' - thousands_separator: '.' - globals: - 'application': '@Basango\SharedKernel\Domain\Application' - -when@test: - twig: - strict_variables: true diff --git a/apps/api-legacy/config/packages/validator.yaml b/apps/api-legacy/config/packages/validator.yaml deleted file mode 100644 index dd47a6a..0000000 --- a/apps/api-legacy/config/packages/validator.yaml +++ /dev/null @@ -1,11 +0,0 @@ -framework: - validation: - # Enables validator auto-mapping support. - # For instance, basic validation constraints will be inferred from Doctrine's metadata. - #auto_mapping: - # App\Entity\: [] - -when@test: - framework: - validation: - not_compromised_password: false diff --git a/apps/api-legacy/config/packages/web_profiler.yaml b/apps/api-legacy/config/packages/web_profiler.yaml deleted file mode 100644 index 1e039b7..0000000 --- a/apps/api-legacy/config/packages/web_profiler.yaml +++ /dev/null @@ -1,11 +0,0 @@ -when@dev: - web_profiler: - toolbar: true - - framework: - profiler: - collect_serializer_data: true - -when@test: - framework: - profiler: { collect: false } diff --git a/apps/api-legacy/config/preload.php b/apps/api-legacy/config/preload.php deleted file mode 100644 index db37723..0000000 --- a/apps/api-legacy/config/preload.php +++ /dev/null @@ -1,5 +0,0 @@ -withPaths([ - __DIR__ . '/src', - __DIR__ . '/tests', - ]) - - ->withRules([ - NoUnusedImportsFixer::class, - ]) - ->withConfiguredRule(MethodArgumentSpaceFixer::class, [ - 'on_multiline' => 'ensure_fully_multiline', - 'attribute_placement' => 'same_line' - ]) - ->withSkip([ - ConcatSpaceFixer::class - ]) - ->withPreparedSets( - psr12: true, - common: true, - cleanCode: true, - ); \ No newline at end of file diff --git a/apps/api-legacy/patches/monolog-telegram-configuration.patch b/apps/api-legacy/patches/monolog-telegram-configuration.patch deleted file mode 100644 index e76d82b..0000000 --- a/apps/api-legacy/patches/monolog-telegram-configuration.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/vendor/symfony/monolog-bundle/DependencyInjection/Configuration.php 2023-11-06 11:08:12.000000000 +0200 -+++ b/vendor/symfony/monolog-bundle/DependencyInjection/Configuration.php 2024-08-16 05:05:49.286417317 +0200 -@@ -595,6 +595,7 @@ - ->booleanNode('disable_notification')->defaultNull()->end() // telegram - ->booleanNode('split_long_messages')->defaultFalse()->end() // telegram - ->booleanNode('delay_between_messages')->defaultFalse()->end() // telegram -+ ->integerNode('topic')->defaultNull()->end() // telegram - ->integerNode('factor')->defaultValue(1)->min(1)->end() // sampling - ->arrayNode('tags') // loggly - ->beforeNormalization() \ No newline at end of file diff --git a/apps/api-legacy/patches/monolog-telegram-extension.patch b/apps/api-legacy/patches/monolog-telegram-extension.patch deleted file mode 100644 index 4415ecd..0000000 --- a/apps/api-legacy/patches/monolog-telegram-extension.patch +++ /dev/null @@ -1,9 +0,0 @@ ---- a/vendor/symfony/monolog-bundle/DependencyInjection/MonologExtension.php 2023-11-06 11:08:12.000000000 +0200 -+++ b/vendor/symfony/monolog-bundle/DependencyInjection/MonologExtension.php 2024-08-16 05:05:49.266417128 +0200 -@@ -351,6 +351,7 @@ - $handler['disable_notification'], - $handler['split_long_messages'], - $handler['delay_between_messages'], -+ $handler['topic'] - ]); - break; \ No newline at end of file diff --git a/apps/api-legacy/phpstan.dist.neon b/apps/api-legacy/phpstan.dist.neon deleted file mode 100644 index 5fbf1f5..0000000 --- a/apps/api-legacy/phpstan.dist.neon +++ /dev/null @@ -1,19 +0,0 @@ -includes: - - vendor/phpstan/phpstan-symfony/extension.neon - - vendor/phpstan/phpstan-symfony/rules.neon -# - vendor/phpstan/phpstan-doctrine/extension.neon -# - vendor/phpstan/phpstan-doctrine/rules.neon - -parameters: - level: 8 - paths: - - bin/ - - config/ - - public/ - - src/ - - tests/ - ignoreErrors: - - identifier: missingType.iterableValue -# doctrine: -# objectManagerLoader: tests/object-manager.php -# allowNullablePropertyForRequiredField: true diff --git a/apps/api-legacy/phpunit.xml.dist b/apps/api-legacy/phpunit.xml.dist deleted file mode 100644 index 7b454b6..0000000 --- a/apps/api-legacy/phpunit.xml.dist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - tests - - - diff --git a/apps/api-legacy/public/.htaccess b/apps/api-legacy/public/.htaccess deleted file mode 100644 index 2776637..0000000 --- a/apps/api-legacy/public/.htaccess +++ /dev/null @@ -1,66 +0,0 @@ -# Use the front controller as index file. It serves as a fallback solution when -# every other rewrite/redirect fails (e.g. in an aliased environment without -# mod_rewrite). Additionally, this reduces the matching process for the -# start page (path "/") because otherwise Apache will apply the rewriting rules -# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). -DirectoryIndex index.php - -# By default, Apache does not evaluate symbolic links if you did not enable this -# feature in your server configuration. Uncomment the following line if you -# install assets as symlinks or if you experience problems related to symlinks -# when compiling LESS/Sass/CoffeScript assets. -# Options +FollowSymlinks - -# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve -# to the front controller "/index.php" but be rewritten to "/index.php/index". - - Options -MultiViews - - - - RewriteEngine On - - # Determine the RewriteBase automatically and set it as environment variable. - # If you are using Apache aliases to do mass virtual hosting or installed the - # project in a subdirectory, the base path will be prepended to allow proper - # resolution of the index.php file and to redirect to the correct URI. It will - # work in environments without path prefix as well, providing a safe, one-size - # fits all solution. But as you do not need it in this case, you can comment - # the following 2 lines to eliminate the overhead. - RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$ - RewriteRule .* - [E=BASE:%1] - - # Sets the HTTP_AUTHORIZATION header removed by Apache - RewriteCond %{HTTP:Authorization} .+ - RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - - # Redirect to URI without front controller to prevent duplicate content - # (with and without `/index.php`). Only do this redirect on the initial - # rewrite by Apache and not on subsequent cycles. Otherwise we would get an - # endless redirect loop (request -> rewrite to front controller -> - # redirect -> request -> ...). - # So in case you get a "too many redirects" error or you always get redirected - # to the start page because your Apache does not expose the REDIRECT_STATUS - # environment variable, you have 2 choices: - # - disable this feature by commenting the following 2 lines or - # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the - # following RewriteCond (best solution) - RewriteCond %{ENV:REDIRECT_STATUS} ="" - RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L] - - # If the requested filename exists, simply serve it. - # We only want to let Apache serve files and not directories. - # Rewrite all other queries to the front controller. - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ %{ENV:BASE}/index.php [L] - - - - - # When mod_rewrite is not available, we instruct a temporary redirect of - # the start page to the front controller explicitly so that the website - # and the generated links can still be used. - RedirectMatch 307 ^/$ /index.php/ - # RedirectTemp cannot be used instead - - diff --git a/apps/api-legacy/public/images/sources/7sur7.cd.png b/apps/api-legacy/public/images/sources/7sur7.cd.png deleted file mode 100644 index 48a6191..0000000 Binary files a/apps/api-legacy/public/images/sources/7sur7.cd.png and /dev/null differ diff --git a/apps/api-legacy/public/images/sources/actualite.cd.png b/apps/api-legacy/public/images/sources/actualite.cd.png deleted file mode 100644 index b6b8b86..0000000 Binary files a/apps/api-legacy/public/images/sources/actualite.cd.png and /dev/null differ diff --git a/apps/api-legacy/public/images/sources/beto.cd.png b/apps/api-legacy/public/images/sources/beto.cd.png deleted file mode 100644 index cae839b..0000000 Binary files a/apps/api-legacy/public/images/sources/beto.cd.png and /dev/null differ diff --git a/apps/api-legacy/public/images/sources/mediacongo.net.png b/apps/api-legacy/public/images/sources/mediacongo.net.png deleted file mode 100644 index bda666d..0000000 Binary files a/apps/api-legacy/public/images/sources/mediacongo.net.png and /dev/null differ diff --git a/apps/api-legacy/public/images/sources/newscd.net.png b/apps/api-legacy/public/images/sources/newscd.net.png deleted file mode 100644 index 98c0ef1..0000000 Binary files a/apps/api-legacy/public/images/sources/newscd.net.png and /dev/null differ diff --git a/apps/api-legacy/public/images/sources/radiookapi.net.png b/apps/api-legacy/public/images/sources/radiookapi.net.png deleted file mode 100644 index 597ed67..0000000 Binary files a/apps/api-legacy/public/images/sources/radiookapi.net.png and /dev/null differ diff --git a/apps/api-legacy/public/index.php b/apps/api-legacy/public/index.php deleted file mode 100644 index c90daef..0000000 --- a/apps/api-legacy/public/index.php +++ /dev/null @@ -1,7 +0,0 @@ - new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); diff --git a/apps/api-legacy/rector.php b/apps/api-legacy/rector.php deleted file mode 100644 index 758f96b..0000000 --- a/apps/api-legacy/rector.php +++ /dev/null @@ -1,39 +0,0 @@ -withPaths([ - __DIR__ . '/src', - __DIR__ . '/tests', - ]) - ->withImportNames( - importDocBlockNames: false, - importShortClasses: false, - removeUnusedImports: true - ) - ->withPhpVersion(PhpVersion::PHP_84) - ->withPhpSets(php84: true) - ->withPreparedSets( - deadCode: true, - codeQuality: true, - codingStyle: true, - typeDeclarations: true, - privatization: true, - instanceOf: true, - earlyReturn: true, - doctrineCodeQuality: true - ) - ->withSkip([ - CatchExceptionNameMatchingTypeRector::class - ]); -} catch (InvalidConfigurationException $e) { - echo $e->getMessage(); - exit(1); -} diff --git a/apps/api-legacy/src/Aggregator/Application/EventListener/SourceCrawledListener.php b/apps/api-legacy/src/Aggregator/Application/EventListener/SourceCrawledListener.php deleted file mode 100644 index c7f71e5..0000000 --- a/apps/api-legacy/src/Aggregator/Application/EventListener/SourceCrawledListener.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final readonly class SourceCrawledListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private string $crawlingNotificationEmail - ) { - } - - public function __invoke(SourceCrawled $event): void - { - if ($event->notify) { - $email = new SourceCrawledEmail( - EmailAddress::from($this->crawlingNotificationEmail), - $event->event, - $event->source - ); - - $this->mailer->send($email); - } - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/Mailing/SourceCrawledEmail.php b/apps/api-legacy/src/Aggregator/Application/Mailing/SourceCrawledEmail.php deleted file mode 100644 index a7ceae0..0000000 --- a/apps/api-legacy/src/Aggregator/Application/Mailing/SourceCrawledEmail.php +++ /dev/null @@ -1,68 +0,0 @@ - - */ -final readonly class SourceCrawledEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private string $event, - private string $source, - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'aggregator.emails.source_crawled.subject'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'aggregator/source_crawled'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'source' => $this->source, - 'event' => $this->event, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/ReadModel/ArticleForExport.php b/apps/api-legacy/src/Aggregator/Application/ReadModel/ArticleForExport.php deleted file mode 100644 index 2b96f5f..0000000 --- a/apps/api-legacy/src/Aggregator/Application/ReadModel/ArticleForExport.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ -final readonly class ArticleForExport -{ - public function __construct( - public ArticleId $id, - public string $title, - public string $link, - public string $categories, - public string $body, - public string $source, - public string $hash, - public \DateTimeImmutable $publishedAt, - public \DateTimeImmutable $crawledAt - ) { - } - - public static function create(array $item): self - { - return new self( - ArticleId::fromString(DataMapping::string($item, 'article_id')), - DataMapping::string($item, 'article_title'), - DataMapping::string($item, 'article_link'), - DataMapping::string($item, 'article_categories'), - DataMapping::string($item, 'article_body'), - DataMapping::string($item, 'article_source'), - DataMapping::string($item, 'article_hash'), - DataMapping::datetime($item, 'article_published_at'), - DataMapping::datetime($item, 'article_crawled_at') - ); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatistics.php b/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatistics.php deleted file mode 100644 index 722a864..0000000 --- a/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatistics.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final readonly class SourceStatistics -{ - public function __construct( - public SourceId $id, - public string $name, - public int $articlesCount, - public int $metadataAvailable, - public ?\DateTimeImmutable $crawledAt = null - ) { - } - - public static function create(array $item): self - { - return new self( - SourceId::fromString(DataMapping::string($item, 'source_id')), - DataMapping::string($item, 'source_name'), - DataMapping::integer($item, 'articles_count'), - DataMapping::integer($item, 'articles_metadata_available'), - DataMapping::nullableDatetime($item, 'source_crawled_at') - ); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatisticsList.php b/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatisticsList.php deleted file mode 100644 index 83ff2d9..0000000 --- a/apps/api-legacy/src/Aggregator/Application/ReadModel/SourceStatisticsList.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final readonly class SourceStatisticsList -{ - public function __construct( - public array $items, - ) { - Assert::allIsInstanceOf($items, SourceStatistics::class); - } - - public static function create(array $items): self - { - return new self( - array_map(fn (array $item): SourceStatistics => SourceStatistics::create($item), $items), - ); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateArticle.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateArticle.php deleted file mode 100644 index 53a146d..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateArticle.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -final readonly class CreateArticle -{ - public function __construct( - public string $title, - public Link $link, - public array $categories, - public string $body, - public string $source, - public int $timestamp, - public ?OpenGraph $metadata = null, - public ?TokenStatistics $tokenStatistics = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateSource.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateSource.php deleted file mode 100644 index bacb95a..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/CreateSource.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final readonly class CreateSource -{ - public function __construct( - public string $name, - public Credibility $credibility, - public ?string $displayName = null, - public ?string $description = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/DeleteArticles.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Command/DeleteArticles.php deleted file mode 100644 index 649fb72..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/DeleteArticles.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final readonly class DeleteArticles -{ - public function __construct( - public string $source, - public ?string $category = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/ExportArticles.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Command/ExportArticles.php deleted file mode 100644 index 65168a3..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Command/ExportArticles.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final readonly class ExportArticles -{ - public function __construct( - public ?string $source = null, - public ?DateRange $date = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateArticleHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateArticleHandler.php deleted file mode 100644 index 967e2c1..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateArticleHandler.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ -final readonly class CreateArticleHandler implements CommandHandler -{ - public function __construct( - private SourceRepository $sourceRepository, - private ArticleRepository $articleRepository, - private HashCalculator $hashCalculator - ) { - } - - public function __invoke(CreateArticle $command): void - { - $hash = $this->hashCalculator->calculate((string) $command->link); - $article = $this->articleRepository->getByHash($hash); - if ($article instanceof Article) { - throw DuplicatedArticle::withLink($command->link); - } - - /** @var \DateTimeImmutable $publishedAt */ - $publishedAt = \DateTimeImmutable::createFromFormat('U', (string) $command->timestamp); - $source = $this->sourceRepository->getByName($command->source); - - $article = new Article( - title: $command->title, - link: $command->link, - body: $command->body, - hash: $hash, - categories: $command->categories, - source: $source, - publishedAt: $publishedAt - ); - $article - ->defineOpenGraph($command->metadata) - ->defineTokenStatistics($command->tokenStatistics) - ->computeReadingTime(); - - $this->articleRepository->add($article); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateSourceHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateSourceHandler.php deleted file mode 100644 index 4e73d7c..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/CreateSourceHandler.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -final readonly class CreateSourceHandler implements CommandHandler -{ - public function __construct( - private SourceRepository $sourceRepository - ) { - } - - public function __invoke(CreateSource $command): void - { - $source = Source::create($command->name, sprintf('https://%s', $command->name)) - ->defineCredibility($command->credibility) - ->defineProfileInfos($command->displayName, $command->description); - - $this->sourceRepository->add($source); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/DeleteArticlesHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/DeleteArticlesHandler.php deleted file mode 100644 index e962d4a..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/DeleteArticlesHandler.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -final readonly class DeleteArticlesHandler implements CommandHandler -{ - public function __construct( - private ArticleRepository $articleRepository, - ) { - } - - public function __invoke(DeleteArticles $command): int - { - return $this->articleRepository->clear($command->source, $command->category); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/ExportArticlesHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/ExportArticlesHandler.php deleted file mode 100644 index 812e2be..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/CommandHandler/ExportArticlesHandler.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ -final readonly class ExportArticlesHandler implements CommandHandler -{ - public function __construct( - private QueryBus $queryBus, - private DataExporter $exporter, - private string $projectDir - ) { - } - - public function __invoke(ExportArticles $command): void - { - $filename = sprintf( - '%s/data/export-%s.csv', - $this->projectDir, - new \DateTimeImmutable('now')->format('U') - ); - - /** @var iterable $articles */ - $articles = $this->queryBus->handle(new GetArticlesForExport($command->source, $command->date)); - - $this->exporter->export($articles, new TransfertSetting($filename)); - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetArticlesForExport.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetArticlesForExport.php deleted file mode 100644 index b3a99e2..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetArticlesForExport.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final readonly class GetArticlesForExport -{ - public function __construct( - public ?string $source = null, - public ?DateRange $date = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetEarliestPublicationDate.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetEarliestPublicationDate.php deleted file mode 100644 index 860110e..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetEarliestPublicationDate.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final readonly class GetEarliestPublicationDate -{ - public function __construct( - public string $source, - public ?string $category = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetLatestPublicationDate.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetLatestPublicationDate.php deleted file mode 100644 index b713b51..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetLatestPublicationDate.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final readonly class GetLatestPublicationDate -{ - public function __construct( - public string $source, - public ?string $category = null - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetSourceStatisticsList.php b/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetSourceStatisticsList.php deleted file mode 100644 index fb2d7bc..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/Query/GetSourceStatisticsList.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final readonly class GetSourceStatisticsList -{ -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetArticlesForExportHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetArticlesForExportHandler.php deleted file mode 100644 index f288163..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetArticlesForExportHandler.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface GetArticlesForExportHandler extends QueryHandler -{ - /** - * @return iterable - */ - public function __invoke(GetArticlesForExport $query): iterable; -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetEarliestPublicationDateHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetEarliestPublicationDateHandler.php deleted file mode 100644 index 8e1984a..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetEarliestPublicationDateHandler.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -interface GetEarliestPublicationDateHandler extends QueryHandler -{ - public function __invoke(GetEarliestPublicationDate $query): \DateTimeImmutable; -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetLatestPublicationDateHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetLatestPublicationDateHandler.php deleted file mode 100644 index c9af756..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetLatestPublicationDateHandler.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -interface GetLatestPublicationDateHandler extends QueryHandler -{ - public function __invoke(GetLatestPublicationDate $query): \DateTimeImmutable; -} diff --git a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetSourceStatisticsListHandler.php b/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetSourceStatisticsListHandler.php deleted file mode 100644 index 3426686..0000000 --- a/apps/api-legacy/src/Aggregator/Application/UseCase/QueryHandler/GetSourceStatisticsListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetSourceStatisticsListHandler extends QueryHandler -{ - public function __invoke(GetSourceStatisticsList $query): SourceStatisticsList; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Event/SourceCrawled.php b/apps/api-legacy/src/Aggregator/Domain/Event/SourceCrawled.php deleted file mode 100644 index c235d6a..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Event/SourceCrawled.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class SourceCrawled -{ - public function __construct( - public string $event, - public string $source, - public bool $notify = false - ) { - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleNotFound.php b/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleNotFound.php deleted file mode 100644 index 0a779a9..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleNotFound.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class ArticleNotFound extends \DomainException implements UserFacingError -{ - public static function withId(ArticleId $id): self - { - return new self(sprintf('article with id %s was not found', $id->toString())); - } - - public function translationId(): string - { - return 'aggregator.exceptions.article_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleOutOfRange.php b/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleOutOfRange.php deleted file mode 100644 index 5652023..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Exception/ArticleOutOfRange.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -final class ArticleOutOfRange extends \DomainException implements UserFacingError -{ - public static function with(string $timestamp, DateRange $dateRange): self - { - $date = new \DateTimeImmutable('@' . $timestamp) - ->format('Y-m-d H:i:s'); - $range = $dateRange->format('Y-m-d H:i:s'); - - return new self(sprintf('article with timestamp %s is out of range %s', $date, $range)); - } - - public function translationId(): string - { - return 'aggregator.exceptions.article_out_of_range'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedArticle.php b/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedArticle.php deleted file mode 100644 index 7013751..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedArticle.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class DuplicatedArticle extends \DomainException implements UserFacingError -{ - public static function withLink(Link $link): self - { - return new self(sprintf('duplicate article with %s link', (string) $link)); - } - - public function translationId(): string - { - return 'aggregator.exceptions.duplicate_article'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedSource.php b/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedSource.php deleted file mode 100644 index 8da7ab5..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Exception/DuplicatedSource.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -final class DuplicatedSource extends \DomainException implements UserFacingError -{ - public static function withName(string $name): self - { - return new self(sprintf('duplicate source with %s name', $name)); - } - - public function translationId(): string - { - return 'aggregator.exceptions.duplicate_source'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Exception/SourceNotFound.php b/apps/api-legacy/src/Aggregator/Domain/Exception/SourceNotFound.php deleted file mode 100644 index 7627976..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Exception/SourceNotFound.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final class SourceNotFound extends \DomainException implements UserFacingError -{ - public static function withName(string $name): self - { - return new self(sprintf('source with name %s was not found', $name)); - } - - public static function withId(SourceId $sourceId): self - { - return new self(sprintf('source with id %s was not found', $sourceId->toString())); - } - - public function translationId(): string - { - return 'aggregator.exceptions.source_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'aggregator'; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Article.php b/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Article.php deleted file mode 100644 index 9eee4b7..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Article.php +++ /dev/null @@ -1,95 +0,0 @@ - - */ -class Article -{ - public readonly ArticleId $id; - - public function __construct( - public readonly string $title, - public readonly Link $link, - public readonly string $body, - public readonly string $hash, - private(set) array $categories, - public readonly Source $source, - public readonly \DateTimeImmutable $publishedAt, - public readonly \DateTimeImmutable $crawledAt = new \DateTimeImmutable(), - private(set) Credibility $credibility = new Credibility(), - private(set) Sentiment $sentiment = Sentiment::NEUTRAL, - private(set) ?OpenGraph $metadata = null, - private(set) ?TokenStatistics $tokenStatistics = null, - private(set) ?ReadingTime $readingTime = null, - private(set) ?\DateTimeImmutable $updatedAt = null, - public readonly ?string $image = null, - public readonly ?string $excerpt = null, - ) { - $this->id = new ArticleId(); - } - - public function defineCredibility(Credibility $credibility): self - { - $this->credibility = $credibility; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function defineSentiment(Sentiment $sentiment): self - { - $this->sentiment = $sentiment; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function assignCategories(array $categories): self - { - $this->categories = $categories; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function computeReadingTime(): self - { - $this->readingTime = ReadingTime::fromContent($this->body); - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function defineOpenGraph(?OpenGraph $object): self - { - $this->metadata = new OpenGraph( - title: $object?->title, - description: $object?->description, - image: $object?->image, - locale: $object->locale ?? 'fr' - ); - - return $this; - } - - public function defineTokenStatistics(?TokenStatistics $statistics): self - { - $this->tokenStatistics = $statistics; - - return $this; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Category.php b/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Category.php deleted file mode 100644 index 49eca6b..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Category.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -class Category -{ - public readonly CategoryId $id; - - public function __construct( - public string $name, - public string $slug, - public array $children = [], - public ?string $description = null, - public ?string $image = null, - ) { - $this->id = new CategoryId(); - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Source.php b/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Source.php deleted file mode 100644 index 8a4eb8d..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Entity/Source.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -class Source -{ - public readonly SourceId $id; - - public function __construct( - public readonly string $name, - public readonly string $url, - private(set) Credibility $credibility = new Credibility(), - private(set) ?string $displayName = null, - private(set) ?string $description = null, - private(set) ?\DateTimeImmutable $updatedAt = null - ) { - $this->id = new SourceId(); - } - - public static function create(string $name, string $url): self - { - return new self($name, $url); - } - - public function defineCredibility(Credibility $credibility): self - { - $this->credibility = $credibility; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function defineProfileInfos(?string $displayName, ?string $description): self - { - $this->displayName = $displayName; - $this->description = $description; - - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/ArticleId.php b/apps/api-legacy/src/Aggregator/Domain/Model/Identity/ArticleId.php deleted file mode 100644 index 82d438a..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/ArticleId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class ArticleId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/CategoryId.php b/apps/api-legacy/src/Aggregator/Domain/Model/Identity/CategoryId.php deleted file mode 100644 index 818d6ab..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/CategoryId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class CategoryId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/SourceId.php b/apps/api-legacy/src/Aggregator/Domain/Model/Identity/SourceId.php deleted file mode 100644 index 4ec6948..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Identity/SourceId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class SourceId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Repository/ArticleRepository.php b/apps/api-legacy/src/Aggregator/Domain/Model/Repository/ArticleRepository.php deleted file mode 100644 index 267e11c..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Repository/ArticleRepository.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -interface ArticleRepository -{ - public function add(Article $article): void; - - public function remove(Article $article): void; - - public function getById(ArticleId $id): Article; - - public function getByHash(string $hash): ?Article; - - public function export(?string $source, ?DateRange $date): \Generator; - - public function clear(string $source, ?string $category): int; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/Repository/SourceRepository.php b/apps/api-legacy/src/Aggregator/Domain/Model/Repository/SourceRepository.php deleted file mode 100644 index 08b4fc4..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/Repository/SourceRepository.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -interface SourceRepository -{ - public function add(Source $source): void; - - public function remove(Source $source): void; - - public function getByName(string $name): Source; - - public function getById(SourceId $sourceId): Source; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Link.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Link.php deleted file mode 100644 index 04bb3b1..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Link.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ -final readonly class Link implements \Stringable, \JsonSerializable -{ - public string $link; - - private function __construct(string $url, ?string $source = null) - { - if (! str_starts_with($url, 'http')) { - Assert::notNull($source, 'You must provide a source if the URL is not absolute.'); - $this->link = sprintf('https://%s/%s', $source, trim($url, '/')); - } else { - $this->link = $url; - } - } - - public function __toString(): string - { - return $this->link; - } - - public static function from(string $url, ?string $source = null): self - { - return new self($url, $source); - } - - public function jsonSerialize(): string - { - return $this->link; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/OpenGraph.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/OpenGraph.php deleted file mode 100644 index e278c2a..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/OpenGraph.php +++ /dev/null @@ -1,58 +0,0 @@ - - */ -final readonly class OpenGraph implements \JsonSerializable -{ - public function __construct( - public ?string $title = null, - public ?string $description = null, - public ?string $image = null, - public ?string $video = null, - public ?string $audio = null, - public ?string $locale = null, - ) { - } - - public static function tryFrom(?string $value): ?self - { - if ($value === null) { - return null; - } - - try { - $object = \json_decode($value, true, 512, JSON_THROW_ON_ERROR); - - return new self( - $object['title'] ?? null, - $object['description'] ?? null, - $object['image'] ?? null, - $object['video'] ?? null, - $object['audio'] ?? null, - $object['locale'] ?? null, - ); - } catch (\Throwable) { - return null; - } - } - - #[\Override] - public function jsonSerialize(): array - { - return [ - 'title' => $this->title, - 'description' => $this->description, - 'image' => $this->image, - 'video' => $this->video, - 'audio' => $this->audio, - 'locale' => $this->locale, - ]; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/ReadingTime.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/ReadingTime.php deleted file mode 100644 index 410d989..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/ReadingTime.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ -final readonly class ReadingTime implements \Stringable, \JsonSerializable -{ - public const int WORDS_PER_MINUTE = 200; - - public int $readingTime; - - public function __construct( - string|int $value - ) { - $this->readingTime = is_string($value) ? intval(str_word_count($value) / self::WORDS_PER_MINUTE) : $value; - } - - public function __toString(): string - { - return (string) $this->readingTime; - } - - public static function create(?int $value): self - { - return new self($value ?? 1); - } - - public static function fromContent(string $content): self - { - return new self($content); - } - - public function jsonSerialize(): string - { - return (string) $this->readingTime; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Bias.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Bias.php deleted file mode 100644 index eb056a4..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Bias.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -enum Bias: string -{ - case NEUTRAL = 'neutral'; - case SLIGHTLY = 'slightly'; - case PARTISAN = 'partisan'; - case EXTREME = 'extreme'; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Credibility.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Credibility.php deleted file mode 100644 index eaa1cc7..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Credibility.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -final readonly class Credibility implements \JsonSerializable -{ - public function __construct( - public Bias $bias = Bias::NEUTRAL, - public Reliability $reliability = Reliability::RELIABLE, - public Transparency $transparency = Transparency::MEDIUM - ) { - } - - public function jsonSerialize(): mixed - { - return [ - 'bias' => $this->bias->value, - 'reliability' => $this->reliability->value, - 'transparency' => $this->transparency->value, - ]; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Reliability.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Reliability.php deleted file mode 100644 index 3b880f3..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Reliability.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -enum Reliability: string -{ - case TRUSTED = 'trusted'; - case RELIABLE = 'reliable'; - case AVERAGE = 'average'; - case LOW_TRUST = 'low_trust'; - case UNRELIABLE = 'unreliable'; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Sentiment.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Sentiment.php deleted file mode 100644 index dabb8da..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Sentiment.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -enum Sentiment: string -{ - case NEGATIVE = 'negative'; - case POSITIVE = 'positive'; - case NEUTRAL = 'neutral'; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Transparency.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Transparency.php deleted file mode 100644 index b17e305..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/Scoring/Transparency.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -enum Transparency: string -{ - case HIGH = 'high'; - case MEDIUM = 'medium'; - case LOW = 'low'; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/TokenStatistics.php b/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/TokenStatistics.php deleted file mode 100644 index f384fd0..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Model/ValueObject/TokenStatistics.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ -final class TokenStatistics implements \JsonSerializable -{ - public ?int $total { - get { - return ($this->title ?? 0) - + ($this->body ?? 0) - + ($this->excerpt ?? 0) - + ($this->categories ?? 0); - } - } - - public function __construct( - public readonly ?int $title = null, - public readonly ?int $body = null, - public readonly ?int $excerpt = null, - public readonly ?int $categories = null, - ) { - } - - public static function tryFrom(?string $value): ?self - { - if ($value === null) { - return null; - } - - try { - $object = \json_decode($value, true, 512, JSON_THROW_ON_ERROR); - - return new self( - $object['title'] ?? null, - $object['body'] ?? null, - $object['excerpt'] ?? null, - $object['categories'] ?? null, - ); - } catch (\Throwable) { - return null; - } - } - - #[\Override] - public function jsonSerialize(): array - { - return [ - 'title' => $this->title, - 'body' => $this->body, - 'excerpt' => $this->excerpt, - 'categories' => $this->categories, - 'total' => $this->total, - ]; - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Service/HashCalculator.php b/apps/api-legacy/src/Aggregator/Domain/Service/HashCalculator.php deleted file mode 100644 index e49e63c..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Service/HashCalculator.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final readonly class HashCalculator -{ - public function calculate(string $data): string - { - return md5($data); - } -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/CredibilityAnalyser.php b/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/CredibilityAnalyser.php deleted file mode 100644 index e2de650..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/CredibilityAnalyser.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -interface CredibilityAnalyser -{ - public function getBias(string $content): Bias; - - public function getTransparency(string $content): Transparency; - - public function getReliability(string $content): Reliability; - - public function analyse(string $content): Credibility; -} diff --git a/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/SentimentAnalyser.php b/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/SentimentAnalyser.php deleted file mode 100644 index 20d337c..0000000 --- a/apps/api-legacy/src/Aggregator/Domain/Service/Scoring/SentimentAnalyser.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -interface SentimentAnalyser -{ - public function analyse(string $content): Sentiment; -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetArticlesForExportDbalHandler.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetArticlesForExportDbalHandler.php deleted file mode 100644 index cd6250a..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetArticlesForExportDbalHandler.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ -final readonly class GetArticlesForExportDbalHandler implements GetArticlesForExportHandler -{ - private const int BATCH_SIZE = 1000; - - public function __construct( - private Connection $connection - ) { - } - - #[\Override] - public function __invoke(GetArticlesForExport $query): iterable - { - $qb = $this->connection->createQueryBuilder() - ->select( - 'a.id as article_id', - 'a.title as article_title', - 'a.link as article_link', - "array_to_string(a.categories, ',') as article_categories", - 'a.body as article_body', - 's.name as article_source', - 'a.hash as article_hash', - 'a.published_at as article_published_at', - 'a.crawled_at as article_crawled_at' - ) - ->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->orderBy('a.published_at', 'DESC') - ->addOrderBy('a.id', 'DESC'); - - if ($query->source !== null) { - $qb->andWhere('s.name = :source') - ->setParameter('source', $query->source); - } - - if ($query->date instanceof DateRange) { - $qb->andWhere('a.published_at BETWEEN to_timestamp(:start) AND to_timestamp(:end)') - ->setParameter('start', $query->date->start) - ->setParameter('end', $query->date->end); - } - - $offset = 0; - - while (true) { - $qb->setFirstResult($offset); - $qb->setMaxResults(self::BATCH_SIZE); - - /** @var array> $data */ - $data = $qb->executeQuery()->fetchAllAssociative(); - if (count($data) === 0) { - break; - } - - foreach ($data as $article) { - yield ArticleForExport::create($article); - } - - $offset += self::BATCH_SIZE; - } - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetEarliestPublicationDateDBalHandler.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetEarliestPublicationDateDBalHandler.php deleted file mode 100644 index ae4c383..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetEarliestPublicationDateDBalHandler.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final readonly class GetEarliestPublicationDateDBalHandler implements GetEarliestPublicationDateHandler -{ - public function __construct( - private Connection $connection, - private LoggerInterface $logger - ) { - } - - #[\Override] - public function __invoke(GetEarliestPublicationDate $query): \DateTimeImmutable - { - $qb = $this->connection->createQueryBuilder() - ->select('MIN(a.published_at)') - ->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where('s.name = :source') - ->setParameter('source', $query->source); - - if ($query->category !== null) { - $qb->andWhere(':category = ANY(a.categories)') - ->setParameter('category', $query->category); - } - - try { - /** @var string|null $date */ - $date = $qb->executeQuery()->fetchOne(); - - return new \DateTimeImmutable($date ?? 'now'); - } catch (\Throwable $e) { - $this->logger->critical('Unable to fetch earliest publication date'); - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetLatestPublicationDateDBalHandler.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetLatestPublicationDateDBalHandler.php deleted file mode 100644 index 991c43b..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetLatestPublicationDateDBalHandler.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final readonly class GetLatestPublicationDateDBalHandler implements GetLatestPublicationDateHandler -{ - public function __construct( - private Connection $connection, - private LoggerInterface $logger - ) { - } - - #[\Override] - public function __invoke(GetLatestPublicationDate $query): \DateTimeImmutable - { - $qb = $this->connection->createQueryBuilder() - ->select('MAX(a.published_at)') - ->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where('s.name = :source') - ->setParameter('source', $query->source); - - if ($query->category !== null) { - $qb->andWhere(':category = ANY(a.categories)') - ->setParameter('category', $query->category); - } - - try { - /** @var string|null $date */ - $date = $qb->executeQuery()->fetchOne(); - - return new \DateTimeImmutable($date ?? 'now'); - } catch (\Throwable $e) { - $this->logger->critical('Unable to fetch latest publication date'); - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetSourceStatisticsListDbalHandler.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetSourceStatisticsListDbalHandler.php deleted file mode 100644 index 459971f..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/GetSourceStatisticsListDbalHandler.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final readonly class GetSourceStatisticsListDbalHandler implements GetSourceStatisticsListHandler -{ - public function __construct( - private Connection $connection - ) { - } - - public function __invoke(GetSourceStatisticsList $query): SourceStatisticsList - { - $qb = $this->connection->createQueryBuilder() - ->select( - 's.id as source_id', - 's.name as source_name', - 'MAX(a.crawled_at) as source_crawled_at', - 'COUNT(a.id) as articles_count', - 'SUM(CASE WHEN a.metadata IS NOT NULL THEN 1 ELSE 0 END) as article_metadata_available' - ) - ->from('source', 's') - ->leftJoin('s', 'article', 'a', 'a.source_id = s.id') - ->groupBy('s.id, s.name') - ->orderBy('s.name', 'ASC'); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - return SourceStatisticsList::create($data); - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/ArticleIdType.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/ArticleIdType.php deleted file mode 100644 index 9e20e1a..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/ArticleIdType.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class ArticleIdType extends AbstractUidType -{ - #[\Override] - public function getName(): string - { - return 'article_id'; - } - - #[\Override] - protected function getUidClass(): string - { - return ArticleId::class; - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/OpenGraphType.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/OpenGraphType.php deleted file mode 100644 index d37d261..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/OpenGraphType.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final class OpenGraphType extends Type -{ - public function getSQLDeclaration(array $column, AbstractPlatform $platform): string - { - return $platform->getJsonTypeDeclarationSQL([ - 'nullable' => true, - 'jsonb' => true, - ]); - } - - public function getName(): string - { - return 'open_graph'; - } - - #[\Override] - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?OpenGraph - { - if ($value === null) { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', OpenGraph::class]); - } - - try { - return OpenGraph::tryFrom($value); - } catch (\Throwable $e) { - throw ConversionException::conversionFailed($value, $this->getName(), $e); - } - } - - #[\Override] - public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string - { - if ($value instanceof OpenGraph) { - return json_encode($value) ?: null; - } - - if ($value === null || $value === '') { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', OpenGraph::class]); - } - - throw ConversionException::conversionFailed($value, $this->getName()); - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/SourceIdType.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/SourceIdType.php deleted file mode 100644 index 9c5b4b8..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/SourceIdType.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class SourceIdType extends AbstractUidType -{ - public function getName(): string - { - return 'source_id'; - } - - protected function getUidClass(): string - { - return SourceId::class; - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/TokenStatisticsType.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/TokenStatisticsType.php deleted file mode 100644 index ae98942..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/DBAL/Types/TokenStatisticsType.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final class TokenStatisticsType extends Type -{ - public function getSQLDeclaration(array $column, AbstractPlatform $platform): string - { - return $platform->getJsonTypeDeclarationSQL([ - 'nullable' => true, - 'jsonb' => true, - ]); - } - - public function getName(): string - { - return 'token_statistics'; - } - - #[\Override] - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?TokenStatistics - { - if ($value === null) { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', TokenStatistics::class]); - } - - try { - return TokenStatistics::tryFrom($value); - } catch (\Throwable $e) { - throw ConversionException::conversionFailed($value, $this->getName(), $e); - } - } - - #[\Override] - public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string - { - if ($value instanceof TokenStatistics) { - return json_encode($value) ?: null; - } - - if ($value === null || $value === '') { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', TokenStatistics::class]); - } - - throw ConversionException::conversionFailed($value, $this->getName()); - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/ArticleOrmRepository.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/ArticleOrmRepository.php deleted file mode 100644 index 0102e87..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/ArticleOrmRepository.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * @author bernard-ng - */ -final class ArticleOrmRepository extends ServiceEntityRepository implements ArticleRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Article::class); - } - - #[\Override] - public function add(Article $article): void - { - $this->getEntityManager()->persist($article); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function remove(Article $article): void - { - $this->getEntityManager()->remove($article); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function getById(ArticleId $id): Article - { - /** @var Article|null $article */ - $article = $this->findOneBy([ - 'id' => $id, - ]); - - if ($article === null) { - throw ArticleNotFound::withId($id); - } - - return $article; - } - - #[\Override] - public function export(?string $source, ?DateRange $date): \Generator - { - $qb = $this->createQueryBuilder('a') - ->orderBy('a.publishedAt', 'DESC'); - - if ($source !== null) { - $qb - ->leftJoin('a.source', 's') - ->andWhere('s.name = :source') - ->setParameter('source', $source); - } - - if ($date instanceof DateRange) { - $qb->andWhere('a.publishedAt BETWEEN :startDate AND :endDate') - ->setParameter('startDate', new DateTimeImmutable()->setTimestamp($date->start)) - ->setParameter('endDate', new DateTimeImmutable()->setTimestamp($date->end)); - } - - $limit = 1000; - $offset = 0; - - while (true) { - $qb->setFirstResult($offset); - $qb->setMaxResults($limit); - - /** @var Article[] $articles */ - $articles = $qb->getQuery()->getResult(); - if (count($articles) === 0) { - break; - } - - foreach ($articles as $article) { - yield $article; - $this->getEntityManager()->detach($article); - } - - $offset += $limit; - } - } - - #[\Override] - public function getByHash(string $hash): ?Article - { - /** @var Article|null $article */ - $article = $this->findOneBy([ - 'hash' => $hash, - ]); - - return $article; - } - - #[\Override] - public function clear(string $source, ?string $category): int - { - $qb = $this->createQueryBuilder('a') - ->leftJoin('a.source', 's') - ->where('s.name = :source') - ->setParameter('source', $source); - - if ($category !== null) { - $qb->andWhere('a.categories LIKE :category') - ->setParameter('category', sprintf('%%%s%%', $category)); - } - - /** @var int $result */ - $result = $qb->delete(Article::class, 'a') - ->getQuery() - ->execute(); - - return $result; - } -} diff --git a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/SourceOrmRepository.php b/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/SourceOrmRepository.php deleted file mode 100644 index 5ae24ed..0000000 --- a/apps/api-legacy/src/Aggregator/Infrastructure/Persistence/Doctrine/ORM/SourceOrmRepository.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * @author bernard-ng - */ -final class SourceOrmRepository extends ServiceEntityRepository implements SourceRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Source::class); - } - - public function add(Source $source): void - { - $this->getEntityManager()->persist($source); - $this->getEntityManager()->flush(); - } - - public function remove(Source $source): void - { - $this->getEntityManager()->remove($source); - $this->getEntityManager()->flush(); - } - - public function getByName(string $name): Source - { - $source = $this->findOneBy([ - 'name' => $name, - ]); - - if ($source === null) { - throw SourceNotFound::withName($name); - } - - return $source; - } - - public function getById(SourceId $sourceId): Source - { - $source = $this->findOneBy([ - 'id' => $sourceId, - ]); - - if ($source === null) { - throw SourceNotFound::withId($sourceId); - } - - return $source; - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/Console/CreateSourceConsole.php b/apps/api-legacy/src/Aggregator/Presentation/Console/CreateSourceConsole.php deleted file mode 100644 index 93777c0..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/Console/CreateSourceConsole.php +++ /dev/null @@ -1,95 +0,0 @@ -addArgument('source', InputArgument::REQUIRED, 'the website source to crawle'); - $this->addArgument('displayName', InputArgument::OPTIONAL, 'the display name of the source'); - $this->addArgument('description', InputArgument::OPTIONAL, 'the description of the source'); - $this->addOption('bias', 'b', InputArgument::OPTIONAL, 'bias of the source', Bias::NEUTRAL->value); - $this->addOption('reliability', 'r', InputArgument::OPTIONAL, 'reliability of the source', Reliability::AVERAGE->value); - $this->addOption('transparency', 't', InputArgument::OPTIONAL, 'transparency of the source', Transparency::MEDIUM->value); - } - - #[\Override] - protected function interact(InputInterface $input, OutputInterface $output): void - { - $this->io = new SymfonyStyle($input, $output); - $this->io->title('Create a new data source'); - - $this->askArgument($input, 'source'); - $this->askArgument($input, 'displayName'); - $this->askOption($input, 'bias'); - $this->askOption($input, 'reliability'); - $this->askOption($input, 'transparency'); - } - - #[\Override] - protected function initialize(InputInterface $input, OutputInterface $output): void - { - $this->io = new SymfonyStyle($input, $output); - } - - #[\Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - if (! $this->io->confirm('Do you want to continue?', false)) { - $this->io->warning('Process aborted'); - return Command::FAILURE; - } - - /** @var string $source */ - $source = $input->getArgument('source'); - - /** @var string|null $displayName */ - $displayName = $input->getArgument('displayName'); - - /** @var string|null $description */ - $description = $input->getArgument('description'); - - $credibility = new Credibility( - bias: Bias::from($input->getOption('bias')), - reliability: Reliability::from($input->getOption('reliability')), - transparency: Transparency::from($input->getOption('transparency')), - ); - - $this->commandBus->handle(new CreateSource($source, $credibility, $displayName, $description)); - - $this->io->success('Source add successfully'); - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/Console/DeleteArticlesConsole.php b/apps/api-legacy/src/Aggregator/Presentation/Console/DeleteArticlesConsole.php deleted file mode 100644 index 039674d..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/Console/DeleteArticlesConsole.php +++ /dev/null @@ -1,71 +0,0 @@ -addArgument('source', InputArgument::REQUIRED, 'the website source to crawle'); - $this->addOption('category', null, InputOption::VALUE_OPTIONAL, 'the category to crawle'); - } - - #[\Override] - protected function initialize(InputInterface $input, OutputInterface $output): void - { - $this->io = new SymfonyStyle($input, $output); - } - - #[\Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var string $source */ - $source = $input->getArgument('source'); - - /** @var string|null $category */ - $category = $input->getOption('category'); - - if ( - $this->io->confirm('Delete all articles ?', false) && - $this->io->confirm('Are you sure ?', false) - ) { - - $confirmation = $this->io->askQuestion(new Question('Specify the source to confirm : ')); - if ($confirmation === $source) { - /** @var int $count */ - $count = $this->commandBus->handle(new DeleteArticles($source, $category)); - $this->io->success(sprintf('%d articles from %s removed', $count, $source)); - } else { - $this->io->warning('Source does not match, aborting !'); - } - } - - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/Console/ExportArticlesConsole.php b/apps/api-legacy/src/Aggregator/Presentation/Console/ExportArticlesConsole.php deleted file mode 100644 index 2879fb2..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/Console/ExportArticlesConsole.php +++ /dev/null @@ -1,65 +0,0 @@ -addArgument('source', InputArgument::OPTIONAL, 'the website source to crawle'); - $this->addOption('date', null, InputOption::VALUE_OPTIONAL, 'Date interval to crawle', null); - } - - #[\Override] - protected function initialize(InputInterface $input, OutputInterface $output): void - { - $this->io = new SymfonyStyle($input, $output); - } - - #[\Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var string|null $source */ - $source = $input->getArgument('source'); - - /** @var string|null $date */ - $date = $input->getOption('date'); - - $confirmation = $this->io->confirm('This can take a while, would like to continue ?', false); - if ($confirmation) { - $this->commandBus->handle(new ExportArticles( - source: $source, - date: $date !== null ? DateRange::from($date) : null - )); - } - - $this->io->success('articles exported successfully'); - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/Console/GetSourceStatisticsListConsole.php b/apps/api-legacy/src/Aggregator/Presentation/Console/GetSourceStatisticsListConsole.php deleted file mode 100644 index 52b8c6a..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/Console/GetSourceStatisticsListConsole.php +++ /dev/null @@ -1,63 +0,0 @@ -io = new SymfonyStyle($input, $output); - } - - #[\Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var SourceStatisticsList $stats */ - $stats = $this->queryBus->handle(new GetSourceStatisticsList()); - - $stopWatch = new Stopwatch(true); - $stopWatch->start('app:stats'); - - $this->io->table( - ['Source', 'Articles', 'Metadata', 'CrawledAt'], - array_map( - fn (SourceStatistics $source): array => [ - $source->name, - number_format($source->articlesCount, decimal_separator: '.', thousands_separator: ','), - number_format($source->metadataAvailable, decimal_separator: '.', thousands_separator: ','), - $source->crawledAt?->format('Y-m-d H:i:s') ?? 'Never', - ], - $stats->items - ) - ); - - $this->io->text((string) $stopWatch->stop('app:stats')); - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/Web/Controller/AddArticleController.php b/apps/api-legacy/src/Aggregator/Presentation/Web/Controller/AddArticleController.php deleted file mode 100644 index aacf9ee..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/Web/Controller/AddArticleController.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -final class AddArticleController extends AbstractController -{ - public function __construct( - #[Autowire(env: 'BASANGO_CRAWLER_TOKEN')] private readonly string $token - ) { - } - - #[Route( - path: '/api/aggregator/articles', - name: 'aggregator_add_article', - requirements: [ - 'token' => Requirement::ASCII_SLUG, - ], - methods: ['POST'] - )] - public function __invoke( - #[MapQueryParameter] string $token, - #[MapRequestPayload] AddArticleModel $model - ): JsonResponse { - if ($token !== $this->token) { - throw $this->createAccessDeniedException(); - } - - $this->handleCommand(new CreateArticle( - $model->title, - Link::from($model->link), - $model->categories, - $model->body, - $model->source, - $model->timestamp, - $model->metadata, - $model->tokenStatistics - )); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/Aggregator/Presentation/WriteModel/AddArticleModel.php b/apps/api-legacy/src/Aggregator/Presentation/WriteModel/AddArticleModel.php deleted file mode 100644 index 90ab6f1..0000000 --- a/apps/api-legacy/src/Aggregator/Presentation/WriteModel/AddArticleModel.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final class AddArticleModel -{ - #[Assert\NotBlank] - public string $title; - - #[Assert\NotBlank] - public string $link; - - #[Assert\NotBlank] - public string $body; - - #[Assert\NotBlank] - public string $source; - - #[Assert\NotBlank] - public int $timestamp; - - public array $categories = []; - - public ?OpenGraph $metadata = null; - - public ?TokenStatistics $tokenStatistics = null; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/Cache/SourceCacheAttributes.php b/apps/api-legacy/src/FeedManagement/Application/Cache/SourceCacheAttributes.php deleted file mode 100644 index 35fd8f5..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/Cache/SourceCacheAttributes.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -enum SourceCacheAttributes: string -{ - case CATEGORIES = 'categories_shares'; - - case PUBLICATIONS = 'publications_graph'; - - public const int CACHE_TTL = 86400; - - public function withId(string $id): string - { - return sprintf('%s_%s', $this->value, $id); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleDetails.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleDetails.php deleted file mode 100644 index 5e41d8e..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleDetails.php +++ /dev/null @@ -1,68 +0,0 @@ - - */ -final readonly class ArticleDetails -{ - public function __construct( - public ArticleId $id, - public string $title, - public Link $link, - public array $categories, - public string $body, - public SourceReference $source, - public string $hash, - public Credibility $credibility, - public Sentiment $sentiment, - public ?OpenGraph $metadata, - public ReadingTime $readingTime, - public \DateTimeImmutable $publishedAt, - public \DateTimeImmutable $crawledAt, - public ?\DateTimeImmutable $updatedAt, - public bool $bookmarked = false - ) { - } - - public static function create(array $item): self - { - return new self( - ArticleId::fromString(DataMapping::string($item, 'article_id')), - DataMapping::string($item, 'article_title'), - Link::from(DataMapping::string($item, 'article_link')), - explode(',', DataMapping::string($item, 'article_categories')), - DataMapping::string($item, 'article_body'), - SourceReference::create($item), - DataMapping::string($item, 'article_hash'), - new Credibility( - DataMapping::enum($item, 'article_bias', Bias::class), - DataMapping::enum($item, 'article_reliability', Reliability::class), - DataMapping::enum($item, 'article_transparency', Transparency::class) - ), - DataMapping::enum($item, 'article_sentiment', Sentiment::class), - OpenGraph::tryFrom(DataMapping::nullableString($item, 'article_metadata')), - ReadingTime::create(DataMapping::nullableInteger($item, 'article_reading_time')), - DataMapping::datetime($item, 'article_published_at'), - DataMapping::datetime($item, 'article_crawled_at'), - DataMapping::nullableDatetime($item, 'article_updated_at'), - DataMapping::boolean($item, 'article_is_bookmarked'), - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverview.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverview.php deleted file mode 100644 index b06e163..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverview.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final readonly class ArticleOverview -{ - public function __construct( - public ArticleId $id, - public string $title, - public Link $link, - public array $categories, - public string $excerpt, - public SourceReference $source, - public ?string $image, - public ReadingTime $readingTime, - public \DateTimeImmutable $publishedAt, - public bool $bookmarked = false - ) { - } - - public static function create(array $item): self - { - return new self( - ArticleId::fromString(DataMapping::string($item, 'article_id')), - DataMapping::string($item, 'article_title'), - Link::from(DataMapping::string($item, 'article_link')), - explode(',', DataMapping::string($item, 'article_categories')), - trim(DataMapping::string($item, 'article_excerpt')), - SourceReference::create($item), - DataMapping::nullableString($item, 'article_image'), - ReadingTime::create(DataMapping::nullableInteger($item, 'article_reading_time')), - DataMapping::datetime($item, 'article_published_at'), - DataMapping::boolean($item, 'article_is_bookmarked'), - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverviewList.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverviewList.php deleted file mode 100644 index 90f4a0e..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/ArticleOverviewList.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final readonly class ArticleOverviewList -{ - public function __construct( - public array $items, - public PaginationInfo $pagination - ) { - Assert::allIsInstanceOf($this->items, ArticleOverview::class); - } - - public static function create(array $items, PaginationInfo $pagination): self - { - return new self( - array_map(fn (array $item): ArticleOverview => ArticleOverview::create($item), $items), - $pagination - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/Bookmark.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/Bookmark.php deleted file mode 100644 index cb687d2..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/Bookmark.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -final readonly class Bookmark -{ - public function __construct( - public BookmarkId $id, - public string $name, - public \DateTimeImmutable $createdAt, - public ?string $description = null, - public int $articlesCount = 0, - public bool $isPublic = false, - public ?\DateTimeImmutable $updatedAt = null - ) { - } - - public static function create(array $item): self - { - return new self( - BookmarkId::fromString(DataMapping::string($item, 'bookmark_id')), - DataMapping::string($item, 'bookmark_name'), - DataMapping::datetime($item, 'bookmark_created_at'), - DataMapping::nullableString($item, 'bookmark_description'), - DataMapping::integer($item, 'bookmark_articles_count'), - DataMapping::boolean($item, 'bookmark_is_public'), - DataMapping::nullableDatetime($item, 'bookmark_updated_at') - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/BookmarkList.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/BookmarkList.php deleted file mode 100644 index acd63da..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/BookmarkList.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final readonly class BookmarkList -{ - public function __construct( - public array $items, - public PaginationInfo $pagination - ) { - Assert::allIsInstanceOf($this->items, Bookmark::class); - } - - public static function create(array $items, PaginationInfo $pagination): self - { - return new self( - array_map(fn (array $item): Bookmark => Bookmark::create($item), $items), - $pagination - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShare.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShare.php deleted file mode 100644 index ce799e5..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShare.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class CategoryShare -{ - public function __construct( - public string $category, - public int $count, - public float $percentage - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShares.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShares.php deleted file mode 100644 index db2cc4e..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CategoryShares.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class CategoryShares -{ - public function __construct( - public array $items = [], - public int $total = 0 - ) { - Assert::allIsInstanceOf($this->items, CategoryShare::class); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/Comment.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/Comment.php deleted file mode 100644 index 7f98b04..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/Comment.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final readonly class Comment -{ - public function __construct( - public CommentId $id, - public UserReference $user, - public Sentiment $sentiment, - public string $content, - public \DateTimeImmutable $createdAt, - ) { - } - - public static function create(array $item): self - { - return new self( - CommentId::fromString(DataMapping::string($item, 'comment_id')), - UserReference::create($item), - DataMapping::enum($item, 'comment_sentiment', Sentiment::class), - DataMapping::string($item, 'comment_content'), - DataMapping::dateTime($item, 'comment_created_at') - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CommentList.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/CommentList.php deleted file mode 100644 index 081af23..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/CommentList.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final readonly class CommentList -{ - public function __construct( - public array $items, - public PaginationInfo $pagination - ) { - Assert::allIsInstanceOf($this->items, Comment::class); - } - - public static function create(array $items, PaginationInfo $pagination): self - { - return new self( - array_map(fn (array $item): Comment => Comment::create($item), $items), - $pagination - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationEntry.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationEntry.php deleted file mode 100644 index 3059cb5..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationEntry.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final readonly class PublicationEntry -{ - public function __construct( - public string $date, - public int $count - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationGraph.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationGraph.php deleted file mode 100644 index b5a217e..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/PublicationGraph.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class PublicationGraph -{ - public function __construct( - public array $items = [], - public int $total = 0 - ) { - Assert::allIsInstanceOf($this->items, PublicationEntry::class); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceDetails.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceDetails.php deleted file mode 100644 index 8ae3b37..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceDetails.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ -final readonly class SourceDetails -{ - public function __construct( - public SourceId $id, - public string $name, - public string $url, - public Credibility $credibility, - public PublicationGraph $publicationGraph, - public CategoryShares $categoryShares, - public int $articlesCount, - public string $crawledAt, - public ?string $displayName = null, - public ?string $description = null, - public ?string $updatedAt = null, - public int $metadataAvailable = 0, - public bool $followed = false, - public ?string $image = null, - ) { - } - - public static function create(array $item, PublicationGraph $publicationGraph, CategoryShares $categoryShares): self - { - return new self( - SourceId::fromString(DataMapping::string($item, 'source_id')), - DataMapping::string($item, 'source_name'), - DataMapping::string($item, 'source_url'), - new Credibility( - DataMapping::enum($item, 'source_bias', Bias::class), - DataMapping::enum($item, 'source_reliability', Reliability::class), - DataMapping::enum($item, 'source_transparency', Transparency::class) - ), - $publicationGraph, - $categoryShares, - DataMapping::integer($item, 'articles_count'), - DataMapping::string($item, 'source_crawled_at'), - DataMapping::nullableString($item, 'source_display_name'), - DataMapping::nullableString($item, 'source_description'), - DataMapping::nullableString($item, 'source_updated_at'), - DataMapping::integer($item, 'articles_metadata_available'), - DataMapping::boolean($item, 'source_is_followed'), - DataMapping::nullableString($item, 'source_image'), - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverview.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverview.php deleted file mode 100644 index 1b59beb..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverview.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final readonly class SourceOverview -{ - public function __construct( - public SourceId $id, - public string $name, - public string $url, - public ?string $displayName = null, - public bool $followed = false, - public ?string $image = null - ) { - } - - public static function create(array $item): self - { - return new self( - SourceId::fromString(DataMapping::string($item, 'source_id')), - DataMapping::string($item, 'source_name'), - DataMapping::string($item, 'source_url'), - DataMapping::nullableString($item, 'source_display_name'), - DataMapping::boolean($item, 'source_is_followed'), - DataMapping::nullableString($item, 'source_image') - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverviewList.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverviewList.php deleted file mode 100644 index 4c260b2..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceOverviewList.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final readonly class SourceOverviewList -{ - public function __construct( - public array $items, - public PaginationInfo $pagination, - ) { - Assert::allIsInstanceOf($items, SourceOverview::class); - } - - public static function create(array $items, PaginationInfo $pagination): self - { - return new self( - array_map(fn (array $item): SourceOverview => SourceOverview::create($item), $items), - $pagination - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceReference.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceReference.php deleted file mode 100644 index 45929f7..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/SourceReference.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final readonly class SourceReference -{ - public function __construct( - public SourceId $id, - public string $name, - public ?string $displayName, - public ?string $image, - public string $url - ) { - } - - public static function create(array $item): self - { - return new self( - SourceId::fromString(DataMapping::string($item, 'source_id')), - DataMapping::string($item, 'source_name'), - DataMapping::nullableString($item, 'source_display_name'), - DataMapping::nullableString($item, 'source_image'), - DataMapping::string($item, 'source_url'), - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/ReadModel/UserReference.php b/apps/api-legacy/src/FeedManagement/Application/ReadModel/UserReference.php deleted file mode 100644 index cb1a190..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/ReadModel/UserReference.php +++ /dev/null @@ -1,30 +0,0 @@ - - */ -final readonly class UserReference -{ - public function __construct( - public UserId $id, - public string $name, - ) { - } - - public static function create(array $item): self - { - return new self( - UserId::fromString(DataMapping::string($item, 'user_id')), - DataMapping::string($item, 'user_name') - ); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddArticleToBookmark.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddArticleToBookmark.php deleted file mode 100644 index 0a5c229..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddArticleToBookmark.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final readonly class AddArticleToBookmark -{ - public function __construct( - public UserId $userId, - public ArticleId $articleId, - public BookmarkId $bookmarkId, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddCommentToArticle.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddCommentToArticle.php deleted file mode 100644 index 4adfe63..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/AddCommentToArticle.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final readonly class AddCommentToArticle -{ - public function __construct( - public UserId $userId, - public ArticleId $articleId, - public string $content, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/CreateBookmark.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/CreateBookmark.php deleted file mode 100644 index 54c6217..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/CreateBookmark.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class CreateBookmark -{ - public function __construct( - public UserId $userId, - public string $name, - public ?string $description, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/DeleteBookmark.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/DeleteBookmark.php deleted file mode 100644 index ca24a84..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/DeleteBookmark.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class DeleteBookmark -{ - public function __construct( - public UserId $userId, - public BookmarkId $bookmarkId - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/FollowSource.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/FollowSource.php deleted file mode 100644 index cbfb9b7..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/FollowSource.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class FollowSource -{ - public function __construct( - public SourceId $sourceId, - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveArticleFromBookmark.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveArticleFromBookmark.php deleted file mode 100644 index dad5322..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveArticleFromBookmark.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final readonly class RemoveArticleFromBookmark -{ - public function __construct( - public UserId $userId, - public ArticleId $articleId, - public BookmarkId $bookmarkId, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveCommentFromArticle.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveCommentFromArticle.php deleted file mode 100644 index 72e8dd4..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/RemoveCommentFromArticle.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class RemoveCommentFromArticle -{ - public function __construct( - public UserId $userId, - public CommentId $commentId - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UnfollowSource.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UnfollowSource.php deleted file mode 100644 index ab53164..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UnfollowSource.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class UnfollowSource -{ - public function __construct( - public SourceId $sourceId, - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UpdateBookmark.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UpdateBookmark.php deleted file mode 100644 index 39c6dc7..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Command/UpdateBookmark.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ -final readonly class UpdateBookmark -{ - public function __construct( - public UserId $userId, - public BookmarkId $bookmarkId, - public string $name, - public ?string $description, - public bool $isPublic = false, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddArticleToBookmarkHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddArticleToBookmarkHandler.php deleted file mode 100644 index b649dac..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddArticleToBookmarkHandler.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final readonly class AddArticleToBookmarkHandler implements CommandHandler -{ - public function __construct( - private BookmarkRepository $bookmarkRepository, - private ArticleRepository $articleRepository - ) { - } - - public function __invoke(AddArticleToBookmark $command): void - { - $bookmark = $this->bookmarkRepository->getById($command->bookmarkId); - if ($bookmark->user->id !== $command->userId) { - throw PermissionNotGranted::withReason('feed_management.exceptions.cannot_add_article_to_bookmark'); - } - - $article = $this->articleRepository->getById($command->articleId); - - $bookmark->addArticle($article); - $this->bookmarkRepository->add($bookmark); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddCommentToArticleHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddCommentToArticleHandler.php deleted file mode 100644 index 039a2e1..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/AddCommentToArticleHandler.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final readonly class AddCommentToArticleHandler implements CommandHandler -{ - public function __construct( - public UserRepository $userRepository, - public ArticleRepository $articleRepository, - public CommentRepository $commentRepository - ) { - } - - public function __invoke(AddCommentToArticle $comment): void - { - $user = $this->userRepository->getById($comment->userId); - $article = $this->articleRepository->getById($comment->articleId); - - $comment = Comment::create($user, $article, $comment->content); - $this->commentRepository->add($comment); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/CreateBookHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/CreateBookHandler.php deleted file mode 100644 index 4e1a555..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/CreateBookHandler.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class CreateBookHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private BookmarkRepository $bookmarkRepository - ) { - } - - public function __invoke(CreateBookmark $command): void - { - $user = $this->userRepository->getById($command->userId); - $bookmark = Bookmark::create($user, $command->name, $command->description); - - $this->bookmarkRepository->add($bookmark); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/DeleteBookmarkHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/DeleteBookmarkHandler.php deleted file mode 100644 index 44c2c70..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/DeleteBookmarkHandler.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class DeleteBookmarkHandler implements CommandHandler -{ - public function __construct( - private BookmarkRepository $bookmarkRepository, - ) { - } - - public function __invoke(DeleteBookmark $command): void - { - $bookmark = $this->bookmarkRepository->getById($command->bookmarkId); - if ($bookmark->user->id !== $command->userId) { - throw PermissionNotGranted::withReason('feed_management.exceptions.cannot_delete_bookmark'); - } - - $this->bookmarkRepository->remove($bookmark); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/FollowSourceHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/FollowSourceHandler.php deleted file mode 100644 index 80b19ec..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/FollowSourceHandler.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ -final readonly class FollowSourceHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private SourceRepository $sourceRepository, - private FollowedSourceRepository $followedSourceRepository - ) { - } - - public function __invoke(FollowSource $command): void - { - $followedSource = $this->followedSourceRepository->getByUserId( - $command->userId, - $command->sourceId - ); - - if ($followedSource instanceof FollowedSource) { - throw SourceAlreadyFollowed::with($command->userId, $command->sourceId); - } - - $user = $this->userRepository->getById($command->userId); - $source = $this->sourceRepository->getById($command->sourceId); - - $followedSource = new FollowedSource($source, $user); - $this->followedSourceRepository->add($followedSource); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveArticleFromBookmarkHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveArticleFromBookmarkHandler.php deleted file mode 100644 index 6ed9b62..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveArticleFromBookmarkHandler.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final readonly class RemoveArticleFromBookmarkHandler implements CommandHandler -{ - public function __construct( - private BookmarkRepository $bookmarkRepository, - private ArticleRepository $articleRepository - ) { - } - - public function __invoke(RemoveArticleFromBookmark $command): void - { - $bookmark = $this->bookmarkRepository->getById($command->bookmarkId); - if ($bookmark->user->id !== $command->userId) { - throw PermissionNotGranted::withReason('feed_management.exceptions.cannot_remove_article_from_bookmark'); - } - - $article = $this->articleRepository->getById($command->articleId); - $bookmark->removeArticle($article); - - $this->bookmarkRepository->add($bookmark); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveCommentFromArticleHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveCommentFromArticleHandler.php deleted file mode 100644 index 128f1ba..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/RemoveCommentFromArticleHandler.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class RemoveCommentFromArticleHandler implements CommandHandler -{ - public function __construct( - private CommentRepository $commentRepository, - ) { - } - - public function __invoke(RemoveCommentFromArticle $command): void - { - $comment = $this->commentRepository->getById($command->commentId); - if ($command->userId !== $comment->user->id) { - throw PermissionNotGranted::withReason('feed_management.exceptions.cannot_delete_comment'); - } - - $this->commentRepository->remove($comment); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UnfollowSourceHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UnfollowSourceHandler.php deleted file mode 100644 index ccf5412..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UnfollowSourceHandler.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final readonly class UnfollowSourceHandler implements CommandHandler -{ - public function __construct( - private FollowedSourceRepository $followedSourceRepository - ) { - } - - public function __invoke(UnfollowSource $command): void - { - $followedSource = $this->followedSourceRepository->getByUserId( - $command->userId, - $command->sourceId - ); - - if (! $followedSource instanceof FollowedSource) { - throw FollowedSourceNotFound::with($command->userId, $command->sourceId); - } - - $this->followedSourceRepository->remove($followedSource); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UpdateBookmarkHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UpdateBookmarkHandler.php deleted file mode 100644 index fe3f42b..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/CommandHandler/UpdateBookmarkHandler.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final readonly class UpdateBookmarkHandler implements CommandHandler -{ - public function __construct( - private BookmarkRepository $bookmarkRepository - ) { - } - - public function __invoke(UpdateBookmark $command): void - { - $bookmark = $this->bookmarkRepository->getById($command->bookmarkId); - if ($bookmark->user->id !== $command->userId) { - throw PermissionNotGranted::withReason('feed_management.exceptions.cannot_update_bookmark'); - } - - $bookmark = match ($command->isPublic) { - true => $bookmark->markAsPublic(), - false => $bookmark->markAsPrivate(), - }; - $bookmark->updateInfos($command->name, $command->description); - - $this->bookmarkRepository->add($bookmark); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleCommentList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleCommentList.php deleted file mode 100644 index 72e72ca..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleCommentList.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class GetArticleCommentList -{ - public function __construct( - public ArticleId $articleId, - public Page $page = new Page(), - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleDetails.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleDetails.php deleted file mode 100644 index 61372a4..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleDetails.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class GetArticleDetails -{ - public function __construct( - public ArticleId $id, - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleOverviewList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleOverviewList.php deleted file mode 100644 index 994d6fc..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetArticleOverviewList.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final readonly class GetArticleOverviewList -{ - public function __construct( - public UserId $userId, - public Page $page = new Page(), - public ArticleFilters $filters = new ArticleFilters(), - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkList.php deleted file mode 100644 index 70a6d99..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkList.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class GetBookmarkList -{ - public function __construct( - public UserId $userId, - public Page $page = new Page(), - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkedArticleList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkedArticleList.php deleted file mode 100644 index 716bae2..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetBookmarkedArticleList.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final readonly class GetBookmarkedArticleList -{ - public function __construct( - public UserId $userId, - public BookmarkId $bookmarkId, - public Page $page = new Page(), - public ArticleFilters $filters = new ArticleFilters() - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceArticleOverviewList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceArticleOverviewList.php deleted file mode 100644 index 9ed3d78..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceArticleOverviewList.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final readonly class GetSourceArticleOverviewList -{ - public function __construct( - public SourceId $sourceId, - public UserId $userId, - public Page $page = new Page(), - public ArticleFilters $filters = new ArticleFilters(), - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceDetails.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceDetails.php deleted file mode 100644 index 9448779..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceDetails.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class GetSourceDetails -{ - public function __construct( - public SourceId $sourceId, - public UserId $userId, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceOverviewList.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceOverviewList.php deleted file mode 100644 index 5d49daf..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/Query/GetSourceOverviewList.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class GetSourceOverviewList -{ - public function __construct( - public UserId $userId, - public Page $page = new Page(), - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleCommentListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleCommentListHandler.php deleted file mode 100644 index e126aac..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleCommentListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetArticleCommentListHandler extends QueryHandler -{ - public function __invoke(GetArticleCommentList $query): CommentList; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleDetailsHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleDetailsHandler.php deleted file mode 100644 index 8eca1cf..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleDetailsHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetArticleDetailsHandler extends QueryHandler -{ - public function __invoke(GetArticleDetails $query): ArticleDetails; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleOverviewListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleOverviewListHandler.php deleted file mode 100644 index 3ae4ddb..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetArticleOverviewListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetArticleOverviewListHandler extends QueryHandler -{ - public function __invoke(GetArticleOverviewList $query): ArticleOverviewList; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkListHandler.php deleted file mode 100644 index 411a91e..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetBookmarkListHandler extends QueryHandler -{ - public function __invoke(GetBookmarkList $query): BookmarkList; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkedArticleListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkedArticleListHandler.php deleted file mode 100644 index 0f19c5a..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetBookmarkedArticleListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetBookmarkedArticleListHandler extends QueryHandler -{ - public function __invoke(GetBookmarkedArticleList $query): ArticleOverviewList; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceArticleOverviewListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceArticleOverviewListHandler.php deleted file mode 100644 index 5b0875a..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceArticleOverviewListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetSourceArticleOverviewListHandler extends QueryHandler -{ - public function __invoke(GetSourceArticleOverviewList $query): ArticleOverviewList; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceDetailsHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceDetailsHandler.php deleted file mode 100644 index febc236..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceDetailsHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetSourceDetailsHandler extends QueryHandler -{ - public function __invoke(GetSourceDetails $query): SourceDetails; -} diff --git a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceOverviewListHandler.php b/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceOverviewListHandler.php deleted file mode 100644 index 6fad62c..0000000 --- a/apps/api-legacy/src/FeedManagement/Application/UseCase/QueryHandler/GetSourceOverviewListHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetSourceOverviewListHandler extends QueryHandler -{ - public function __invoke(GetSourceOverviewList $query): SourceOverviewList; -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/ArticleAlreadyBookmarked.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/ArticleAlreadyBookmarked.php deleted file mode 100644 index 13a9de7..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/ArticleAlreadyBookmarked.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class ArticleAlreadyBookmarked extends \DomainException implements UserFacingError -{ - public static function with(ArticleId $articleId, BookmarkId $bookmarkId): self - { - return new self(sprintf('Article %s already bookmarked in bookmark %s', $articleId->toString(), $bookmarkId->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.article_already_bookmarked'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkNotFound.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkNotFound.php deleted file mode 100644 index 0d6377c..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkNotFound.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class BookmarkNotFound extends \DomainException implements UserFacingError -{ - public static function withId(BookmarkId $id): self - { - return new self(sprintf('Bookmark with id "%s" not found.', $id->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.bookmark_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkedArticleNotFound.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkedArticleNotFound.php deleted file mode 100644 index 21e24e7..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/BookmarkedArticleNotFound.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class BookmarkedArticleNotFound extends \DomainException implements UserFacingError -{ - public static function with(ArticleId $articleId, BookmarkId $bookmarkId): self - { - return new self(sprintf('Article %s not found in bookmark %s', $articleId->toString(), $bookmarkId->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.bookmarked_article_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/CommentNotFound.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/CommentNotFound.php deleted file mode 100644 index 5ed3570..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/CommentNotFound.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class CommentNotFound extends \DomainException implements UserFacingError -{ - public static function withId(CommentId $id): self - { - return new self(sprintf('Comment with id "%s" not found.', $id->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.comment_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/FollowedSourceNotFound.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/FollowedSourceNotFound.php deleted file mode 100644 index 8eac7ec..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/FollowedSourceNotFound.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class FollowedSourceNotFound extends \DomainException implements UserFacingError -{ - public static function with(UserId $userId, SourceId $sourceId): self - { - return new self(sprintf('User %s does not follow source %s', $userId->toString(), $sourceId->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.followed_source_not_found'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Exception/SourceAlreadyFollowed.php b/apps/api-legacy/src/FeedManagement/Domain/Exception/SourceAlreadyFollowed.php deleted file mode 100644 index 88a24ed..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Exception/SourceAlreadyFollowed.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class SourceAlreadyFollowed extends \DomainException implements UserFacingError -{ - public static function with(UserId $userId, SourceId $sourceId): self - { - return new self(sprintf('User %s already follows source %s', $userId->toString(), $sourceId->toString())); - } - - public function translationId(): string - { - return 'feed_management.exceptions.source_already_followed'; - } - - public function translationParameters(): array - { - return []; - } - - public function translationDomain(): string - { - return 'feed_management'; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Bookmark.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Bookmark.php deleted file mode 100644 index 80ad1d5..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Bookmark.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ -class Bookmark -{ - public readonly BookmarkId $id; - - /** - * @var DataCollection - */ - public private(set) iterable $articles; - - private function __construct( - public readonly User $user, - private(set) string $name, - private(set) ?string $description, - private(set) bool $isPublic = false, - private(set) ?\DateTimeImmutable $updatedAt = null, - public readonly \DateTimeImmutable $createdAt = new \DateTimeImmutable() - ) { - $this->id = new BookmarkId(); - $this->articles = new DataCollection(); - } - - public static function create(User $user, string $name, ?string $description = null): self - { - return new self($user, $name, $description); - } - - public function updateInfos(string $name, ?string $description = null): self - { - $this->name = $name; - $this->description = $description; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function markAsPrivate(): self - { - $this->isPublic = false; - - return $this; - } - - public function markAsPublic(): self - { - $this->isPublic = true; - - return $this; - } - - public function addArticle(Article $article): self - { - if ($this->articles->contains($article)) { - throw ArticleAlreadyBookmarked::with($article->id, $this->id); - } - - $this->articles->add($article); - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function removeArticle(Article $article): self - { - if (! $this->articles->contains($article)) { - throw BookmarkedArticleNotFound::with($article->id, $this->id); - } - - $this->articles->removeElement($article); - - return $this; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Comment.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Comment.php deleted file mode 100644 index e2298ba..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/Comment.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -class Comment -{ - public readonly CommentId $id; - - public function __construct( - public readonly User $user, - public readonly Article $article, - public readonly string $content, - private(set) bool $isSpam = false, - private(set) Sentiment $sentiment = Sentiment::NEUTRAL, - public readonly \DateTimeImmutable $createdAt = new \DateTimeImmutable(), - ) { - $this->id = new CommentId(); - } - - public static function create(User $user, Article $article, string $content): self - { - return new self($user, $article, $content); - } - - public function defineSentiment(Sentiment $sentiment): self - { - $this->sentiment = $sentiment; - - return $this; - } - - public function markAsSpam(): self - { - $this->isSpam = true; - - return $this; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/FollowedSource.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/FollowedSource.php deleted file mode 100644 index 938b7c8..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Entity/FollowedSource.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -readonly class FollowedSource -{ - public FollowedSourceId $id; - - public function __construct( - public Source $source, - public User $follower, - public \DateTimeImmutable $createdAt = new \DateTimeImmutable(), - ) { - $this->id = new FollowedSourceId(); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Filters/ArticleFilters.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Filters/ArticleFilters.php deleted file mode 100644 index 228e98f..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Filters/ArticleFilters.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final class ArticleFilters -{ - public function __construct( - public ?string $search = null, - public ?string $category = null, - public ?DateRange $dateRange = null, - public SortDirection $sortDirection = SortDirection::DESC, - ) { - } -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/BookmarkId.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/BookmarkId.php deleted file mode 100644 index 9dfbd2a..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/BookmarkId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class BookmarkId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/CommentId.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/CommentId.php deleted file mode 100644 index 90e33d5..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/CommentId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class CommentId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/FollowedSourceId.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/FollowedSourceId.php deleted file mode 100644 index 4847abb..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Identity/FollowedSourceId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class FollowedSourceId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/BookmarkRepository.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/BookmarkRepository.php deleted file mode 100644 index a4b5f96..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/BookmarkRepository.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface BookmarkRepository -{ - public function add(Bookmark $bookmark): void; - - public function remove(Bookmark $bookmark): void; - - public function getById(BookmarkId $bookmarkId): Bookmark; -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/CommentRepository.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/CommentRepository.php deleted file mode 100644 index d8c27a3..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/CommentRepository.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface CommentRepository -{ - public function add(Comment $comment): void; - - public function remove(Comment $comment): void; - - public function getById(CommentId $commentId): Comment; -} diff --git a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/FollowedSourceRepository.php b/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/FollowedSourceRepository.php deleted file mode 100644 index 4f28fb9..0000000 --- a/apps/api-legacy/src/FeedManagement/Domain/Model/Repository/FollowedSourceRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -interface FollowedSourceRepository -{ - public function add(FollowedSource $followedSource): void; - - public function remove(FollowedSource $followedSource): void; - - public function getByUserId(UserId $userId, SourceId $sourceId): ?FollowedSource; -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleCommentListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleCommentListDbalHandler.php deleted file mode 100644 index 9c72fc4..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleCommentListDbalHandler.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ -final readonly class GetArticleCommentListDbalHandler implements GetArticleCommentListHandler -{ - use PaginationQuery; - - public function __construct( - private Connection $connection, - ) { - } - - public function __invoke(GetArticleCommentList $query): CommentList - { - $qb = $this->connection->createQueryBuilder() - ->select( - 'c.id as comment_id', - 'c.content as comment_content', - 'c.sentiment as comment_sentiment', - 'c.created_at as comment_created_at' - ) - ->addSelect('u.id as user_id, u.name as user_name') - ->from('comment', 'c') - ->innerJoin('c', 'user', 'u', 'c.user_id = u.id') - ->where('c.article_id = :articleId') - ->setParameter('articleId', $query->articleId->toString()); - - $qb = $this->applyCursorPagination($qb, $query->page, new PaginatorKeyset('c.id', 'c.created_at')); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('comment_id', 'comment_created_at')); - return CommentList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleDetailsDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleDetailsDbalHandler.php deleted file mode 100644 index b6024a7..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleDetailsDbalHandler.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final readonly class GetArticleDetailsDbalHandler implements GetArticleDetailsHandler -{ - use BookmarkQuery; - use SourceQuery; - use ArticleQuery; - - public function __construct( - private Connection $connection, - ) { - } - - #[\Override] - public function __invoke(GetArticleDetails $query): ArticleDetails - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addArticleDetailsSelectQuery($qb); - $qb = $this->addSourceOverviewSelectQuery($qb); - $qb = $this->addArticleBookmarkedExistsQuery($qb); - - $qb->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->from('article', 'a') - ->where('a.id = :articleId') - ->setParameter('articleId', $query->id->toString()) - ->setParameter('userId', $query->userId->toString()) - ; - - try { - /** @var array|false $data */ - $data = $qb->executeQuery()->fetchAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - if ($data === false) { - throw ArticleNotFound::withId($query->id); - } - - return ArticleDetails::create($data); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleOverviewListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleOverviewListDbalHandler.php deleted file mode 100644 index 921d210..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetArticleOverviewListDbalHandler.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ -final readonly class GetArticleOverviewListDbalHandler implements GetArticleOverviewListHandler -{ - use PaginationQuery; - use BookmarkQuery; - use ArticleQuery; - use SourceQuery; - - public function __construct( - private Connection $connection, - ) { - } - - #[\Override] - public function __invoke(GetArticleOverviewList $query): ArticleOverviewList - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addArticleOverviewSelectQuery($qb); - $qb = $this->addSourceOverviewSelectQuery($qb); - $qb = $this->addArticleBookmarkedExistsQuery($qb); - - $qb->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->orderBy('a.published_at', $query->filters->sortDirection->value) - ->setParameter('userId', $query->userId->toString()) - ; - - $qb = $this->applyArticleFilters($qb, $query->filters); - $qb = $this->applyCursorPagination( - $qb, - $query->page, - new PaginatorKeyset('a.id', 'a.published_at'), - $query->filters->sortDirection - ); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('article_id', 'article_published_at')); - return ArticleOverviewList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkListDbalHandler.php deleted file mode 100644 index 22bbdde..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkListDbalHandler.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -final readonly class GetBookmarkListDbalHandler implements GetBookmarkListHandler -{ - use PaginationQuery; - use BookmarkQuery; - - public function __construct( - private Connection $connection, - ) { - } - - public function __invoke(GetBookmarkList $query): BookmarkList - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addBookmarkSelectQuery($qb); - - $qb->from('bookmark', 'b') - ->leftJoin('b', 'bookmark_article', 'ba', 'ba.bookmark_id = b.id') - ->where('b.user_id = :userId') - ->groupBy('b.id') - ->setParameter('userId', $query->userId->toString()) - ; - - $qb = $this->applyCursorPagination($qb, $query->page, new PaginatorKeyset('b.id')); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('bookmark_id')); - return BookmarkList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkedArticleListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkedArticleListDbalHandler.php deleted file mode 100644 index 157cd4d..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetBookmarkedArticleListDbalHandler.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final readonly class GetBookmarkedArticleListDbalHandler implements GetBookmarkedArticleListHandler -{ - use PaginationQuery; - use ArticleQuery; - use SourceQuery; - - public function __construct( - private Connection $connection, - ) { - } - - public function __invoke(GetBookmarkedArticleList $query): ArticleOverviewList - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addArticleOverviewSelectQuery($qb); - $qb = $this->addSourceOverviewSelectQuery($qb); - - $qb - ->addSelect('1 as article_is_bookmarked') - ->from('bookmark_article', 'ba') - ->innerJoin('ba', 'article', 'a', 'a.id = ba.article_id') - ->innerJoin('ba', 'bookmark', 'b', 'b.id = ba.bookmark_id AND b.user_id = :userId') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where('b.id = :bookmarkId') - ->setParameter('bookmarkId', $query->bookmarkId->toString()) - ->setParameter('userId', $query->userId->toString()) - ; - - $qb = $this->applyArticleFilters($qb, $query->filters); - $qb = $this->applyCursorPagination( - $qb, - $query->page, - new PaginatorKeyset('a.id', 'a.published_at'), - $query->filters->sortDirection - ); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('article_id', 'article_published_at')); - return ArticleOverviewList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceArticleOverviewListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceArticleOverviewListDbalHandler.php deleted file mode 100644 index 2cddd11..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceArticleOverviewListDbalHandler.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final readonly class GetSourceArticleOverviewListDbalHandler implements GetSourceArticleOverviewListHandler -{ - use PaginationQuery; - use BookmarkQuery; - use ArticleQuery; - use SourceQuery; - - public function __construct( - private Connection $connection, - ) { - } - - #[\Override] - public function __invoke(GetSourceArticleOverviewList $query): ArticleOverviewList - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addArticleOverviewSelectQuery($qb); - $qb = $this->addSourceOverviewSelectQuery($qb); - $qb = $this->addArticleBookmarkedExistsQuery($qb); - - $qb->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where('s.id = :sourceId') - ->setParameter('userId', $query->userId->toString()) - ->setParameter('sourceId', $query->sourceId->toString()) - ; - - $qb = $this->applyArticleFilters($qb, $query->filters); - $qb = $this->applyCursorPagination( - $qb, - $query->page, - new PaginatorKeyset('a.id', 'a.published_at'), - $query->filters->sortDirection - ); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('article_id', 'article_published_at')); - return ArticleOverviewList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceDetailsDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceDetailsDbalHandler.php deleted file mode 100644 index 5f01a88..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceDetailsDbalHandler.php +++ /dev/null @@ -1,165 +0,0 @@ - - */ -final readonly class GetSourceDetailsDbalHandler implements GetSourceDetailsHandler -{ - use SourceQuery; - - private const int PUBLICATION_GRAPH_DAYS = 180; - - public function __construct( - private Connection $connection, - private CacheInterface $cache - ) { - } - - #[\Override] - public function __invoke(GetSourceDetails $query): SourceDetails - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addSourceDetailsSelectQuery($qb); - $qb = $this->addFollowedSourceExistsQuery($qb); - - $qb->from('source', 's') - ->leftJoin('s', 'article', 'a', 'a.source_id = s.id') - ->where('s.id = :sourceId') - ->setParameter('sourceId', $query->sourceId->toString()) - ->setParameter('userId', $query->userId->toString()); - // Aggregate columns are selected; include non-aggregated columns in GROUP BY for PostgreSQL - $qb->groupBy('s.id, s.name, s.description, s.url, s.updated_at, s.display_name, s.bias, s.reliability, s.transparency'); - - try { - $data = $qb->executeQuery()->fetchAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - if (empty($data['source_id'])) { - throw SourceNotFound::withId($query->sourceId); - } - - return SourceDetails::create( - $data, - $this->getPublicationGraph($query), - $this->getCategoryShares($query) - ); - } - - public function getPublicationGraph(GetSourceDetails $query): PublicationGraph - { - $cacheKey = SourceCacheAttributes::PUBLICATIONS->withId($query->sourceId->toString()); - $dateRange = DateRange::backward(days: self::PUBLICATION_GRAPH_DAYS); - - $qb = $this->connection->createQueryBuilder() - ->select('DATE(a.published_at) AS day, COUNT(a.id) AS count') - ->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where(' s.id = :sourceId') - ->andWhere('a.published_at BETWEEN to_timestamp(:start) AND to_timestamp(:end)') - ->groupBy('day') - ->orderBy('day', 'ASC') - ->setParameter('sourceId', $query->sourceId->toString()) - ->setParameter('start', $dateRange->start, ParameterType::INTEGER) - ->setParameter('end', $dateRange->end, ParameterType::INTEGER) - ->enableResultCache(new QueryCacheProfile(SourceCacheAttributes::CACHE_TTL, $cacheKey)); - - try { - /** @var list $data */ - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - return $this->cache->get($cacheKey, function (ItemInterface $item) use ($data, $dateRange): PublicationGraph { - $item->expiresAfter(SourceCacheAttributes::CACHE_TTL); - - $countsByDate = []; - foreach ($data as $row) { - $countsByDate[$row['day']] = (int) $row['count']; - } - - $start = \DateTimeImmutable::createFromTimestamp($dateRange->start); - $end = \DateTimeImmutable::createFromTimestamp($dateRange->end); - $period = new \DatePeriod($start, new \DateInterval('P1D'), $end); - - $heatmap = []; - foreach ($period as $date) { - $day = $date->format('Y-m-d'); - $heatmap[] = new PublicationEntry($day, $countsByDate[$day] ?? 0); - } - - return new PublicationGraph($heatmap, count($heatmap)); - }); - } - - public function getCategoryShares(GetSourceDetails $query): CategoryShares - { - $cacheKey = SourceCacheAttributes::CATEGORIES->withId($query->sourceId->toString()); - $qb = $this->connection->createQueryBuilder() - ->select("array_to_string(a.categories, ',') AS categories") - ->from('article', 'a') - ->innerJoin('a', 'source', 's', 'a.source_id = s.id') - ->where('s.id = :sourceId') - ->setParameter('sourceId', $query->sourceId->toString()) - ->enableResultCache(new QueryCacheProfile(SourceCacheAttributes::CACHE_TTL, $cacheKey)); - - try { - /** @var array $categories */ - $categories = $qb->executeQuery()->fetchFirstColumn(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - return $this->cache->get($cacheKey, function (ItemInterface $item) use ($categories): CategoryShares { - $item->expiresAfter(SourceCacheAttributes::CACHE_TTL); - - $counts = []; - foreach ($categories as $row) { - foreach (array_filter(array_map('trim', explode(',', $row))) as $cat) { - $counts[$cat] = ($counts[$cat] ?? 0) + 1; - } - } - - $total = array_sum($counts); - - $shares = array_map( - fn (string $category, int $count): CategoryShare => new CategoryShare( - category: $category, - count: $count, - percentage: $total > 0 ? round(($count / $total) * 100, 2) : 0.0 - ), - array_keys($counts), - array_values($counts) - ); - usort($shares, fn (CategoryShare $a, CategoryShare $b): int => ($a->count <=> $b->count) * -1); - - return new CategoryShares($shares, count($counts)); - }); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceOverviewListDbalHandler.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceOverviewListDbalHandler.php deleted file mode 100644 index d215b86..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/GetSourceOverviewListDbalHandler.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ -final readonly class GetSourceOverviewListDbalHandler implements GetSourceOverviewListHandler -{ - use PaginationQuery; - use SourceQuery; - - public function __construct( - private Connection $connection, - ) { - } - - #[\Override] - public function __invoke(GetSourceOverviewList $query): SourceOverviewList - { - $qb = $this->connection->createQueryBuilder(); - $qb = $this->addSourceOverviewSelectQuery($qb); - $qb = $this->addFollowedSourceExistsQuery($qb); - - $qb->from('source', 's') - ->setParameter('userId', $query->userId->toString()) - ; - - $qb = $this->applyCursorPagination($qb, $query->page, new PaginatorKeyset('s.id', 's.created_at')); - - try { - $data = $qb->executeQuery()->fetchAllAssociative(); - } catch (\Throwable $e) { - throw NoResult::forQuery($qb->getSQL(), $qb->getParameters(), $e); - } - - $pagination = $this->createPaginationInfo($data, $query->page, new PaginatorKeyset('source_id', 'source_created_at')); - return SourceOverviewList::create($data, $pagination); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/ArticleQuery.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/ArticleQuery.php deleted file mode 100644 index e37076d..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/ArticleQuery.php +++ /dev/null @@ -1,86 +0,0 @@ - - */ -trait ArticleQuery -{ - private function addArticleOverviewSelectQuery(QueryBuilder $qb): QueryBuilder - { - return $qb->addSelect( - 'a.id as article_id', - 'a.title as article_title', - 'a.link as article_link', - "array_to_string(a.categories, ',') as article_categories", - 'a.excerpt as article_excerpt', - 'a.published_at as article_published_at', - 'a.image as article_image', - 'a.reading_time as article_reading_time', - ); - } - - private function addArticleDetailsSelectQuery(QueryBuilder $qb): QueryBuilder - { - return $qb->addSelect( - 'a.id as article_id', - 'a.title as article_title', - 'a.link as article_link', - "array_to_string(a.categories, ',') as article_categories", - 'a.body as article_body', - 'a.hash as article_hash', - 'a.published_at as article_published_at', - 'a.crawled_at as article_crawled_at', - 'a.updated_at as article_updated_at', - 'a.bias as article_bias', - 'a.reliability as article_reliability', - 'a.transparency as article_transparency', - 'a.sentiment as article_sentiment', - 'a.metadata as article_metadata', - 'a.reading_time as article_reading_time', - ); - } - - /** - * Applies filters to the provided QueryBuilder instance based on the given ArticleFilters. - * - * @param QueryBuilder $qb The query builder instance to which filters will be applied. - * @param ArticleFilters $filters The filters containing criteria for filtering articles. - * - * @return QueryBuilder The updated query builder with the applied filters. - */ - private function applyArticleFilters(QueryBuilder $qb, ArticleFilters $filters): QueryBuilder - { - if ($filters->category !== null) { - $qb->andWhere(':category = ANY(a.categories)') - ->setParameter('category', $filters->category); - } - - if ($filters->search !== null) { - $qb - ->addSelect("ts_rank(a.tsv, to_tsquery('french', :search)) AS rank") - ->andWhere("a.tsv @@ to_tsquery('french', :search)") - ->setParameter('search', $filters->search) - ->resetOrderBy() - ->orderBy('rank', $filters->sortDirection->value); - } - - if ($filters->dateRange instanceof DateRange) { - $qb->andWhere('a.published_at BETWEEN to_timestamp(:start) AND to_timestamp(:end)') - ->setParameter('start', $filters->dateRange->start, ParameterType::INTEGER) - ->setParameter('end', $filters->dateRange->end, ParameterType::INTEGER); - } - - return $qb; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/BookmarkQuery.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/BookmarkQuery.php deleted file mode 100644 index 83c617f..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/BookmarkQuery.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -trait BookmarkQuery -{ - private function addBookmarkSelectQuery(QueryBuilder $qb): QueryBuilder - { - return $qb->addSelect( - 'b.id AS bookmark_id', - 'b.name AS bookmark_name', - 'b.description AS bookmark_description', - 'b.created_at AS bookmark_created_at', - 'b.updated_at AS bookmark_updated_at', - 'COUNT(ba.article_id) AS bookmark_articles_count', - 'b.is_public AS bookmark_is_public' - ); - } - - private function addArticleBookmarkedExistsQuery(QueryBuilder $qb): QueryBuilder - { - $subQb = $this->connection->createQueryBuilder() - ->select('1') - ->from('bookmark_article', 'ba') - ->innerJoin('ba', 'bookmark', 'b', 'ba.bookmark_id = b.id') - ->where('ba.article_id = a.id') - ->andWhere('b.user_id = :userId'); - $query = sprintf('EXISTS (%s)', $subQb->getSQL()); - - return $qb->addSelect(sprintf('%s as article_is_bookmarked', $query)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/SourceQuery.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/SourceQuery.php deleted file mode 100644 index 6f9a472..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Queries/SourceQuery.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -trait SourceQuery -{ - private function addSourceOverviewSelectQuery(QueryBuilder $qb): QueryBuilder - { - return $qb - ->addSelect( - 's.id as source_id', - 's.display_name as source_display_name', - "CONCAT('https://devscast.org/images/sources/', s.name, '.png') as source_image", - 's.url as source_url', - 's.name as source_name', - 's.created_at as source_created_at', - ); - } - - private function addSourceDetailsSelectQuery(QueryBuilder $qb): QueryBuilder - { - return $qb->addSelect( - 's.id as source_id', - 's.name as source_name', - 's.description as source_description', - 's.url as source_url', - 's.updated_at as source_updated_at', - 's.display_name as source_display_name', - 's.bias as source_bias', - 's.reliability as source_reliability', - 's.transparency as source_transparency', - "CONCAT('https://devscast.org/images/sources/', s.name, '.png') as source_image", - 'COUNT(a.hash) AS articles_count', - 'MAX(a.crawled_at) AS source_crawled_at', - 'COUNT(*) FILTER (WHERE a.metadata IS NOT NULL) AS articles_metadata_available', - ); - } - - private function addFollowedSourceExistsQuery(QueryBuilder $qb): QueryBuilder - { - $subQb = $this->connection->createQueryBuilder() - ->select('1') - ->from('followed_source', 'f') - ->where('f.source_id = s.id') - ->andWhere('f.follower_id = :userId'); - $query = sprintf('EXISTS (%s)', $subQb->getSQL()); - - return $qb->addSelect(sprintf('%s as source_is_followed', $query)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/BookmarkIdType.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/BookmarkIdType.php deleted file mode 100644 index 7b9c0a9..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/BookmarkIdType.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class BookmarkIdType extends AbstractUidType -{ - public function getName(): string - { - return 'bookmark_id'; - } - - protected function getUidClass(): string - { - return BookmarkId::class; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/CommentIdType.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/CommentIdType.php deleted file mode 100644 index 93d0e50..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/CommentIdType.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class CommentIdType extends AbstractUidType -{ - public function getName(): string - { - return 'comment_id'; - } - - protected function getUidClass(): string - { - return CommentId::class; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/FollowedSourceIdType.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/FollowedSourceIdType.php deleted file mode 100644 index c2662f9..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/DBAL/Types/FollowedSourceIdType.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class FollowedSourceIdType extends AbstractUidType -{ - public function getName(): string - { - return 'followed_source_id'; - } - - protected function getUidClass(): string - { - return FollowedSourceId::class; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/BookmarkOrmRepository.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/BookmarkOrmRepository.php deleted file mode 100644 index 26fe894..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/BookmarkOrmRepository.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * @author bernard-ng - */ -final class BookmarkOrmRepository extends ServiceEntityRepository implements BookmarkRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Bookmark::class); - } - - public function add(Bookmark $bookmark): void - { - $this->getEntityManager()->persist($bookmark); - $this->getEntityManager()->flush(); - } - - public function remove(Bookmark $bookmark): void - { - $this->getEntityManager()->remove($bookmark); - $this->getEntityManager()->flush(); - } - - public function getById(BookmarkId $bookmarkId): Bookmark - { - $bookmark = $this->findOneBy([ - 'id' => $bookmarkId, - ]); - - if ($bookmark === null) { - throw BookmarkNotFound::withId($bookmarkId); - } - - return $bookmark; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/CommentOrmRepository.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/CommentOrmRepository.php deleted file mode 100644 index 0096fa1..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/CommentOrmRepository.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * @author bernard-ng - */ -final class CommentOrmRepository extends ServiceEntityRepository implements CommentRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Comment::class); - } - - public function add(Comment $comment): void - { - $this->getEntityManager()->persist($comment); - $this->getEntityManager()->flush(); - } - - public function remove(Comment $comment): void - { - $this->getEntityManager()->remove($comment); - $this->getEntityManager()->flush(); - } - - public function getById(CommentId $commentId): Comment - { - $comment = $this->findOneBy([ - 'id' => $commentId, - ]); - - if (! $comment instanceof Comment) { - throw CommentNotFound::withId($commentId); - } - - return $comment; - } -} diff --git a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/FollowedSourceOrmRepository.php b/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/FollowedSourceOrmRepository.php deleted file mode 100644 index e677977..0000000 --- a/apps/api-legacy/src/FeedManagement/Infrastructure/Persistence/Doctrine/ORM/FollowedSourceOrmRepository.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * @author bernard-ng - */ -final class FollowedSourceOrmRepository extends ServiceEntityRepository implements FollowedSourceRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, FollowedSource::class); - } - - public function add(FollowedSource $followedSource): void - { - $this->getEntityManager()->persist($followedSource); - $this->getEntityManager()->flush(); - } - - public function remove(FollowedSource $followedSource): void - { - $this->getEntityManager()->remove($followedSource); - $this->getEntityManager()->flush(); - } - - public function getByUserId(UserId $userId, SourceId $sourceId): ?FollowedSource - { - return $this->createQueryBuilder('fs') - ->andWhere('IDENTITY(fs.follower) = :userId') - ->andWhere('IDENTITY(fs.source) = :sourceId') - ->setParameter('sourceId', $sourceId->toString()) - ->setParameter('userId', $userId->toString()) - ->getQuery() - ->getOneOrNullResult(); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddArticleToBookmarkController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddArticleToBookmarkController.php deleted file mode 100644 index 1c665ca..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddArticleToBookmarkController.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final class AddArticleToBookmarkController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks/{bookmarkId}/articles/{articleId}', - name: 'feed_management_add_article_to_bookmark', - requirements: [ - 'bookmarkId' => Requirement::UUID_V7, - 'articleId' => Requirement::UUID_V7, - ], - methods: ['POST'] - )] - public function __invoke(BookmarkId $bookmarkId, ArticleId $articleId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new AddArticleToBookmark($securityUser->userId, $articleId, $bookmarkId)); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddCommentToArticleController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddCommentToArticleController.php deleted file mode 100644 index 97e04d3..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/AddCommentToArticleController.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final class AddCommentToArticleController extends AbstractController -{ - #[Route( - path: '/api/feed/articles/{articleId}/comments', - name: 'feed_management_add_comment_to_article', - requirements: [ - 'articleId' => Requirement::UUID_V7, - ], - methods: ['POST'] - )] - public function __invoke(ArticleId $articleId, #[MapRequestPayload] AddCommentToArticleModel $model): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new AddCommentToArticle($securityUser->userId, $articleId, $model->content)); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/CreateBookmarkController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/CreateBookmarkController.php deleted file mode 100644 index c3e571f..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/CreateBookmarkController.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final class CreateBookmarkController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks', - name: 'feed_management_create_bookmark', - methods: ['POST'] - )] - public function __invoke(#[MapRequestPayload] CreateBookmarkModel $model): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new CreateBookmark( - $securityUser->userId, - $model->name, - $model->description - )); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/DeleteBookmarkController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/DeleteBookmarkController.php deleted file mode 100644 index 0c6f5cd..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/DeleteBookmarkController.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class DeleteBookmarkController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks/{bookmarkId}', - name: 'feed_management_delete_bookmark', - requirements: [ - 'bookmarkId' => Requirement::UUID_V7, - ], - methods: ['DELETE'] - )] - public function __invoke(BookmarkId $bookmarkId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new DeleteBookmark($securityUser->userId, $bookmarkId)); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/FollowSourceController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/FollowSourceController.php deleted file mode 100644 index 670ecdb..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/FollowSourceController.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class FollowSourceController extends AbstractController -{ - #[Route( - path: '/api/feed/sources/{sourceId}/follow', - name: 'feed_management_follow_source', - requirements: [ - 'sourceId' => Requirement::UUID_V7, - ], - methods: ['POST'] - )] - public function __invoke(SourceId $sourceId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new FollowSource($sourceId, $securityUser->userId)); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleCommentListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleCommentListController.php deleted file mode 100644 index 307eb83..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleCommentListController.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final class GetArticleCommentListController extends AbstractController -{ - #[Route( - path: '/api/feed/articles/{articleId}/comments', - name: 'feed_management_article_comment_list', - requirements: [ - 'articleId' => Requirement::UUID_V7, - ], - methods: ['GET'] - )] - public function __invoke(ArticleId $articleId, #[MapQueryString] Page $page): JsonResponse - { - /** @var CommentList $data */ - $data = $this->handleQuery(new GetArticleCommentList($articleId, $page)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleDetailsController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleDetailsController.php deleted file mode 100644 index 6be1888..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleDetailsController.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class GetArticleDetailsController extends AbstractController -{ - #[Route( - path: 'api/feed/articles/{articleId}', - name: 'feed_management_article_details', - requirements: [ - 'articleId' => Requirement::UUID_V7, - ], - methods: ['GET'] - )] - public function __invoke(ArticleId $articleId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetArticleDetails($articleId, $securityUser->userId)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleOverviewListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleOverviewListController.php deleted file mode 100644 index 33855a8..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetArticleOverviewListController.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class GetArticleOverviewListController extends AbstractController -{ - #[Route( - path: 'api/feed/articles', - name: 'feed_management_article_overview_list', - methods: ['GET'] - )] - public function __invoke( - #[MapQueryString] Page $page, - #[MapQueryString] ArticleFilters $filters - ): JsonResponse { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetArticleOverviewList($securityUser->userId, $page, $filters)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkListController.php deleted file mode 100644 index bf4c7d0..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkListController.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class GetBookmarkListController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks', - name: 'feed_management_bookmark_list', - methods: ['GET'] - )] - public function __invoke(#[MapQueryString] Page $page): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetBookmarkList($securityUser->userId, $page)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkedArticleListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkedArticleListController.php deleted file mode 100644 index f88db52..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetBookmarkedArticleListController.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final class GetBookmarkedArticleListController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks/{bookmarkId}/articles', - name: 'feed_management_bookmarked_article_list', - requirements: [ - 'bookmarkId' => Requirement::UUID_V7, - ], - methods: ['GET'] - )] - public function __invoke(BookmarkId $bookmarkId, #[MapQueryString] Page $page): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetBookmarkedArticleList($securityUser->userId, $bookmarkId, $page)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceArticleOverviewListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceArticleOverviewListController.php deleted file mode 100644 index 6d1025f..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceArticleOverviewListController.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ -final class GetSourceArticleOverviewListController extends AbstractController -{ - #[Route( - path: 'api/feed/sources/{sourceId}/articles', - name: 'feed_management_source_article_list', - requirements: [ - 'sourceId' => Requirement::UUID_V7, - ], - methods: ['GET'] - )] - public function __invoke( - SourceId $sourceId, - #[MapQueryString] Page $page, - #[MapQueryString] ArticleFilters $filters - ): JsonResponse { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetSourceArticleOverviewList($sourceId, $securityUser->userId, $page, $filters)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceDetailsController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceDetailsController.php deleted file mode 100644 index 44215df..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceDetailsController.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class GetSourceDetailsController extends AbstractController -{ - #[Route( - path: '/api/feed/sources/{sourceId}', - name: 'feed_management_source_details', - requirements: [ - 'sourceId' => Requirement::UUID_V7, - ], - methods: ['GET'] - )] - public function __invoke(SourceId $sourceId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetSourceDetails($sourceId, $securityUser->userId)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceOverviewListController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceOverviewListController.php deleted file mode 100644 index 1d97e3f..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/GetSourceOverviewListController.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class GetSourceOverviewListController extends AbstractController -{ - #[Route( - path: '/api/feed/sources', - name: 'feed_management_source_overview_list', - methods: ['GET'] - )] - public function __invoke(#[MapQueryString] Page $page): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $data = $this->handleQuery(new GetSourceOverviewList($securityUser->userId, $page)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveArticleFromBookmarkController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveArticleFromBookmarkController.php deleted file mode 100644 index 81bf7aa..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveArticleFromBookmarkController.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final class RemoveArticleFromBookmarkController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks/{bookmarkId}/articles/{articleId}', - name: 'feed_management_remove_article_from_bookmark', - requirements: [ - 'bookmarkId' => Requirement::UUID_V7, - 'articleId' => Requirement::UUID_V7, - ], - methods: ['DELETE'] - )] - public function __invoke(BookmarkId $bookmarkId, ArticleId $articleId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new RemoveArticleFromBookmark($securityUser->userId, $articleId, $bookmarkId)); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveCommentFromArticleController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveCommentFromArticleController.php deleted file mode 100644 index 07ff9f0..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/RemoveCommentFromArticleController.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final class RemoveCommentFromArticleController extends AbstractController -{ - #[Route( - path: '/api/feed/articles/{articleId}/comments/{commentId}', - name: 'feed_management_remove_comment_from_article', - requirements: [ - 'articleId' => Requirement::UUID_V7, - 'commentId' => Requirement::UUID_V7, - ], - methods: ['DELETE'] - )] - public function __invoke(CommentId $commentId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new RemoveCommentFromArticle($securityUser->userId, $commentId)); - - return new JsonResponse(status: Response::HTTP_OK); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UnfollowSourceController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UnfollowSourceController.php deleted file mode 100644 index 8f6adec..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UnfollowSourceController.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class UnfollowSourceController extends AbstractController -{ - #[Route( - path: '/api/feed/sources/{sourceId}/unfollow', - name: 'feed_management_unfollow_source', - requirements: [ - 'sourceId' => Requirement::UUID_V7, - ], - methods: ['DELETE'] - )] - public function __invoke(SourceId $sourceId): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new UnfollowSource($sourceId, $securityUser->userId)); - - return new JsonResponse(status: Response::HTTP_OK); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UpdateBookmarkController.php b/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UpdateBookmarkController.php deleted file mode 100644 index fe141c0..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/Web/Controller/UpdateBookmarkController.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -final class UpdateBookmarkController extends AbstractController -{ - #[Route( - path: '/api/feed/bookmarks/{bookmarkId}', - name: 'feed_management_update_bookmark', - requirements: [ - 'bookmarkId' => Requirement::UUID_V7, - ], - methods: ['PUT'] - )] - public function __invoke(BookmarkId $bookmarkId, #[MapRequestPayload] UpdateBookmarkModel $model): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new UpdateBookmark( - $securityUser->userId, - $bookmarkId, - $model->name, - $model->description, - $model->isPublic - )); - - return new JsonResponse(status: Response::HTTP_CREATED); - } -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/AddCommentToArticleModel.php b/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/AddCommentToArticleModel.php deleted file mode 100644 index f064c61..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/AddCommentToArticleModel.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class AddCommentToArticleModel -{ - #[Assert\NotBlank] - #[Assert\Length(min: 5, max: 512)] - public string $content; -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/CreateBookmarkModel.php b/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/CreateBookmarkModel.php deleted file mode 100644 index b4efaaf..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/CreateBookmarkModel.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final class CreateBookmarkModel -{ - #[Assert\NotBlank] - #[Assert\Length(max: 255)] - public string $name; - - #[Assert\Length(max: 512)] - public ?string $description = null; - - public bool $isPublic = false; -} diff --git a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/UpdateBookmarkModel.php b/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/UpdateBookmarkModel.php deleted file mode 100644 index 08567f1..0000000 --- a/apps/api-legacy/src/FeedManagement/Presentation/WriteModel/UpdateBookmarkModel.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final class UpdateBookmarkModel -{ - #[Assert\NotBlank] - #[Assert\Length(max: 255)] - public string $name; - - #[Assert\Length(max: 512)] - public ?string $description = null; - - public bool $isPublic = false; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountConfirmedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountConfirmedListener.php deleted file mode 100644 index ca0e576..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountConfirmedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class AccountConfirmedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(AccountConfirmed $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new AccountConfirmedEmail($user->email, false, null); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountLockedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountLockedListener.php deleted file mode 100644 index d50d27c..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountLockedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class AccountLockedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(AccountLocked $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new AccountLockedEmail($user->email, $event->token); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountUnlockedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountUnlockedListener.php deleted file mode 100644 index 3b0a8a8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/AccountUnlockedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class AccountUnlockedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(AccountUnlocked $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new AccountUnlockedEmail($user->email); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/ConfirmationRequestedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/ConfirmationRequestedListener.php deleted file mode 100644 index 844ea7d..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/ConfirmationRequestedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class ConfirmationRequestedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(ConfirmationRequested $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new ConfirmationRequestedEmail($user->email, $user->name, $event->token); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/LoginProfileChangedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/LoginProfileChangedListener.php deleted file mode 100644 index ffd8352..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/LoginProfileChangedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class LoginProfileChangedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(LoginProfileChanged $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new LoginProfileChangedEmail($user->email, $event->device, $event->location); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordCreatedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordCreatedListener.php deleted file mode 100644 index b7cb997..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordCreatedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class PasswordCreatedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(PasswordCreated $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new PasswordCreatedEmail($user->email, $event->password); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordForgottenListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordForgottenListener.php deleted file mode 100644 index 7bb8261..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordForgottenListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class PasswordForgottenListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(PasswordForgotten $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new PasswordForgottenEmail($user->email, $event->token); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordResetListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordResetListener.php deleted file mode 100644 index 9e64b84..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordResetListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class PasswordResetListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(PasswordReset $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new PasswordResetEmail($user->email); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordUpdatedListener.php b/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordUpdatedListener.php deleted file mode 100644 index c90d2cf..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/EventListener/PasswordUpdatedListener.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class PasswordUpdatedListener implements EventListener -{ - public function __construct( - private Mailer $mailer, - private UserRepository $userRepository - ) { - } - - public function __invoke(PasswordUpdated $event): void - { - $user = $this->userRepository->getById($event->userId); - $email = new PasswordUpdatedEmail($user->email); - - $this->mailer->send($email); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountConfirmedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountConfirmedEmail.php deleted file mode 100644 index 065fb0e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountConfirmedEmail.php +++ /dev/null @@ -1,68 +0,0 @@ - - */ -final readonly class AccountConfirmedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private bool $isSocialLogin, - private ?string $socialLoginService - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.account_confirmed'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/account_confirmed'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'is_social_login' => $this->isSocialLogin, - 'social_login_service' => $this->socialLoginService, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountLockedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountLockedEmail.php deleted file mode 100644 index 58b3fc8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountLockedEmail.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final readonly class AccountLockedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private GeneratedToken $token - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.account_locked'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/account_locked'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'token' => $this->token, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountUnlockedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountUnlockedEmail.php deleted file mode 100644 index 397c3bc..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/AccountUnlockedEmail.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final readonly class AccountUnlockedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.account_unlocked'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/account_unlocked'; - } - - #[\Override] - public function templateVariables(): array - { - return []; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/ConfirmationRequestedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/ConfirmationRequestedEmail.php deleted file mode 100644 index c126dce..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/ConfirmationRequestedEmail.php +++ /dev/null @@ -1,69 +0,0 @@ - - */ -final readonly class ConfirmationRequestedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private string $name, - private GeneratedToken $token - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.user_registered'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/user_registered'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'name' => $this->name, - 'token' => $this->token, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/LoginProfileChangedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/LoginProfileChangedEmail.php deleted file mode 100644 index d61e169..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/LoginProfileChangedEmail.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -final readonly class LoginProfileChangedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private Device $device, - private GeoLocation $location - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.login_profile_changed'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/login_profile_changed'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'device' => $this->device, - 'location' => $this->location, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordCreatedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordCreatedEmail.php deleted file mode 100644 index 84697e1..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordCreatedEmail.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final readonly class PasswordCreatedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private GeneratedCode $code - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.password_created'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/password_created'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'code' => $this->code, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordForgottenEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordForgottenEmail.php deleted file mode 100644 index a0ca588..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordForgottenEmail.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -final readonly class PasswordForgottenEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - private GeneratedToken $token - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.password_forgotten'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/password_forgotten'; - } - - #[\Override] - public function templateVariables(): array - { - return [ - 'token' => $this->token, - ]; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordResetEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordResetEmail.php deleted file mode 100644 index 4ec5e0e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordResetEmail.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final readonly class PasswordResetEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient, - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.password_reset'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/password_reset'; - } - - #[\Override] - public function templateVariables(): array - { - return []; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordUpdatedEmail.php b/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordUpdatedEmail.php deleted file mode 100644 index 77d1c0f..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/Mailing/PasswordUpdatedEmail.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final readonly class PasswordUpdatedEmail implements EmailDefinition -{ - public function __construct( - private EmailAddress $recipient - ) { - } - - #[\Override] - public function recipient(): EmailAddress - { - return $this->recipient; - } - - #[\Override] - public function subject(): string - { - return 'identity_and_access.emails.subjects.password_updated'; - } - - #[\Override] - public function subjectVariables(): array - { - return []; - } - - #[\Override] - public function template(): string - { - return 'identity_and_access/password_updated'; - } - - #[\Override] - public function templateVariables(): array - { - return []; - } - - #[\Override] - public function locale(): string - { - return 'fr'; - } - - #[\Override] - public function getDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/ReadModel/UserProfile.php b/apps/api-legacy/src/IdentityAndAccess/Application/ReadModel/UserProfile.php deleted file mode 100644 index 07a795f..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/ReadModel/UserProfile.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final readonly class UserProfile -{ - public function __construct( - public UserId $id, - public string $name, - public EmailAddress $email, - public \DateTimeImmutable $createdAt, - public ?\DateTimeImmutable $updatedAt = null, - ) { - } - - public static function create(array $item): self - { - return new self( - UserId::fromString(DataMapping::string($item, 'user_id')), - DataMapping::string($item, 'user_name'), - EmailAddress::from(DataMapping::string($item, 'user_email')), - DataMapping::dateTime($item, 'user_created_at'), - DataMapping::nullableDateTime($item, 'user_updated_at'), - ); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ConfirmAccount.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ConfirmAccount.php deleted file mode 100644 index 243272d..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ConfirmAccount.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class ConfirmAccount -{ - public function __construct( - public GeneratedToken $token - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/LockAccount.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/LockAccount.php deleted file mode 100644 index 8e13510..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/LockAccount.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class LockAccount -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/Register.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/Register.php deleted file mode 100644 index 000d6e6..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/Register.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final readonly class Register -{ - public function __construct( - public string $name, - public EmailAddress $email, - public ?string $password, - public Roles $roles = new Roles() - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginAttempt.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginAttempt.php deleted file mode 100644 index 8b912c8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginAttempt.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class RegisterLoginAttempt -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginSuccess.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginSuccess.php deleted file mode 100644 index c269dd8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RegisterLoginSuccess.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class RegisterLoginSuccess -{ - public function __construct( - public UserId $userId, - public ClientProfile $profile - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RequestPassword.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RequestPassword.php deleted file mode 100644 index 66de9c9..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/RequestPassword.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class RequestPassword -{ - public function __construct( - public EmailAddress $email - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ResetPassword.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ResetPassword.php deleted file mode 100644 index cfc76c3..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/ResetPassword.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final readonly class ResetPassword -{ - public function __construct( - public GeneratedToken $token, - public string $password - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UnlockAccount.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UnlockAccount.php deleted file mode 100644 index 5e093e7..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UnlockAccount.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class UnlockAccount -{ - public function __construct( - public GeneratedToken $token, - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UpdatePassword.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UpdatePassword.php deleted file mode 100644 index ca5b444..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Command/UpdatePassword.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class UpdatePassword -{ - public function __construct( - public UserId $userId, - public string $current, - public string $password, - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ConfirmAccountHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ConfirmAccountHandler.php deleted file mode 100644 index 8e2fde8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ConfirmAccountHandler.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final readonly class ConfirmAccountHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(ConfirmAccount $command): void - { - $token = $this->verificationTokenRepository->getByToken( - $command->token, - TokenPurpose::CONFIRM_ACCOUNT - ); - - $user = $this->userRepository->getById($token->user->id); - $user->confirmAccount(); - - $this->verificationTokenRepository->remove($token); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/LockAccountHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/LockAccountHandler.php deleted file mode 100644 index 3d7dcb6..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/LockAccountHandler.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final readonly class LockAccountHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private SecretGenerator $secretGenerator, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(LockAccount $command): void - { - $user = $this->userRepository->getById($command->userId); - $token = $this->createVerificationToken($user); - $user->lockAccount($token); - - $this->userRepository->add($user); - $this->verificationTokenRepository->add($token); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } - - private function createVerificationToken(User $user): VerificationToken - { - $secret = $this->secretGenerator->generateToken(); - return VerificationToken::create($user, $secret, TokenPurpose::UNLOCK_ACCOUNT); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterHandler.php deleted file mode 100644 index 7888296..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterHandler.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -final readonly class RegisterHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private PasswordHasher $passwordHasher, - private SecretGenerator $secretGenerator, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(Register $command): void - { - $user = $this->userRepository->getByEmail($command->email); - if ($user instanceof User) { - throw EmailAlreadyUsed::with($command->email); - } - - $user = User::register($command->name, $command->email, $command->roles); - $password = $command->password ?? $this->secretGenerator->generateCode(); - $token = $this->createVerificationToken($user); - - $user - ->definePassword($password, $this->passwordHasher) - ->requestAccountConfirmation($token); - - $this->userRepository->add($user); - $this->verificationTokenRepository->add($token); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } - - private function createVerificationToken(User $user): VerificationToken - { - $secret = $this->secretGenerator->generateToken(); - return VerificationToken::create($user, $secret, TokenPurpose::CONFIRM_ACCOUNT); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginAttemptHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginAttemptHandler.php deleted file mode 100644 index 6c4bcf9..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginAttemptHandler.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ -final readonly class RegisterLoginAttemptHandler implements CommandHandler -{ - private const int ATTEMPTS_LIMIT = 3; - - public function __construct( - private UserRepository $userRepository, - private LoginAttemptRepository $loginAttemptRepository, - private CommandBus $commandBus - ) { - } - - public function __invoke(RegisterLoginAttempt $command): void - { - $user = $this->userRepository->getById($command->userId); - $attempts = $this->loginAttemptRepository->countBy($user); - - if ($attempts < self::ATTEMPTS_LIMIT) { - $this->loginAttemptRepository->add(LoginAttempt::create($user)); - } elseif ($user->isLocked === false) { - $this->commandBus->handle(new LockAccount($user->id)); - } - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginSuccessHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginSuccessHandler.php deleted file mode 100644 index 61122bb..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RegisterLoginSuccessHandler.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final readonly class RegisterLoginSuccessHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private LoginHistoryRepository $loginHistoryRepository, - private LoginAttemptRepository $loginAttemptRepository, - private ClientProfiler $clientProfiler, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(RegisterLoginSuccess $command): void - { - $user = $this->userRepository->getById($command->userId); - $device = $this->clientProfiler->detect($command->profile); - $location = $this->clientProfiler->locate($command->profile); - - $current = LoginHistory::create($user, $command->profile->userIp, $device, $location); - $previous = $this->loginHistoryRepository->getLastBy($user); - if ($previous instanceof LoginHistory) { - $current->matchPreviousProfile($previous); - } - - $this->loginHistoryRepository->add($current); - $this->loginAttemptRepository->deleteBy($user); - $this->eventDispatcher->dispatch($current->releaseEvents()); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RequestPasswordHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RequestPasswordHandler.php deleted file mode 100644 index 302e641..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/RequestPasswordHandler.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ -final readonly class RequestPasswordHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private SecretGenerator $secretGenerator, - private EventDispatcher $eventDispatcher, - ) { - } - - public function __invoke(RequestPassword $command): void - { - $user = $this->userRepository->getByEmail($command->email); - if (! $user instanceof User) { - throw UserNotFound::withEmail($command->email); - } - - $token = $this->createVerificationToken($user); - $user->requestPasswordReset($token); - - $this->userRepository->add($user); - $this->verificationTokenRepository->add($token); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } - - private function createVerificationToken(User $user): VerificationToken - { - $secret = $this->secretGenerator->generateToken(); - return VerificationToken::create($user, $secret, TokenPurpose::PASSWORD_RESET); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ResetPasswordHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ResetPasswordHandler.php deleted file mode 100644 index fec3ad0..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/ResetPasswordHandler.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ -final readonly class ResetPasswordHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private PasswordHasher $passwordHasher, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(ResetPassword $command): void - { - $token = $this->verificationTokenRepository->getByToken( - $command->token, - TokenPurpose::PASSWORD_RESET - ); - - $user = $this->userRepository->getById($token->user->id); - $user->resetPassword($command->password, $this->passwordHasher); - - $this->userRepository->add($user); - $this->verificationTokenRepository->remove($token); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UnlockAccountHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UnlockAccountHandler.php deleted file mode 100644 index 5913c02..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UnlockAccountHandler.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -final readonly class UnlockAccountHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private VerificationTokenRepository $verificationTokenRepository, - private LoginAttemptRepository $loginAttemptRepository, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(UnlockAccount $command): void - { - $token = $this->verificationTokenRepository->getByToken( - $command->token, - TokenPurpose::UNLOCK_ACCOUNT - ); - - $user = $this->userRepository->getById($token->user->id); - $user->unlockAccount(); - - $this->userRepository->add($user); - $this->verificationTokenRepository->remove($token); - $this->loginAttemptRepository->deleteBy($user); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UpdatePasswordHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UpdatePasswordHandler.php deleted file mode 100644 index b985c92..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/CommandHandler/UpdatePasswordHandler.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -final readonly class UpdatePasswordHandler implements CommandHandler -{ - public function __construct( - private UserRepository $userRepository, - private PasswordHasher $passwordHasher, - private EventDispatcher $eventDispatcher - ) { - } - - public function __invoke(UpdatePassword $command): void - { - $user = $this->userRepository->getById($command->userId); - $user->updatePassword($command->current, $command->password, $this->passwordHasher); - - $this->userRepository->add($user); - $this->eventDispatcher->dispatch($user->releaseEvents()); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Query/GetUserProfile.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Query/GetUserProfile.php deleted file mode 100644 index adaec3b..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/Query/GetUserProfile.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class GetUserProfile -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/QueryHandler/GetUserProfileHandler.php b/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/QueryHandler/GetUserProfileHandler.php deleted file mode 100644 index d9ba2f9..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Application/UseCase/QueryHandler/GetUserProfileHandler.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface GetUserProfileHandler extends QueryHandler -{ - public function __invoke(GetUserProfile $query): UserProfile; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountConfirmed.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountConfirmed.php deleted file mode 100644 index 67cfc2d..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountConfirmed.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class AccountConfirmed -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountLocked.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountLocked.php deleted file mode 100644 index 0ba4c26..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountLocked.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class AccountLocked -{ - public function __construct( - public UserId $userId, - public GeneratedToken $token - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountUnlocked.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountUnlocked.php deleted file mode 100644 index f64bb80..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/AccountUnlocked.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class AccountUnlocked -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/ConfirmationRequested.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/ConfirmationRequested.php deleted file mode 100644 index 145bfba..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/ConfirmationRequested.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class ConfirmationRequested -{ - public function __construct( - public UserId $userId, - public GeneratedToken $token - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/EmailUpdated.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/EmailUpdated.php deleted file mode 100644 index 3d51d35..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/EmailUpdated.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final readonly class EmailUpdated -{ - public function __construct( - public UserId $userId, - public EmailAddress $previous, - public EmailAddress $current - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/LoginProfileChanged.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/LoginProfileChanged.php deleted file mode 100644 index fc85cc9..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/LoginProfileChanged.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final readonly class LoginProfileChanged -{ - public function __construct( - public UserId $userId, - public Device $device, - public GeoLocation $location - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordCreated.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordCreated.php deleted file mode 100644 index 644f878..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordCreated.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class PasswordCreated -{ - public function __construct( - public UserId $userId, - #[\SensitiveParameter] public GeneratedCode $password - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordForgotten.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordForgotten.php deleted file mode 100644 index db687d4..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordForgotten.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final readonly class PasswordForgotten -{ - public function __construct( - public UserId $userId, - public GeneratedToken $token, - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordReset.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordReset.php deleted file mode 100644 index baeace9..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordReset.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class PasswordReset -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordUpdated.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordUpdated.php deleted file mode 100644 index b98f949..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Event/PasswordUpdated.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class PasswordUpdated -{ - public function __construct( - public UserId $userId - ) { - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountIsLocked.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountIsLocked.php deleted file mode 100644 index c797c3c..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountIsLocked.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class AccountIsLocked extends \DomainException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.account_is_locked'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountNotConfirmed.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountNotConfirmed.php deleted file mode 100644 index 0786eb7..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/AccountNotConfirmed.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class AccountNotConfirmed extends \DomainException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.account_not_confirmed'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/EmailAlreadyUsed.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/EmailAlreadyUsed.php deleted file mode 100644 index aaeb448..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/EmailAlreadyUsed.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -final class EmailAlreadyUsed extends \DomainException implements UserFacingError -{ - public static function with(EmailAddress $email): self - { - return new self(sprintf('the %s email is already used by another user', $email->value)); - } - - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.email_already_used'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidCurrentPassword.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidCurrentPassword.php deleted file mode 100644 index 5093277..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidCurrentPassword.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class InvalidCurrentPassword extends \DomainException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.invalid_current_password'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidVerificationToken.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidVerificationToken.php deleted file mode 100644 index f5bf110..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/InvalidVerificationToken.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class InvalidVerificationToken extends \DomainException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.invalid_verification_token'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PasswordAlreadyDefined.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PasswordAlreadyDefined.php deleted file mode 100644 index 58b13b5..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PasswordAlreadyDefined.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class PasswordAlreadyDefined extends \DomainException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.password_already_defined'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PermissionNotGranted.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PermissionNotGranted.php deleted file mode 100644 index c6f93f2..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/PermissionNotGranted.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class PermissionNotGranted extends \DomainException implements UserFacingError -{ - public static function withReason(string $message): self - { - return new self($message); - } - - public function translationId(): string - { - return 'identity_and_access.exceptions.permission_not_granted'; - } - - public function translationParameters(): array - { - return [ - '{reason}' => $this->message, - ]; - } - - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/UserNotFound.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/UserNotFound.php deleted file mode 100644 index f7e1323..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Exception/UserNotFound.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -final class UserNotFound extends \DomainException implements UserFacingError -{ - public static function withEmail(EmailAddress $email): self - { - return new self(\sprintf('User with email %s was not found', $email->value)); - } - - public static function withId(UserId $userId): self - { - return new self(\sprintf('User with id %s was not found', $userId->toString())); - } - - #[\Override] - public function translationId(): string - { - return 'identity_and_access.exceptions.user_not_found'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'identity_and_access'; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginAttempt.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginAttempt.php deleted file mode 100644 index 061f122..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginAttempt.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -readonly class LoginAttempt -{ - public LoginAttemptId $id; - - private function __construct( - public User $user, - public \DateTimeImmutable $createdAt = new \DateTimeImmutable() - ) { - $this->id = new LoginAttemptId(); - } - - public static function create(User $user): self - { - return new self($user); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginHistory.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginHistory.php deleted file mode 100644 index 0ee8789..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/LoginHistory.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -class LoginHistory -{ - use EventEmitterTrait; - - public readonly LoginHistoryId $id; - - private function __construct( - public readonly User $user, - public readonly ?string $ipAddress, - public readonly Device $device, - public readonly GeoLocation $location, - public readonly \DateTimeImmutable $createdAt = new \DateTimeImmutable() - ) { - $this->id = new LoginHistoryId(); - } - - public static function create(User $user, ?string $userIp, Device $device, GeoLocation $location): self - { - return new self($user, $userIp, $device, $location); - } - - public function matchPreviousProfile(self $previous): self - { - if ( - $this->ipAddress !== $previous->ipAddress || - $this->location->city !== $previous->location->city || - $this->location->country !== $previous->location->country || - $this->device->operatingSystem !== $previous->device->operatingSystem - ) { - $this->emitEvent(new LoginProfileChanged($this->user->id, $this->device, $this->location)); - } - - return $this; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/RefreshToken.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/RefreshToken.php deleted file mode 100644 index 373351c..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/RefreshToken.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -class User -{ - use EventEmitterTrait; - - public readonly UserId $id; - - public function __construct( - private(set) string $name, - private(set) EmailAddress $email, - private(set) Roles $roles, - private(set) ?string $password = null, - private(set) bool $isLocked = false, - private(set) bool $isConfirmed = false, - private(set) ?\DateTimeImmutable $updatedAt = null, - public readonly ?\DateTimeImmutable $createdAt = new \DateTimeImmutable(), - ) { - $this->id = new UserId(); - } - - public function lockAccount(VerificationToken $verificationToken): self - { - $this->isLocked = true; - $this->emitEvent(new AccountLocked($this->id, $verificationToken->token)); - - return $this; - } - - public function unlockAccount(): self - { - $this->isLocked = false; - $this->emitEvent(new AccountUnlocked($this->id)); - - return $this; - } - - public function confirmAccount(): self - { - $this->isConfirmed = true; - $this->emitEvent(new AccountConfirmed($this->id)); - - return $this; - } - - public static function register(string $name, EmailAddress $email, ?Roles $roles): self - { - return new self($name, $email, $roles ?? Roles::user()); - } - - public function updateProfile(string $name, Roles $roles): static - { - $this->name = $name; - $this->roles = $roles; - $this->updatedAt = new \DateTimeImmutable(); - - return $this; - } - - public function updateEmail(EmailAddress $email): self - { - $previous = $this->email; - $this->email = $email; - $this->emitEvent(new EmailUpdated($this->id, $previous, $email)); - - return $this; - } - - public function resetPassword(string $password, PasswordHasher $passwordHasher): void - { - $this->password = $passwordHasher->hash($this, $password); - $this->emitEvent(new PasswordReset($this->id)); - } - - public function updatePassword(string $current, string $new, PasswordHasher $passwordHasher): self - { - if ($this->password === null || ! $passwordHasher->verify($this, $current)) { - throw new InvalidCurrentPassword(); - } - - $this->password = $passwordHasher->hash($this, $new); - $this->emitEvent(new PasswordUpdated($this->id)); - - return $this; - } - - public function definePassword(GeneratedCode|string $password, PasswordHasher $passwordHasher): self - { - if ($this->password !== null) { - throw new PasswordAlreadyDefined(); - } - - $this->password = $passwordHasher->hash($this, (string) $password); - $this->updatedAt = new \DateTimeImmutable(); - - if ($password instanceof GeneratedCode) { - $this->emitEvent(new PasswordCreated($this->id, $password)); - } - - return $this; - } - - public function requestPasswordReset(VerificationToken $verificationToken): self - { - $this->emitEvent(new PasswordForgotten($this->id, $verificationToken->token)); - - return $this; - } - - public function requestAccountConfirmation(VerificationToken $verificationToken): self - { - $this->emitEvent(new ConfirmationRequested($this->id, $verificationToken->token)); - - return $this; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/VerificationToken.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/VerificationToken.php deleted file mode 100644 index 277f2e1..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Entity/VerificationToken.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -readonly class VerificationToken -{ - public const string DEFAULT_VALIDITY = 'PT2H'; - - public VerificationTokenId $id; - - public function __construct( - public User $user, - public GeneratedToken $token, - public TokenPurpose $purpose, - public \DateTimeImmutable $createdAt = new \DateTimeImmutable() - ) { - $this->id = new VerificationTokenId(); - } - - public static function create(User $user, GeneratedToken $token, TokenPurpose $purpose): self - { - return new self($user, $token, $purpose); - } - - public function isExpired(): bool - { - $now = new \DateTimeImmutable(); - $validUntil = (\DateTime::createFromImmutable($this->createdAt)) - ->add(new \DateInterval(self::DEFAULT_VALIDITY)); - - return $now > $validUntil; - } - - public function assertValid(): void - { - if ($this->isExpired()) { - throw new InvalidVerificationToken(); - } - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginAttemptId.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginAttemptId.php deleted file mode 100644 index 1a215c7..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginAttemptId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class LoginAttemptId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginHistoryId.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginHistoryId.php deleted file mode 100644 index 4c530cc..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/LoginHistoryId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class LoginHistoryId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/UserId.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/UserId.php deleted file mode 100644 index 14c4d1e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/UserId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class UserId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/VerificationTokenId.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/VerificationTokenId.php deleted file mode 100644 index 8a02c3b..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Identity/VerificationTokenId.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class VerificationTokenId extends UuidV7 -{ -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginAttemptRepository.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginAttemptRepository.php deleted file mode 100644 index ea5d666..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginAttemptRepository.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -interface LoginAttemptRepository -{ - public function add(LoginAttempt $loginAttempt): void; - - public function remove(LoginAttempt $loginAttempt): void; - - public function countBy(User $user): int; - - public function deleteBy(User $user): void; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginHistoryRepository.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginHistoryRepository.php deleted file mode 100644 index 68ad1ca..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/LoginHistoryRepository.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface LoginHistoryRepository -{ - public function add(LoginHistory $loginHistory): void; - - public function remove(LoginHistory $loginHistory): void; - - public function getLastBy(User $user): ?LoginHistory; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/UserRepository.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/UserRepository.php deleted file mode 100644 index 9387197..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/UserRepository.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ -interface UserRepository -{ - public function add(User $user): void; - - public function remove(User $user): void; - - public function getById(UserId $userId): User; - - public function getByEmail(EmailAddress $email): ?User; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/VerificationTokenRepository.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/VerificationTokenRepository.php deleted file mode 100644 index 9f63d5c..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/Repository/VerificationTokenRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -interface VerificationTokenRepository -{ - public function add(VerificationToken $verificationToken): void; - - public function remove(VerificationToken $verificationToken): void; - - public function getByToken(GeneratedToken $token, TokenPurpose $purpose): VerificationToken; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Role.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Role.php deleted file mode 100644 index 067dc12..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Role.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -enum Role: string -{ - case USER = 'ROLE_USER'; - case ADMIN = 'ROLE_ADMIN'; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Roles.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Roles.php deleted file mode 100644 index 7c1232a..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Roles.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ -readonly class Roles implements \Stringable -{ - private array $roles; - - public function __construct(array $roles = [Role::USER]) - { - Assert::notEmpty($roles, 'identity_and_access.validations.empty_roles'); - Assert::allIsInstanceOf($roles, Role::class); - - $roles[] = Role::USER; - $this->roles = array_unique(\array_map(fn (Role $role) => $role->value, $roles)); - } - - #[\Override] - public function __toString(): string - { - return implode(',', $this->roles); - } - - public static function admin(): self - { - return new self([Role::USER, Role::ADMIN]); - } - - public static function user(): self - { - return new self(); - } - - public function toArray(): array - { - return $this->roles; - } - - public static function fromArray(array $roles): self - { - return new self($roles); - } - - public function contains(string $role): bool - { - return in_array($role, $this->roles, true); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedCode.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedCode.php deleted file mode 100644 index 3bd6b2e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedCode.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -final readonly class GeneratedCode implements \Stringable -{ - public function __construct( - public string $code - ) { - Assert::notEmpty($this->code); - } - - #[\Override] - public function __toString(): string - { - return $this->code; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedToken.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedToken.php deleted file mode 100644 index 28fbc81..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/Secret/GeneratedToken.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -final readonly class GeneratedToken implements \Stringable -{ - public function __construct( - public string $token, - ) { - Assert::notEmpty($this->token); - } - - #[\Override] - public function __toString(): string - { - return $this->token; - } - - public function isEqualTo(self $token): bool - { - return $this->token === $token->token; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/TokenPurpose.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/TokenPurpose.php deleted file mode 100644 index 8695407..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Model/ValueObject/TokenPurpose.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -enum TokenPurpose: string -{ - case CONFIRM_ACCOUNT = 'confirm_account'; - case PASSWORD_RESET = 'password_reset'; - case UNLOCK_ACCOUNT = 'unlock_account'; - case DELETE_ACCOUNT = 'delete_account'; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Service/PasswordHasher.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Service/PasswordHasher.php deleted file mode 100644 index 4593a12..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Service/PasswordHasher.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface PasswordHasher -{ - public function hash(User $user, string $password): string; - - public function verify(User $user, string $password): bool; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Domain/Service/SecretGenerator.php b/apps/api-legacy/src/IdentityAndAccess/Domain/Service/SecretGenerator.php deleted file mode 100644 index ba00fb7..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Domain/Service/SecretGenerator.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -interface SecretGenerator -{ - public function generateToken(int $length = 60): GeneratedToken; - - public function generateCode(int $length = 6): GeneratedCode; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginFailureListener.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginFailureListener.php deleted file mode 100644 index 4cd707f..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginFailureListener.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -#[AsEventListener(LoginFailureEvent::class)] -final readonly class LoginFailureListener -{ - public function __construct( - private CommandBus $commandBus - ) { - } - - public function __invoke(LoginFailureEvent $event): void - { - /** @var SecurityUser|null $user */ - $user = $event->getPassport()?->getUser(); - - if ($user && $event->getException() instanceof BadCredentialsException) { - $this->commandBus->handle(new RegisterLoginAttempt($user->userId)); - } - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginSuccessListener.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginSuccessListener.php deleted file mode 100644 index 6028a07..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/EventListener/LoginSuccessListener.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -#[AsEventListener(InteractiveLoginEvent::class)] -final readonly class LoginSuccessListener -{ - public function __construct( - private CommandBus $commandBus, - ) { - } - - public function __invoke(InteractiveLoginEvent $event): void - { - /** @var SecurityUser|null $user */ - $user = $event->getAuthenticationToken()->getUser(); - - if ($user !== null) { - $profile = new ClientProfile( - IpUtils::anonymize((string) $event->getRequest()->getClientIp(), 1), - $event->getRequest()->headers->get('User-Agent'), - $event->getRequest()->server->all() - ); - - $this->commandBus->handle(new RegisterLoginSuccess($user->userId, $profile)); - } - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUser.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUser.php deleted file mode 100644 index 854e7bd..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUser.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ -final readonly class SecurityUser implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface -{ - public function __construct( - public UserId $userId, - public EmailAddress $email, - public ?string $password, - public array $roles, - public bool $isLocked, - public bool $isConfirmed - ) { - } - - public static function create(User $user): self - { - return new self( - $user->id, - $user->email, - (string) $user->password, - $user->roles->toArray(), - $user->isLocked, - $user->isConfirmed - ); - } - - #[\Override] - public function getPassword(): ?string - { - return $this->password; - } - - #[\Override] - public function getRoles(): array - { - return $this->roles; - } - - #[\Override] - public function eraseCredentials(): void - { - } - - #[\Override] - public function getUserIdentifier(): string - { - /** @var non-empty-string $email */ - $email = $this->email->value; - - return $email; - } - - #[\Override] - public function isEqualTo(UserInterface $user): bool - { - if (! $user instanceof self) { - return false; - } - - return $this->userId->equals($user->userId); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUserProvider.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUserProvider.php deleted file mode 100644 index 53ad895..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/SecurityUserProvider.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * @author bernard-ng - */ -final readonly class SecurityUserProvider implements UserProviderInterface -{ - public function __construct( - private UserRepository $userRepository, - ) { - } - - #[\Override] - public function refreshUser(UserInterface $user): UserInterface - { - return $this->loadUserByIdentifier($user->getUserIdentifier()); - } - - #[\Override] - public function loadUserByIdentifier(string $identifier): UserInterface - { - $user = $this->userRepository->getByEmail(EmailAddress::from($identifier)); - if (! $user instanceof User) { - throw new UserNotFoundException(); - } - - return SecurityUser::create($user); - } - - #[\Override] - public function supportsClass(string $class): bool - { - return $class === SecurityUser::class; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserChecker.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserChecker.php deleted file mode 100644 index a2cc2c5..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserChecker.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -final readonly class UserChecker implements UserCheckerInterface -{ - #[\Override] - public function checkPreAuth(UserInterface $user): void - { - if ($user instanceof SecurityUser && $user->isLocked) { - throw new AccountIsLocked(); - } - } - - #[\Override] - public function checkPostAuth(UserInterface $user): void - { - if ($user instanceof SecurityUser && $user->isConfirmed === false) { - throw new AccountNotConfirmed(); - } - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserPasswordHasher.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserPasswordHasher.php deleted file mode 100644 index a068150..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Framework/Symfony/Security/UserPasswordHasher.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final readonly class UserPasswordHasher implements PasswordHasher -{ - public function __construct( - private UserPasswordHasherInterface $passwordHasher - ) { - } - - #[\Override] - public function hash(User $user, string $password): string - { - $securityUser = SecurityUser::create($user); - return $this->passwordHasher->hashPassword($securityUser, $password); - } - - #[\Override] - public function verify(User $user, string $password): bool - { - $securityUser = SecurityUser::create($user); - return $this->passwordHasher->isPasswordValid($securityUser, $password); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/GetUserProfileDbalHandler.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/GetUserProfileDbalHandler.php deleted file mode 100644 index 4478e1b..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/GetUserProfileDbalHandler.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final readonly class GetUserProfileDbalHandler implements GetUserProfileHandler -{ - public function __construct( - private Connection $connection - ) { - } - - public function __invoke(GetUserProfile $query): UserProfile - { - $qb = $this->connection->createQueryBuilder() - ->select( - 'u.id as user_id', - 'u.name as user_name', - 'u.email as user_email', - 'u.created_at as user_created_at', - 'u.updated_at as user_updated_at' - ) - ->from('user', 'u') - ->where('u.id = :userId') - ->setParameter('userId', $query->userId->toString()); - - /** @var array|false $data */ - $data = $qb->executeQuery()->fetchAssociative(); - - if ($data === false) { - throw UserNotFound::withId($query->userId); - } - - return UserProfile::create($data); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginAttemptIdType.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginAttemptIdType.php deleted file mode 100644 index c890c0d..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginAttemptIdType.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class LoginAttemptIdType extends AbstractUidType -{ - #[\Override] - public function getName(): string - { - return 'login_attempt_id'; - } - - #[\Override] - protected function getUidClass(): string - { - return LoginAttemptId::class; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginHistoryIdType.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginHistoryIdType.php deleted file mode 100644 index aca2a9d..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/LoginHistoryIdType.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class LoginHistoryIdType extends AbstractUidType -{ - #[\Override] - public function getName(): string - { - return 'login_history_id'; - } - - #[\Override] - protected function getUidClass(): string - { - return LoginHistoryId::class; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/UserIdType.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/UserIdType.php deleted file mode 100644 index 5db2732..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/UserIdType.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class UserIdType extends AbstractUidType -{ - #[\Override] - public function getName(): string - { - return 'user_id'; - } - - #[\Override] - protected function getUidClass(): string - { - return UserId::class; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/VerificationTokenIdType.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/VerificationTokenIdType.php deleted file mode 100644 index 18df09e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/DBAL/Types/VerificationTokenIdType.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class VerificationTokenIdType extends AbstractUidType -{ - #[\Override] - public function getName(): string - { - return 'verification_token_id'; - } - - #[\Override] - protected function getUidClass(): string - { - return VerificationTokenId::class; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginAttemptOrmRepository.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginAttemptOrmRepository.php deleted file mode 100644 index f22da34..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginAttemptOrmRepository.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * @author bernard-ng - */ -final class LoginAttemptOrmRepository extends ServiceEntityRepository implements LoginAttemptRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, LoginAttempt::class); - } - - #[\Override] - public function add(LoginAttempt $loginAttempt): void - { - $this->getEntityManager()->persist($loginAttempt); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function remove(LoginAttempt $loginAttempt): void - { - $this->getEntityManager()->remove($loginAttempt); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function countBy(User $user): int - { - return $this->count([ - 'user' => $user, - ]); - } - - #[\Override] - public function deleteBy(User $user): void - { - $this->createQueryBuilder('la') - ->delete(LoginAttempt::class, 'la') - ->where('la.user = :user') - ->setParameter('user', $user) - ->getQuery() - ->execute(); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginHistoryOrmRepository.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginHistoryOrmRepository.php deleted file mode 100644 index d1a5cc7..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/LoginHistoryOrmRepository.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * @author bernard-ng - */ -final class LoginHistoryOrmRepository extends ServiceEntityRepository implements LoginHistoryRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, LoginHistory::class); - } - - #[\Override] - public function add(LoginHistory $loginHistory): void - { - $this->getEntityManager()->persist($loginHistory); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function remove(LoginHistory $loginHistory): void - { - $this->getEntityManager()->remove($loginHistory); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function getLastBy(User $user): ?LoginHistory - { - /** @var LoginHistory|null $loginHistory */ - $loginHistory = $this->createQueryBuilder('lh') - ->andWhere('lh.user = :user') - ->setParameter('user', $user) - ->orderBy('lh.createdAt', 'DESC') - ->setMaxResults(1) - ->getQuery() - ->getOneOrNullResult(); - - return $loginHistory; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/UserOrmRepository.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/UserOrmRepository.php deleted file mode 100644 index 0196f00..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/UserOrmRepository.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * @author bernard-ng - */ -final class UserOrmRepository extends ServiceEntityRepository implements UserRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, User::class); - } - - #[\Override] - public function add(User $user): void - { - $this->getEntityManager()->persist($user); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function remove(User $user): void - { - $this->getEntityManager()->remove($user); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function getById(UserId $userId): User - { - $user = $this->findOneBy([ - 'id' => $userId, - ]); - - if ($user === null) { - throw UserNotFound::withId($userId); - } - - return $user; - } - - #[\Override] - public function getByEmail(EmailAddress $email): ?User - { - return $this->findOneBy([ - 'email' => $email, - ]); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/VerificationTokenOrmRepository.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/VerificationTokenOrmRepository.php deleted file mode 100644 index e35bc45..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Persistence/Doctrine/ORM/VerificationTokenOrmRepository.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * @author bernard-ng - */ -final class VerificationTokenOrmRepository extends ServiceEntityRepository implements VerificationTokenRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, VerificationToken::class); - } - - #[\Override] - public function add(VerificationToken $verificationToken): void - { - $this->getEntityManager()->persist($verificationToken); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function remove(VerificationToken $verificationToken): void - { - $this->getEntityManager()->remove($verificationToken); - $this->getEntityManager()->flush(); - } - - #[\Override] - public function getByToken(GeneratedToken $token, TokenPurpose $purpose): VerificationToken - { - $token = $this->findOneBy([ - 'token.token' => $token->token, - 'purpose' => $purpose->value, - ]); - - if ($token === null) { - throw new InvalidVerificationToken(); - } - - return $token; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Secret/RandomizerSecretGenerator.php b/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Secret/RandomizerSecretGenerator.php deleted file mode 100644 index 5d798ce..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Infrastructure/Secret/RandomizerSecretGenerator.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final readonly class RandomizerSecretGenerator implements SecretGenerator -{ - private const string ALLOWED_CHARACTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - #[\Override] - public function generateToken(int $length = 60): GeneratedToken - { - $value = new Randomizer() - ->getBytesFromString(self::ALLOWED_CHARACTERS, $length); - - return new GeneratedToken($value); - } - - #[\Override] - public function generateCode(int $length = 6): GeneratedCode - { - $min = 10 ** ($length - 1); - $max = 10 ** $length - 1; - - $value = new Randomizer() - ->getInt($min, $max); - - return new GeneratedCode((string) $value); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Console/RegisterConsole.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Console/RegisterConsole.php deleted file mode 100644 index cf2ccbd..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Console/RegisterConsole.php +++ /dev/null @@ -1,92 +0,0 @@ - - */ -#[AsCommand('app:user-register', 'register a new user')] -final class RegisterConsole extends Command -{ - use AskArgumentFeature; - - private SymfonyStyle $io; - - public function __construct( - private readonly CommandBus $commandBus, - ) { - parent::__construct(); - } - - #[\Override] - protected function configure(): void - { - $this - ->setDescription('Creates users and stores them in the database') - ->addArgument('name', InputArgument::OPTIONAL, 'The name of the new user') - ->addArgument('email', InputArgument::OPTIONAL, 'The email of the new user') - ->addArgument('password', InputArgument::OPTIONAL, 'The plain password of the new user') - ->addOption('admin', null, InputOption::VALUE_NONE, 'If set, the user is created as an administrator'); - } - - #[\Override] - protected function initialize(InputInterface $input, OutputInterface $output): void - { - $this->io = new SymfonyStyle($input, $output); - } - - #[\Override] - protected function interact(InputInterface $input, OutputInterface $output): void - { - if ( - $input->getArgument('name') !== null && - $input->getArgument('email') !== null && - $input->getArgument('password') !== null - ) { - return; - } - - $this->askArgument($input, 'name'); - $this->askArgument($input, 'email'); - $this->askArgument($input, 'password', true); - } - - #[\Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var string $name */ - $name = $input->getArgument('name'); - - /** @var string $email */ - $email = $input->getArgument('email'); - - /** @var string $password */ - $password = $input->getArgument('password'); - - /** @var bool $admin */ - $admin = $input->getOption('admin'); - - $command = new Register($name, EmailAddress::from($email), $password, $admin ? Roles::admin() : Roles::user()); - $this->commandBus->handle($command); - $this->io->success(\sprintf('%s was created: %s', $admin ? 'ADMIN' : 'USER', $email)); - - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ConfirmAccountController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ConfirmAccountController.php deleted file mode 100644 index 3a6d209..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ConfirmAccountController.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class ConfirmAccountController extends AbstractController -{ - #[Route( - path: '/api/account/confirm/{token}', - name: 'identity_and_access_confirm_account', - requirements: [ - 'token' => Requirement::ASCII_SLUG, - ], - methods: ['GET'] - )] - public function __invoke(string $token): JsonResponse - { - $token = new GeneratedToken($token); - $this->handleCommand(new ConfirmAccount($token)); - - return new JsonResponse(status: 200); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/GetUserProfileController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/GetUserProfileController.php deleted file mode 100644 index c95d2db..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/GetUserProfileController.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final class GetUserProfileController extends AbstractController -{ - #[Route( - path: '/api/me', - name: 'identity_and_access_me', - methods: ['GET'] - )] - public function __invoke(): JsonResponse - { - $security = $this->getSecurityUser(); - $data = $this->handleQuery(new GetUserProfile($security->userId)); - - return JsonResponse::fromJsonString($this->serialize($data)); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RegisterController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RegisterController.php deleted file mode 100644 index 8f05ac8..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RegisterController.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class RegisterController extends AbstractController -{ - #[Route( - path: '/api/register', - name: 'identity_and_access_register', - methods: ['POST'] - )] - public function __invoke(#[MapRequestPayload] RegisterModel $model): JsonResponse - { - $this->handleCommand(new Register( - $model->name, - EmailAddress::from($model->email), - $model->password - )); - - return new JsonResponse(status: 201); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RequestPasswordController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RequestPasswordController.php deleted file mode 100644 index ca87294..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/RequestPasswordController.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -final class RequestPasswordController extends AbstractController -{ - #[Route( - path: '/api/password/request', - name: 'identity_and_access_request_password', - methods: ['POST'] - )] - public function __invoke(#[MapRequestPayload] RequestPasswordModel $model): JsonResponse - { - $email = EmailAddress::from($model->email); - $this->handleCommand(new RequestPassword($email)); - - return new JsonResponse(status: 200); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ResetPasswordController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ResetPasswordController.php deleted file mode 100644 index 2de345e..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/ResetPasswordController.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -final class ResetPasswordController extends AbstractController -{ - #[Route( - path: '/api/password/reset/{token}', - name: 'identity_and_access_reset_password', - requirements: [ - 'token' => Requirement::ASCII_SLUG, - ], - methods: ['POST'] - )] - public function __invoke(#[MapRequestPayload] ResetPasswordModel $model, string $token): JsonResponse - { - $token = new GeneratedToken($token); - $this->handleCommand(new ResetPassword($token, $model->password)); - - return new JsonResponse(status: 200); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UnlockAccountController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UnlockAccountController.php deleted file mode 100644 index 2af42d2..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UnlockAccountController.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -final class UnlockAccountController extends AbstractController -{ - #[Route( - path: '/api/account/unlock/{token}', - name: 'identity_and_access_unlock_account', - requirements: [ - 'token' => Requirement::ASCII_SLUG, - ], - methods: ['GET'] - )] - public function __invoke(string $token): JsonResponse - { - $token = new GeneratedToken($token); - $this->handleCommand(new UnlockAccount($token)); - - return new JsonResponse(status: 200); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UpdatePasswordController.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UpdatePasswordController.php deleted file mode 100644 index 41972eb..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/Web/Controller/UpdatePasswordController.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class UpdatePasswordController extends AbstractController -{ - #[Route( - path: '/api/password/update', - name: 'identity_and_access_update_password', - methods: ['POST'] - )] - public function __invoke(#[MapRequestPayload] UpdatePasswordModel $model): JsonResponse - { - $securityUser = $this->getSecurityUser(); - $this->handleCommand(new UpdatePassword( - $securityUser->userId, - $model->current, - $model->password - )); - - return new JsonResponse(status: 200); - } -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RegisterModel.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RegisterModel.php deleted file mode 100644 index 9e91990..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RegisterModel.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -final class RegisterModel -{ - #[Assert\NotBlank] - #[Assert\Length(min: 3, max: 255)] - public string $name; - - #[Assert\NotBlank] - #[Assert\Email] - public string $email; - - #[Assert\NotBlank] - #[Assert\Length(max: 512)] - public string $password; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RequestPasswordModel.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RequestPasswordModel.php deleted file mode 100644 index 68d0110..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/RequestPasswordModel.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final class RequestPasswordModel -{ - #[Assert\NotBlank] - #[Assert\Email] - #[Assert\Length(max: 255)] - public string $email; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/ResetPasswordModel.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/ResetPasswordModel.php deleted file mode 100644 index 34f973b..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/ResetPasswordModel.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class ResetPasswordModel -{ - #[Assert\NotBlank] - #[Assert\Length(max: 512)] - #[Assert\PasswordStrength] - public string $password; - - #[Assert\EqualTo( - propertyPath: 'password', - message: 'identity_and_access.exceptions.passwords_do_not_match', - )] - public string $confirm; -} diff --git a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/UpdatePasswordModel.php b/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/UpdatePasswordModel.php deleted file mode 100644 index b694b73..0000000 --- a/apps/api-legacy/src/IdentityAndAccess/Presentation/WriteModel/UpdatePasswordModel.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -final class UpdatePasswordModel -{ - #[Assert\NotBlank] - public string $current; - - #[Assert\NotBlank] - #[Assert\Length(max: 512)] - #[Assert\PasswordStrength] - public string $password; - - #[Assert\EqualTo( - propertyPath: 'password', - message: 'identity_and_access.exceptions.passwords_do_not_match', - )] - public string $confirm; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Asset/AssetType.php b/apps/api-legacy/src/SharedKernel/Application/Asset/AssetType.php deleted file mode 100644 index 4739adf..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Asset/AssetType.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -enum AssetType -{ - case SOURCE_PROFILE_IMAGE; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Asset/AssetUrlProvider.php b/apps/api-legacy/src/SharedKernel/Application/Asset/AssetUrlProvider.php deleted file mode 100644 index 7bcfed4..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Asset/AssetUrlProvider.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface AssetUrlProvider -{ - public function getUrl(string $id, AssetType $type): ?string; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Mailing/EmailDefinition.php b/apps/api-legacy/src/SharedKernel/Application/Mailing/EmailDefinition.php deleted file mode 100644 index b240f07..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Mailing/EmailDefinition.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -interface EmailDefinition -{ - public function recipient(): EmailAddress; - - public function subject(): string; - - public function subjectVariables(): array; - - public function template(): string; - - public function templateVariables(): array; - - public function locale(): string; - - public function getDomain(): string; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Mailing/Mailer.php b/apps/api-legacy/src/SharedKernel/Application/Mailing/Mailer.php deleted file mode 100644 index 11eb00f..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Mailing/Mailer.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface Mailer -{ - public function send(EmailDefinition $email): void; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/AsyncMessage.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/AsyncMessage.php deleted file mode 100644 index 2233d70..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/AsyncMessage.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -interface AsyncMessage -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandBus.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandBus.php deleted file mode 100644 index 867a323..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandBus.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface CommandBus -{ - public function handle(object $message): mixed; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandHandler.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandHandler.php deleted file mode 100644 index c34f1b0..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/CommandHandler.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -interface CommandHandler -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageBus.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageBus.php deleted file mode 100644 index 9203dfc..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageBus.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface MessageBus -{ - public function dispatch(AsyncMessage $message): void; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageHandler.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageHandler.php deleted file mode 100644 index 6d8a7d8..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/MessageHandler.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -interface MessageHandler -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryBus.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryBus.php deleted file mode 100644 index fb2570d..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryBus.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface QueryBus -{ - public function handle(object $message): mixed; -} diff --git a/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryHandler.php b/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryHandler.php deleted file mode 100644 index 333c250..0000000 --- a/apps/api-legacy/src/SharedKernel/Application/Messaging/QueryHandler.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -interface QueryHandler -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Application.php b/apps/api-legacy/src/SharedKernel/Domain/Application.php deleted file mode 100644 index 9d01770..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Application.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final class Application -{ - public string $name = 'Basango'; - - public string $website = 'https://basango.ngandu.dev'; - - public string $emailAddress = 'contact@devscast.tech'; - - public string $infoAddress = 'contact@devscast.tech'; - - public string $emailName = 'Basango'; - - public string $legalName = 'Devscast Software SàSu'; - - public string $legalRegistrationCode = ''; - - public string $legalVatCode = ''; - - public string $legalAddress = '10465, Avenue Lac kipopo, Lubumbashi, Haut-Katanga, RDC'; - - public string $legalPhone = '+243892530482'; -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Assert.php b/apps/api-legacy/src/SharedKernel/Domain/Assert.php deleted file mode 100644 index 8f8de44..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Assert.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final class Assert extends \Webmozart\Assert\Assert -{ - #[\Override] - protected static function reportInvalidArgument($message): void - { - throw new InvalidArgument($message); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataExporter.php b/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataExporter.php deleted file mode 100644 index 6c6d46b..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataExporter.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface DataExporter -{ - public function export(iterable $data, TransfertSetting $setting = new TransfertSetting()): \SplFileObject; -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataImporter.php b/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataImporter.php deleted file mode 100644 index d5360c3..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataImporter.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface DataImporter -{ - public function import(\SplFileObject $file, TransfertSetting $setting = new TransfertSetting()): iterable; -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataMapping.php b/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataMapping.php deleted file mode 100644 index d00e8d9..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/DataMapping.php +++ /dev/null @@ -1,179 +0,0 @@ - - */ -abstract class DataMapping -{ - /** - * @param array $data - * @param non-empty-string $key - */ - public static function uuid(array $data, string $key): UuidV7 - { - Assert::keyExists($data, $key); - return UuidV7::fromString($data[$key]); - } - - /** - * @template T of \BackedEnum - * @param array $data - * @param non-empty-string $key - * @param class-string $class - * @phpstan-return T - */ - public static function enum(array $data, string $key, string $class): \BackedEnum - { - Assert::keyExists($data, $key); - return $class::from($data[$key]); - } - - /** - * @template T of \BackedEnum - * @param array $data - * @param non-empty-string $key - * @param class-string $class - * @phpstan-return T - */ - public static function nullableEnum(array $data, string $key, string $class): ?\BackedEnum - { - Assert::keyExists($data, $key); - return $class::tryFrom($data[$key]); - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function string(array $data, string $key): string - { - if (! isset($data[$key]) || $data[$key] === '') { - return ''; - } - - return strval($data[$key]); - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function nullableString(array $data, string $key): ?string - { - if (! isset($data[$key]) || $data[$key] === '') { - return null; - } - - return strval($data[$key]); - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function boolean(array $data, string $key): bool - { - return isset($data[$key]) && (bool) $data[$key]; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function nullableBoolean(array $data, string $key): ?bool - { - if (! isset($data[$key])) { - return null; - } - - return (bool) $data[$key]; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function integer(array $data, string $key): int - { - return isset($data[$key]) ? (int) $data[$key] : 0; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function nullableInteger(array $data, string $key): ?int - { - if (! isset($data[$key])) { - return null; - } - - return (int) $data[$key]; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function float(array $data, string $key): float - { - return isset($data[$key]) ? (float) $data[$key] : 0.0; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function nullableFloat(array $data, string $key): ?float - { - if (! isset($data[$key])) { - return null; - } - - return (float) $data[$key]; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function datetime(array $data, string $key, string $format = 'Y-m-d H:i:s'): \DateTimeImmutable - { - Assert::keyExists($data, $key); - $datetime = \DateTimeImmutable::createFromFormat($format, $data[$key]); - - if ($datetime === false) { - throw new \InvalidArgumentException('Invalid datetime format'); - } - - return $datetime; - } - - /** - * @param array $data - * @param non-empty-string $key - */ - public static function nullableDatetime(array $data, string $key, string $format = 'Y-m-d H:i:s'): ?\DateTimeImmutable - { - if (! isset($data[$key])) { - return null; - } - - $datetime = \DateTimeImmutable::createFromFormat($format, $data[$key]); - - if ($datetime === false) { - throw new \InvalidArgumentException('Invalid datetime format'); - } - - return $datetime; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/TransfertSetting.php b/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/TransfertSetting.php deleted file mode 100644 index 17dbf0e..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/DataTransfert/TransfertSetting.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class TransfertSetting -{ - public function __construct( - public ?string $filename = null, - public ?string $type = null, - public string $format = 'csv' - ) { - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventDispatcher.php b/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventDispatcher.php deleted file mode 100644 index 0219fcf..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventDispatcher.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -interface EventDispatcher -{ - /** - * @param array $events - */ - public function dispatch(array $events): void; -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventEmitterTrait.php b/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventEmitterTrait.php deleted file mode 100644 index dcc03ed..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/EventDispatcher/EventEmitterTrait.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -trait EventEmitterTrait -{ - /** - * @var array - */ - private array $emittedEvents = []; - - public function emitEvent(object $event): void - { - $this->emittedEvents[] = $event; - } - - /** - * @return array - */ - public function releaseEvents(): array - { - return $this->emittedEvents; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/EventListener/EventListener.php b/apps/api-legacy/src/SharedKernel/Domain/EventListener/EventListener.php deleted file mode 100644 index ac0d288..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/EventListener/EventListener.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -interface EventListener -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidArgument.php b/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidArgument.php deleted file mode 100644 index be4a6c1..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidArgument.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final class InvalidArgument extends \RuntimeException implements UserFacingError -{ - #[\Override] - public function translationId(): string - { - return 'shared_kernel.exceptions.invalid_argument'; - } - - #[\Override] - public function translationParameters(): array - { - return []; - } - - #[\Override] - public function translationDomain(): string - { - return 'messages'; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidEmailAddress.php b/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidEmailAddress.php deleted file mode 100644 index b25215d..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Exception/InvalidEmailAddress.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ -final class InvalidEmailAddress extends \InvalidArgumentException implements UserFacingError -{ - public function __construct( - private readonly string $email - ) { - parent::__construct(sprintf('%s : Invalid email address provided', $this->email)); - } - - public static function withValue(string $value): self - { - return new self($value); - } - - #[\Override] - public function translationId(): string - { - return 'shared_kernel.exceptions.invalid_email_address'; - } - - #[\Override] - public function translationParameters(): array - { - return [ - '%email%' => $this->email, - ]; - } - - #[\Override] - public function translationDomain(): string - { - return 'messages'; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Exception/UserFacingError.php b/apps/api-legacy/src/SharedKernel/Domain/Exception/UserFacingError.php deleted file mode 100644 index e4ac4eb..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Exception/UserFacingError.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface UserFacingError extends \Throwable -{ - public function translationId(): string; - - public function translationParameters(): array; - - public function translationDomain(): string; -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/Collection.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/Collection.php deleted file mode 100644 index b22f243..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/Collection.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * @author bernard-ng - */ -interface Collection extends DoctrineCollection -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/DataCollection.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/DataCollection.php deleted file mode 100644 index 6880f31..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Collection/DataCollection.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * @author bernard-ng - */ -final class DataCollection extends DoctrineArrayCollection -{ -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/Page.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/Page.php deleted file mode 100644 index 5c6cc61..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/Page.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class Page -{ - public const int DEFAULT_PAGE = 1; - - public const int DEFAULT_LIMIT = 5; - - public const int MAX_LIMIT = 100; - - public function __construct( - public int $page = self::DEFAULT_PAGE, - public int $limit = self::DEFAULT_LIMIT, - public ?string $cursor = null, - public int $offset = 0, - ) { - Assert::greaterThanEq($this->page, self::DEFAULT_PAGE); - Assert::greaterThanEq($this->limit, self::DEFAULT_LIMIT); - Assert::lessThanEq($this->limit, self::MAX_LIMIT); - - $this->offset = intval(($this->page - 1) * $this->limit); - } - - public function next(): self - { - return new self($this->page + 1, $this->limit); - } - - public function previous(): self - { - if ($this->page === self::DEFAULT_PAGE) { - return $this; - } - - return new self($this->page - 1, $this->limit); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationCursor.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationCursor.php deleted file mode 100644 index 13ad035..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationCursor.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -final readonly class PaginationCursor -{ - public function __construct( - public UuidV7 $id, - public ?\DateTimeImmutable $date = null, - ) { - } - - /** - * Creates a new PaginationCursor from a DateTimeImmutable and a UuidV7. - * @throws \JsonException When JSON encoding fails - */ - public static function encode(array $item, PaginatorKeyset $keyset): string - { - $payload = [ - 'id' => DataMapping::string($item, $keyset->id), - ]; - - if ($keyset->date !== null) { - $payload['date'] = DataMapping::dateTime($item, $keyset->date)->format('Y-m-d H:i:s'); - } - - return base64_encode(json_encode($payload, JSON_THROW_ON_ERROR)); - - } - - /** - * Decodes a cursor string into a PaginationCursor object. - * Returns null if the cursor is invalid or cannot be decoded. - */ - public static function decode(?string $cursor): ?self - { - if ($cursor === null) { - return null; - } - - try { - $decoded = base64_decode($cursor, true); - if ($decoded === false) { - return null; - } - - $data = json_decode($decoded, true, 512, JSON_THROW_ON_ERROR); - - if (! is_array($data) || ! isset($data['id'])) { - throw new \InvalidArgumentException('Invalid cursor format'); - } - - $date = null; - if (isset($data['date'])) { - $date = new \DateTimeImmutable($data['date']); - } - - return new self( - id: UuidV7::fromString($data['id']), - date: $date, - ); - } catch (\Throwable) { - return null; - } - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationInfo.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationInfo.php deleted file mode 100644 index 3de5e34..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginationInfo.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final class PaginationInfo -{ - public function __construct( - public readonly int $current, - public readonly int $limit, - public ?string $cursor = null, - public bool $hasNext = false, - ) { - } - - public static function from(Page $page): self - { - return new self($page->page, $page->limit); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginatorKeyset.php b/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginatorKeyset.php deleted file mode 100644 index fdc97aa..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/Pagination/PaginatorKeyset.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final readonly class PaginatorKeyset -{ - /** - * @param non-empty-string $id - * @param non-empty-string|null $date - */ - public function __construct( - public string $id, - public ?string $date = null, - ) { - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/DateRange.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/DateRange.php deleted file mode 100644 index 6674387..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/DateRange.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ -final class DateRange implements \Stringable -{ - private function __construct( - public int $start, - public int $end - ) { - Assert::notEq($this->start, 0); - Assert::notEq($this->end, 0); - Assert::greaterThanEq($end, $start); - } - - #[\Override] - public function __toString(): string - { - return sprintf('%d:%d', $this->start, $this->end); - } - - public static function from(string $interval, string $format = 'Y-m-d', string $separator = ':'): self - { - if ($separator === '') { - throw new \InvalidArgumentException('Separator cannot be empty'); - } - - [$startDate, $endDate] = explode($separator, $interval); - - /** @var DateTime $start */ - $start = DateTime::createFromFormat($format, $startDate); - - /** @var DateTime $end */ - $end = DateTime::createFromFormat($format, $endDate); - - return new self((int) $start->format('U'), (int) $end->format('U')); - } - - public static function backward(\DateTimeImmutable $date = new \DateTimeImmutable(), ?int $days = null): self - { - $days ??= 30; - $start = $date->modify(sprintf('-%d days', $days)); - $end = $date->modify('+1 days'); - - return new self((int) $start->format('U'), (int) $end->format('U')); - } - - public static function forward(\DateTimeImmutable $date): self - { - $start = $date; - $end = new \DateTimeImmutable('now')->modify('+1 days'); - - return new self((int) $start->format('U'), (int) $end->format('U')); - } - - public function format(string $format = 'Y-m-d'): string - { - return sprintf('%s:%s', date($format, $this->start), date($format, $this->end)); - } - - public function inRange(int $timestamp): bool - { - return $timestamp >= $this->start && $timestamp <= $this->end; - } - - public function outRange(int $timestamp): bool - { - return $timestamp < $this->start || $timestamp > $this->end; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/EmailAddress.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/EmailAddress.php deleted file mode 100644 index 19531ff..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/EmailAddress.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -final readonly class EmailAddress implements \Stringable, \JsonSerializable -{ - public string $value; - - public function __construct(string $value) - { - try { - Assert::notEmpty($value); - Assert::email($value); - } catch (\Throwable) { - throw InvalidEmailAddress::withValue($value); - } - - $this->value = $value; - } - - #[\Override] - public function __toString(): string - { - return $this->value; - } - - /** - * @throws InvalidEmailAddress - */ - public static function from(string $value): self - { - return new self($value); - } - - public function provider(): string - { - return substr($this->value, strpos($this->value, '@') + 1); - } - - public function jsonSerialize(): string - { - return $this->value; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/SortDirection.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/SortDirection.php deleted file mode 100644 index dc642fe..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/SortDirection.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -enum SortDirection: string -{ - case ASC = 'asc'; - case DESC = 'desc'; - - public function opposite(): self - { - return match ($this) { - self::ASC => self::DESC, - self::DESC => self::ASC, - }; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/ClientProfile.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/ClientProfile.php deleted file mode 100644 index 53f9f10..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/ClientProfile.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -final readonly class ClientProfile -{ - public function __construct( - #[\SensitiveParameter] public ?string $userIp = null, - public ?string $userAgent = null, - public array $hints = [] - ) { - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/Device.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/Device.php deleted file mode 100644 index 0bb1de6..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/Device.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -final readonly class Device -{ - public function __construct( - public ?string $operatingSystem = null, - public ?string $client = null, - public ?string $device = null, - public bool $isBot = false, - ) { - } - - public static function empty(): self - { - return new self(); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/GeoLocation.php b/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/GeoLocation.php deleted file mode 100644 index b75e183..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Model/ValueObject/Tracking/GeoLocation.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final readonly class GeoLocation -{ - public function __construct( - public ?string $country = null, - public ?string $city = null, - public ?string $timeZone = null, - public ?float $longitude = null, - public ?float $latitude = null, - public ?int $accuracyRadius = null, - ) { - } - - public static function from(array $data): self - { - Assert::keyExists($data, 'country'); - Assert::keyExists($data, 'city'); - Assert::keyExists($data, 'time_zone'); - Assert::keyExists($data, 'longitude'); - Assert::keyExists($data, 'latitude'); - Assert::keyExists($data, 'accuracy_radius'); - - return new self( - country: $data['country'] ?? null, - city: $data['city'] ?? null, - timeZone: $data['time_zone'] ?? null, - longitude: $data['longitude'] ?? null, - latitude: $data['latitude'] ?? null, - accuracyRadius: $data['accuracy_radius'] ?? null, - ); - } - - public static function empty(): self - { - return new self(); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Domain/Tracking/ClientProfiler.php b/apps/api-legacy/src/SharedKernel/Domain/Tracking/ClientProfiler.php deleted file mode 100644 index a56457f..0000000 --- a/apps/api-legacy/src/SharedKernel/Domain/Tracking/ClientProfiler.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -interface ClientProfiler -{ - public function detect(ClientProfile $profile): Device; - - public function locate(ClientProfile $profile): GeoLocation; - - public function locateCountry(ClientProfile $profile): ?string; -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/EventDispatcher/SymfonyEventDispatcher.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/EventDispatcher/SymfonyEventDispatcher.php deleted file mode 100644 index 1ba8bd8..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/EventDispatcher/SymfonyEventDispatcher.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -final readonly class SymfonyEventDispatcher implements EventDispatcher -{ - public function __construct( - private EventDispatcherInterface $eventDispatcher - ) { - } - - /** - * @param array $events - */ - #[\Override] - public function dispatch(array $events): void - { - foreach ($events as $event) { - $this->eventDispatcher->dispatch($event, $event::class); - } - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Kernel.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Kernel.php deleted file mode 100644 index 123f505..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Kernel.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -class Kernel extends BaseKernel -{ - use MicroKernelTrait; -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/NormalizerFormatter.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/NormalizerFormatter.php deleted file mode 100644 index 1c624db..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/NormalizerFormatter.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ -class NormalizerFormatter extends MonologNormalizerFormatter implements FormatterInterface -{ - public const string SIMPLE_DATE = 'Y-m-d\TH:i:sP'; - - protected string $dateFormat; - - protected int $maxNormalizeDepth = 9; - - protected int $maxNormalizeItemCount = 1000; - - protected string $basePath = ''; - - private int $jsonEncodeOptions = JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_PRETTY_PRINT; - - /** - * Setting a base path will hide the base path from exception and stack trace file names to shorten them - * - * @return $this - */ - #[\Override] - public function setBasePath(string $path = ''): self - { - if ($path !== '') { - $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - } - - $this->basePath = $path; - - return $this; - } - - /** - * Return the JSON representation of a value - * - * @param mixed $data - * @return string if encoding fails and ignoreErrors is true 'null' is returned - * @throws \RuntimeException if encoding fails and errors are not ignored - */ - #[\Override] - protected function toJson($data, bool $ignoreErrors = false): string - { - $json = Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors); - return <<< JSON -```json -{$json} -``` -JSON; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/TelegramFormatter.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/TelegramFormatter.php deleted file mode 100644 index 5043c53..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Logging/TelegramFormatter.php +++ /dev/null @@ -1,198 +0,0 @@ - - */ -class TelegramFormatter extends NormalizerFormatter -{ - public const int BATCH_MODE_JSON = 1; - - public const int BATCH_MODE_NEWLINES = 2; - - /** - * @param self::BATCH_MODE_* $batchMode - * - * @throws \RuntimeException If the function json_encode does not exist - */ - public function __construct( - protected int $batchMode = self::BATCH_MODE_JSON, - protected bool $appendNewline = true, - protected bool $ignoreEmptyContextAndExtra = false, - protected bool $includeStacktraces = false, - string $basePath = '' - ) { - $this->basePath = $basePath; - - parent::__construct(); - } - - /** - * The batch mode option configures the formatting style for - * multiple records. By default, multiple records will be - * formatted as a JSON-encoded array. However, for - * compatibility with some API endpoints, alternative styles - * are available. - */ - public function getBatchMode(): int - { - return $this->batchMode; - } - - /** - * True if newlines are appended to every formatted record - */ - public function isAppendingNewlines(): bool - { - return $this->appendNewline; - } - - #[\Override] - public function format(LogRecord $record): string - { - /** @var array $normalized */ - $normalized = parent::format($record); - - if (isset($normalized['context']) && $normalized['context'] === []) { - unset($normalized['context']); - } - - if (isset($normalized['extra']) && $normalized['extra'] === []) { - unset($normalized['extra']); - } - - return $this->toJson($normalized, true) . "\n\n"; - } - - #[\Override] - public function formatBatch(array $records): string - { - return match ($this->batchMode) { - static::BATCH_MODE_NEWLINES => $this->formatBatchNewlines($records), - default => $this->formatBatchJson($records), - }; - } - - /** - * @return $this - */ - public function includeStacktraces(bool $include = true): self - { - $this->includeStacktraces = $include; - - return $this; - } - - /** - * Return a JSON-encoded array of records. - * - * @phpstan-param LogRecord[] $records - */ - protected function formatBatchJson(array $records): string - { - return $this->toJson($this->normalize($records), true); - } - - /** - * Use new lines to separate records instead of a - * JSON-encoded array. - * - * @phpstan-param LogRecord[] $records - */ - protected function formatBatchNewlines(array $records): string - { - $oldNewline = $this->appendNewline; - $this->appendNewline = false; - $formatted = array_map(fn (LogRecord $record): string => $this->format($record), $records); - $this->appendNewline = $oldNewline; - - return implode("\n\n", $formatted); - } - - /** - * Normalizes given $data. - * - * @return array|bool|float|int|object|string|null - */ - #[\Override] - protected function normalize(mixed $data, int $depth = 0): array|bool|float|int|object|string|null - { - if ($depth > $this->maxNormalizeDepth) { - return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; - } - - if (\is_array($data)) { - $normalized = []; - - $count = 1; - foreach ($data as $key => $value) { - if ($count++ > $this->maxNormalizeItemCount) { - $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . \count($data) . ' total), aborting normalization'; - break; - } - - $normalized[$key] = $this->normalize($value, $depth + 1); - } - - return $normalized; - } - - if (\is_object($data)) { - if ($data instanceof \DateTimeInterface) { - return $this->formatDate($data); - } - - if ($data instanceof \Throwable) { - /** @var array|float|object|bool|int|string|null $throwable */ - $throwable = $this->normalizeException($data, $depth); - return $throwable; - } - - // if the object has specific json serializability we want to make sure we skip the __toString treatment below - if ($data instanceof \JsonSerializable) { - return $data; - } - - if ($data instanceof \Stringable) { - return $data->__toString(); - } - - if ($data::class === '__PHP_Incomplete_Class') { - return new \ArrayObject($data); - } - - return $data; - } - - if (\is_resource($data)) { - return parent::normalize($data); - } - - /** @var array|float|object|bool|int|string|null $data */ - return $data; - } - - /** - * Normalizes given exception with or without its own stack trace based on - * `includeStacktraces` property. - * - * @inheritDoc - */ - #[\Override] - protected function normalizeException(\Throwable $e, int $depth = 0): array|float|object|bool|int|string|null - { - $data = parent::normalizeException($e, $depth); - if (! $this->includeStacktraces) { - unset($data['trace']); - } - - return $data; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Mailing/SymfonyMailer.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Mailing/SymfonyMailer.php deleted file mode 100644 index 67e665f..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Mailing/SymfonyMailer.php +++ /dev/null @@ -1,69 +0,0 @@ - - */ -final readonly class SymfonyMailer implements Mailer -{ - public function __construct( - private MailerInterface $mailer, - private TranslatorInterface $translator, - private Application $application = new Application() - ) { - } - - /** - * @throws TransportExceptionInterface - */ - #[\Override] - public function send(EmailDefinition $email): void - { - $sender = new Address( - $this->application->emailAddress, - $this->application->emailName - ); - - $htmlTemplate = sprintf('emails/%s.html.twig', $email->template()); - $txtTemplate = sprintf('emails/%s.txt.twig', $email->template()); - - $message = new TemplatedEmail() - ->from($sender) - ->to($email->recipient()->value) - ->subject( - $this->translator->trans( - $email->subject(), - $email->subjectVariables(), - $email->getDomain(), - $email->locale() - ) - ) - ->htmlTemplate($htmlTemplate) - ->textTemplate($txtTemplate) - ->context(array_merge( - $email->templateVariables(), - [ - 'application' => new Application(), - 'locale' => $email->locale(), - 'domain' => $email->getDomain(), - ] - )) - ; - - $this->mailer->send($message); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerCommandBus.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerCommandBus.php deleted file mode 100644 index f1fd3f1..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerCommandBus.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -final class MessengerCommandBus implements CommandBus -{ - use HandleTrait { - HandleTrait::handle as messengerHandle; - } - - public function __construct(MessageBusInterface $commandBus) - { - $this->messageBus = $commandBus; - } - - /** - * @throws \Throwable - */ - #[\Override] - public function handle(object $command): mixed - { - try { - return $this->messengerHandle($command); - } catch (HandlerFailedException $e) { - while ($e instanceof HandlerFailedException) { - /** @var \Throwable $e */ - $e = $e->getPrevious(); - } - - throw $e; - } - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerMessageBus.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerMessageBus.php deleted file mode 100644 index 75e4e64..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerMessageBus.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -final readonly class MessengerMessageBus implements MessageBus -{ - public function __construct( - private MessageBusInterface $messageBus - ) { - } - - /** - * @throws ExceptionInterface - */ - #[\Override] - public function dispatch(AsyncMessage $message): void - { - $this->messageBus->dispatch($message); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerQueryBus.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerQueryBus.php deleted file mode 100644 index ead69e5..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Framework/Symfony/Messaging/MessengerQueryBus.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -final class MessengerQueryBus implements QueryBus -{ - use HandleTrait { - HandleTrait::handle as messengerHandle; - } - - public function __construct(MessageBusInterface $queryBus) - { - $this->messageBus = $queryBus; - } - - /** - * @throws \Throwable - */ - #[\Override] - public function handle(object $message): mixed - { - try { - return $this->messengerHandle($message); - } catch (HandlerFailedException $e) { - while ($e instanceof HandlerFailedException) { - /** @var \Throwable $e */ - $e = $e->getPrevious(); - } - - throw $e; - } - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Features/PaginationQuery.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Features/PaginationQuery.php deleted file mode 100644 index eeceac7..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Features/PaginationQuery.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -trait PaginationQuery -{ - public function createPaginationInfo(array &$data, Page $page, PaginatorKeyset $keyset): PaginationInfo - { - $paginationInfo = PaginationInfo::from($page); - if ($data === []) { - return $paginationInfo; - } - - $hasNext = count($data) > $page->limit; - if ($hasNext) { - array_pop($data); - } - - $cursorSource = end($data); - - if (is_array($cursorSource)) { - $paginationInfo->cursor = PaginationCursor::encode($cursorSource, $keyset); - } - - $paginationInfo->hasNext = $hasNext; - reset($data); - - return $paginationInfo; - } - - public function applyCursorPagination( - QueryBuilder $qb, - Page $page, - PaginatorKeyset $keyset, - SortDirection $direction = SortDirection::DESC - ): QueryBuilder { - $comparisonOperator = $direction === SortDirection::ASC ? '>' : '<'; - - if ($keyset->date !== null) { - $qb->addOrderBy($keyset->date, $direction->value); - } - - $qb->addOrderBy($keyset->id, $direction->value); - - $cursor = PaginationCursor::decode($page->cursor); - if (! $cursor instanceof PaginationCursor) { - return $qb->setMaxResults($page->limit + 1); - } - - if ($keyset->date === null) { - $qb - ->andWhere(sprintf('%s %s :cursorLastId', $keyset->id, $comparisonOperator)) - ->setParameter('cursorLastId', $cursor->id->toString()); - } else { - if (! $cursor->date instanceof \DateTimeImmutable) { - return $qb->setMaxResults($page->limit + 1); - } - - $qb - ->andWhere(sprintf('(%s, %s) %s (:cursorLastDate, :cursorLastId)', $keyset->date, $keyset->id, $comparisonOperator)) - ->setParameter('cursorLastDate', $cursor->date->format('Y-m-d H:i:s')) - ->setParameter('cursorLastId', $cursor->id->toString()); - } - - return $qb->setMaxResults($page->limit + 1); - } - - public function applyOffsetPagination(QueryBuilder $qb, Page $page): QueryBuilder - { - return $qb - ->setFirstResult($page->offset) - ->setMaxResults($page->limit) - ; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/NoResult.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/NoResult.php deleted file mode 100644 index 569fbe3..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/NoResult.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final class NoResult extends \RuntimeException -{ - public static function forQuery(string $query, array $parameters, ?\Throwable $previous = null): self - { - return new self( - sprintf('%s - Query "%s" (parameters: %s) produced no results', $previous?->getMessage(), $query, json_encode($parameters)), - previous: $previous - ); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Types/EmailType.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Types/EmailType.php deleted file mode 100644 index d72be3a..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/DBAL/Types/EmailType.php +++ /dev/null @@ -1,74 +0,0 @@ - - */ -final class EmailType extends Type -{ - public const string NAME = 'email'; - - #[\Override] - public function getSQLDeclaration(array $column, AbstractPlatform $platform): string - { - return $platform->getStringTypeDeclarationSQL([ - 'length' => 255, - ]); - } - - #[\Override] - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?EmailAddress - { - if ($value === null) { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', EmailAddress::class]); - } - - try { - return EmailAddress::from($value); - } catch (\Throwable $e) { - throw ConversionException::conversionFailed($value, $this->getName(), $e); - } - } - - #[\Override] - public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string - { - if ($value instanceof EmailAddress) { - return (string) $value; - } - - if ($value === null || $value === '') { - return null; - } - - if (! \is_string($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', EmailAddress::class]); - } - - try { - return (string) EmailAddress::from($value); - } catch (\Throwable $e) { - throw ConversionException::conversionFailed($value, $this->getName(), $e); - } - } - - #[\Override] - public function getName(): string - { - return self::NAME; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/Importer/ImportEngine.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/Importer/ImportEngine.php deleted file mode 100644 index 0053dbd..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Doctrine/Importer/ImportEngine.php +++ /dev/null @@ -1,313 +0,0 @@ - ['tsv', 'image', 'excerpt'], - ]; - - private Connection $targetConnection; - - private PDO $sourceConnection; - - public function __construct( - private EntityManagerInterface $em, - #[Autowire(env: 'SOURCE_DATABASE_HOST')] private string $host, - #[Autowire(env: 'SOURCE_DATABASE_USER')] private string $user, - #[Autowire(env: 'SOURCE_DATABASE_PASS')] private string $pass, - #[Autowire(env: 'SOURCE_DATABASE_PORT')] private int $port = 3306, - #[Autowire(env: 'SOURCE_DATABASE_NAME')] private string $name = 'app', - ) { - // Target (PostgreSQL via Doctrine DBAL) - $this->targetConnection = $this->em->getConnection(); - $this->targetConnection->getConfiguration()->setMiddlewares([]); - - // If DBAL exposes a native PDO, harden it for low memory - try { - $native = $this->targetConnection->getNativeConnection(); - if ($native instanceof PDO) { - // Use server-side prepares; avoids driver-side buffering - $native->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); - $native->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); - $native->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } - } catch (\Throwable) { - // If the platform/driver doesn’t expose a PDO, ignore safely - } - - // Source (MariaDB/MySQL via PDO), unbuffered - $this->sourceConnection = new PDO( - dsn: sprintf('mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', $this->host, $this->port, $this->name), - username: $this->user, - password: $this->pass, - options: [ - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ] - ); - - // Unbuffered cursor (critical for memory) - if (defined('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY')) { - $this->sourceConnection->setAttribute(constant('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'), false); - } - } - - public function import(string $table, int $batchSize = 1000): int - { - $this->reset($table); - $rows = $this->copy($table); - return $this->paste($table, $rows, $batchSize); - } - - /** - * Truncate target table safely with replication role toggling. - */ - private function reset(string $tableName): void - { - $platform = $this->targetConnection->getDatabasePlatform(); - $this->targetConnection->beginTransaction(); - - try { - $this->targetConnection->executeStatement("SET session_replication_role = 'replica'"); - $sql = $platform->getTruncateTableSQL($tableName, true); - $this->targetConnection->executeStatement($sql); - $this->targetConnection->executeStatement("SET session_replication_role = 'origin'"); - $this->targetConnection->commit(); - } catch (Throwable $e) { - if ($this->targetConnection->isTransactionActive()) { - $this->targetConnection->rollBack(); - } - - throw $e; - } - } - - /** - * Stream rows from MySQL unbuffered; ensure cursor is always closed. - */ - private function copy(string $table): iterable - { - $sql = sprintf('SELECT * FROM `%s`', str_replace('`', '', $table)); - $stmt = $this->sourceConnection->query($sql); - - if ($stmt === false) { - // Return an empty iterable on failure - return []; - } - - return (function () use ($stmt): Generator { - try { - while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) { - yield $row; - } - } finally { - // Free server resources ASAP - $stmt->closeCursor(); - } - })(); - } - - /** - * Insert rows into PostgreSQL with minimal allocations. - * - Fixed-size $params array reused per row - * - Batch transactions to limit peak memory - * - Periodic GC for long streams - */ - private function paste(string $table, iterable $rows, int $batchSize = 1000): int - { - if ($batchSize <= 0) { - $batchSize = 1000; - } - - $platform = $this->targetConnection->getDatabasePlatform(); - $quote = static fn (string|int $id) => $platform->quoteIdentifier((string) $id); - - $ignored = $this->ignoredColumnsFor($table); - $ignoredFlip = $ignored !== [] ? array_flip($ignored) : []; - - $columns = null; - $statement = null; - $params = null; // fixed-size, reused - $total = 0; - $inBatch = 0; - - try { - foreach ($rows as $row) { - // Build statement on first row (after ignoring columns) - if ($columns === null) { - if ($ignoredFlip !== []) { - $row = array_diff_key($row, $ignoredFlip); - } - - /** @var list $columns */ - $columns = array_map(static fn (int|string $k): string => (string) $k, array_keys($row)); - $columnList = implode(', ', array_map($quote, $columns)); - $placeholders = implode(', ', array_fill(0, count($columns), '?')); - $sql = sprintf('INSERT INTO %s (%s) VALUES (%s)', $quote($table), $columnList, $placeholders); - $statement = $this->targetConnection->prepare($sql); - - // Allocate params array once, with fixed size - $params = array_fill(0, count($columns), null); - - // Begin first batch transaction - $this->targetConnection->beginTransaction(); - } - - // Fill params by index (avoid per-row array allocs) - $i = 0; - foreach ($columns as $col) { - $val = $row[$col] ?? null; - - if ($val !== null) { - if ($col === 'id' || str_ends_with((string) $col, '_id')) { - $params[$i++] = $this->normalizeUuidValue($val); - continue; - } - - // Convert invalid date to now() - if (str_ends_with((string) $col, '_at') && $val === '0000-00-00 00:00:00') { - $val = new \DateTimeImmutable('now')->format('Y-m-d H:i:s'); - $params[$i++] = $val; - continue; - } - - // Convert categories to PG text[] literal cheaply - if ($col === 'categories') { - if (is_string($val)) { - $val = $this->ensureUtf8String($val); - } - - $params[$i++] = sprintf('{%s}', $val); - continue; - } - - if (is_string($val)) { - $params[$i++] = $this->ensureUtf8String($val); - continue; - } - } - - $params[$i++] = $val; - } - - if (! $statement instanceof Statement) { - throw new \LogicException('Insert statement not initialized.'); - } - - // @phpstan-ignore-next-line - $statement->executeStatement($params); - $total++; - $inBatch++; - - if ($inBatch >= $batchSize) { - $this->targetConnection->commit(); - $inBatch = 0; - - // Start next batch transaction - $this->targetConnection->beginTransaction(); - - // Help GC on very long imports - if (($total % ($batchSize * 5)) === 0) { - gc_collect_cycles(); - } - } - } - - // Commit trailing rows if any - if ($inBatch > 0 && $this->targetConnection->isTransactionActive()) { - $this->targetConnection->commit(); - } - } catch (Throwable $e) { - if ($this->targetConnection->isTransactionActive()) { - $this->targetConnection->rollBack(); - } - - // Keep failure payloads small to avoid memory spikes - throw $e; - } finally { - // Release large references promptly - $statement = null; - $columns = null; - $params = null; - gc_collect_cycles(); - } - - return $total; - } - - private function ignoredColumnsFor(string $table): array - { - $normalized = strtolower(trim($table, '`"')); - return self::IGNORE_COLUMNS[$normalized] ?? []; - } - - /** - * Keep it cheap: fast-path valid UTF-8; otherwise minimal conversions. - */ - private function ensureUtf8String(string $value): string - { - // Fast path: valid UTF-8 - if (@preg_match('//u', $value) === 1) { - return $value; - } - - // Try common legacy encodings with transliteration - $converted = @iconv('CP1252', 'UTF-8//TRANSLIT', $value); - if ($converted === false) { - $converted = @iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $value); - } - - if ($converted === false) { - // Last resort: drop invalid sequences - $converted = @iconv('UTF-8', 'UTF-8//IGNORE', $value); - } - - return $converted !== false ? $converted : $value; - } - - private function normalizeUuidValue(mixed $value): string - { - if ($value instanceof Uuid) { - return (string) $value; - } - - if (is_string($value)) { - return Uuid::fromBinary($value)->toString(); - } - - return (string) $value; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/Asset/AssetUrlProvider.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/Asset/AssetUrlProvider.php deleted file mode 100644 index eabdef2..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/Asset/AssetUrlProvider.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -final class AssetUrlProvider implements AssetUrlProviderInterface -{ - public function __construct( - #[Autowire(env: 'SERVER_ADDR')] public ?string $serverAddress = null, - #[Autowire(env: 'SERVER_PORT')] public ?string $serverPort = null, - #[Autowire(env: 'APP_ENV')] public string $env = 'dev' - ) { - $this->serverAddress ??= $_SERVER['SERVER_ADDR'] ?? null; - $this->serverPort ??= $_SERVER['SERVER_PORT'] ?? null; - } - - public function getUrl(string $id, AssetType $type): ?string - { - if ($this->serverAddress === null) { - return null; - } - - $path = match ($type) { - AssetType::SOURCE_PROFILE_IMAGE => sprintf('/images/sources/%s.png', $id), - }; - - $scheme = $this->env === 'prod' ? 'https' : 'http'; - return sprintf('%s://%s:%s/%s', $scheme, $this->serverAddress, $this->serverPort, $path); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/DataTransfert.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/DataTransfert.php deleted file mode 100644 index 2500978..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Persistence/Filesystem/DataTransfert.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final readonly class DataTransfert implements DataImporter, DataExporter -{ - private const array SUPPORTED_FORMATS = ['csv']; - - public function __construct( - private SerializerInterface $serializer, - private Filesystem $filesystem, - ) { - } - - #[\Override] - public function export(iterable $data, TransfertSetting $setting = new TransfertSetting()): \SplFileObject - { - Assert::oneOf($setting->format, self::SUPPORTED_FORMATS); - - $data = $this->serializer->serialize($data, $setting->format); - $filename = $setting->filename ?? $this->filesystem->tempnam(sys_get_temp_dir(), 'export'); - $this->filesystem->dumpFile($filename, $data); - - return new \SplFileObject($filename); - } - - #[\Override] - public function import(\SplFileObject $file, TransfertSetting $setting = new TransfertSetting()): iterable - { - Assert::notNull($setting->type); - Assert::oneOf($setting->format, self::SUPPORTED_FORMATS); - - $data = $this->filesystem->readFile($file->getPathname()); - - return $this->serializer->deserialize($data, $setting->type, $setting->format); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Infrastructure/Tracking/ClientProfiler.php b/apps/api-legacy/src/SharedKernel/Infrastructure/Tracking/ClientProfiler.php deleted file mode 100644 index 46d2982..0000000 --- a/apps/api-legacy/src/SharedKernel/Infrastructure/Tracking/ClientProfiler.php +++ /dev/null @@ -1,134 +0,0 @@ - - */ -final readonly class ClientProfiler implements ClientProfilerInterface -{ - private const string GEOIP_CITY_DATABASE = 'geoip_city.mmdb'; - - private const string GEOIP_COUNTRY_DATABASE = 'geoip_country.mmdb'; - - public function __construct( - private string $projectDir, - private LoggerInterface $logger - ) { - } - - #[\Override] - public function locate(ClientProfile $profile): GeoLocation - { - if ($this->shouldSkipIpLocalization($profile)) { - return GeoLocation::empty(); - } - - try { - $database = sprintf('%s/%s', $this->projectDir, self::GEOIP_CITY_DATABASE); - - Assert::notNull($profile->userIp); - $data = new Reader($database)->city($profile->userIp); - - return GeoLocation::from([ - 'country' => $data->country->isoCode, - 'city' => $data->city->name, - 'time_zone' => $data->location->timeZone, - 'longitude' => $data->location->longitude, - 'latitude' => $data->location->latitude, - 'accuracy_radius' => $data->location->accuracyRadius, - ]); - } catch (\Throwable $e) { - $this->logger->error('Unable to fetch location from IP address', [ - 'ip' => $profile->userIp, - 'exception' => $e, - ]); - - return GeoLocation::empty(); - } - } - - #[\Override] - public function locateCountry(ClientProfile $profile): ?string - { - if ($this->shouldSkipIpLocalization($profile)) { - return null; - } - - try { - $database = sprintf('%s/%s', $this->projectDir, self::GEOIP_COUNTRY_DATABASE); - - Assert::notNull($profile->userIp); - $data = new Reader($database)->country($profile->userIp); - - /** @var string|null $country */ - $country = $data->country->isoCode; - - return $country; - } catch (\Throwable $e) { - $this->logger->error('Unable to fetch country from IP address', [ - 'ip' => $profile->userIp, - 'exception' => $e, - ]); - - return null; - } - } - - #[\Override] - public function detect(ClientProfile $profile): Device - { - if ($profile->userAgent === null || $profile->hints === []) { - return Device::empty(); - } - - try { - $detector = new DeviceDetector($profile->userAgent, ClientHints::factory($profile->hints)); - $detector->parse(); - - $osLabel = is_string($detector->getOs('name')) ? $detector->getOs('name') : ''; - $clientLabel = is_string($detector->getClient('name')) ? $detector->getClient('name') : ''; - - return new Device( - operatingSystem: OperatingSystem::getOsFamily($osLabel), - client: match (true) { - $detector->isBrowser() => Browser::getBrowserFamily($clientLabel), - default => $clientLabel - }, - device: $detector->getDeviceName(), - isBot: $detector->isBot(), - ); - } catch (\Throwable $e) { - $this->logger->error('Unable to detect device', [ - 'user_agent' => $profile->userAgent, - 'exception' => $e, - ]); - - return Device::empty(); - } - } - - private function shouldSkipIpLocalization(ClientProfile $profile): bool - { - return \filter_var($profile->userIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) - || $profile->userIp === null - || IpUtils::isPrivateIp($profile->userIp); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Presentation/Console/AskArgumentFeature.php b/apps/api-legacy/src/SharedKernel/Presentation/Console/AskArgumentFeature.php deleted file mode 100644 index 848a2c2..0000000 --- a/apps/api-legacy/src/SharedKernel/Presentation/Console/AskArgumentFeature.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -trait AskArgumentFeature -{ - private function askArgument(InputInterface $input, string $name, bool $hidden = false): void - { - $value = \strval($input->getArgument($name)); - if ($value !== '') { - $this->io->text(\sprintf(' > %s: %s', $name, $value)); - } else { - $value = match ($hidden) { - false => $this->io->ask(\strtoupper($name)), - default => $this->io->askHidden(\strtoupper($name)) - }; - $input->setArgument($name, $value); - } - } - - private function askOption(InputInterface $input, string $name): void - { - $value = \strval($input->getOption($name)); - if ($value !== '') { - $this->io->text(\sprintf(' > %s: %s', $name, $value)); - } else { - $value = $this->io->ask(\strtoupper($name)); - $input->setOption($name, $value); - } - } -} diff --git a/apps/api-legacy/src/SharedKernel/Presentation/Console/SyncImport.php b/apps/api-legacy/src/SharedKernel/Presentation/Console/SyncImport.php deleted file mode 100644 index 7fa8794..0000000 --- a/apps/api-legacy/src/SharedKernel/Presentation/Console/SyncImport.php +++ /dev/null @@ -1,54 +0,0 @@ -io = new SymfonyStyle($input, $output); - } - - #[Override] - protected function execute(InputInterface $input, OutputInterface $output): int - { - if (! $this->io->confirm('Do you want to continue?', false)) { - $this->io->warning('Process aborted'); - return Command::FAILURE; - } - - $tables = ['user', 'source', 'article']; - foreach ($tables as $table) { - $count = $this->importEngine->import($table); - $this->io->text(sprintf('Imported %d records into %s table.', $count, $table)); - } - - $this->io->success('Source add successfully'); - return Command::SUCCESS; - } -} diff --git a/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/AbstractController.php b/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/AbstractController.php deleted file mode 100644 index 21f57b0..0000000 --- a/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/AbstractController.php +++ /dev/null @@ -1,91 +0,0 @@ - - */ -abstract class AbstractController extends SymfonyController -{ - protected ?Response $response = null; - - #[\Override] - public static function getSubscribedServices(): array - { - $subscribedServices = parent::getSubscribedServices(); - - $subscribedServices[] = CommandBus::class; - $subscribedServices[] = QueryBus::class; - $subscribedServices[] = TranslatorInterface::class; - $subscribedServices[] = LoggerInterface::class; - $subscribedServices[] = SerializerInterface::class; - - return $subscribedServices; - } - - public function getSecurityUser(): SecurityUser - { - /** @var SecurityUser|null $user */ - $user = $this->getUser(); - - if ($user === null) { - throw $this->createAccessDeniedException( - 'You must be authenticated to access this resource.' - ); - } - - return $user; - } - - public function serialize(mixed $data, string $format = 'json', array $context = []): string - { - /** @var SerializerInterface $serializer */ - $serializer = $this->container->get(SerializerInterface::class); - return $serializer->serialize($data, $format, $context); - } - - #[\Override] - protected function render(string $view, array $parameters = [], ?Response $response = null): Response - { - return parent::render($view, $parameters, $response ?? $this->response); - } - - protected function handleCommand(object $command): mixed - { - /** @var CommandBus $commandBus */ - $commandBus = $this->container->get(CommandBus::class); - return $commandBus->handle($command); - } - - protected function handleQuery(object $query): mixed - { - /** @var QueryBus $queryBus */ - $queryBus = $this->container->get(QueryBus::class); - return $queryBus->handle($query); - } - - protected function trans(string $key, array $params = [], string $domain = 'messages'): string - { - /** @var TranslatorInterface $trans */ - $trans = $this->container->get(TranslatorInterface::class); - return $trans->trans($key, $params, $domain); - } - - protected function setStatus(int $status): void - { - $this->response = new Response(status: $status); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/DefaultController.php b/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/DefaultController.php deleted file mode 100644 index 03760b7..0000000 --- a/apps/api-legacy/src/SharedKernel/Presentation/Web/Controller/DefaultController.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final class DefaultController extends AbstractController -{ - #[Route( - path: '', - name: 'default', - methods: ['GET'] - )] - public function __invoke(): JsonResponse - { - return $this->json([ - 'repository' => 'https://github.com/bernard-ng/basango', - 'title' => 'Basango : Towards a scalable and intelligent system for Congolese News curation', - 'description' => 'The Basango is a structured and scalable dataset of news articles sourced from major media outlets covering diverse aspects of the Democratic Republic of Congo (DRC). Designed for efficiency, this system enables the automated collection, processing, and organization of news stories spanning politics, economy, society, culture, environment, and international affairs.', - 'status' => 200, - ]); - } -} diff --git a/apps/api-legacy/src/SharedKernel/Presentation/Web/EventListener/UserFacingErrorListener.php b/apps/api-legacy/src/SharedKernel/Presentation/Web/EventListener/UserFacingErrorListener.php deleted file mode 100644 index 5ab987c..0000000 --- a/apps/api-legacy/src/SharedKernel/Presentation/Web/EventListener/UserFacingErrorListener.php +++ /dev/null @@ -1,92 +0,0 @@ - - */ -#[AsEventListener(KernelEvents::EXCEPTION, priority: -1)] -final readonly class UserFacingErrorListener -{ - private const array NOT_FOUND_EXCEPTIONS = [ - ArticleNotFound::class, - SourceNotFound::class, - UserNotFound::class, - CommentNotFound::class, - BookmarkNotFound::class, - FollowedSourceNotFound::class, - BookmarkedArticleNotFound::class, - ]; - - private const array BAD_REQUEST_EXCEPTIONS = [ - InvalidArgument::class, - ]; - - private const array FORBIDDEN_EXCEPTIONS = [ - PermissionNotGranted::class, - ]; - - private const array CONFLICT_EXCEPTIONS = [ - DuplicatedArticle::class, - ]; - - public function __construct( - private TranslatorInterface $translator - ) { - } - - public function __invoke(ExceptionEvent $event): void - { - $exception = $event->getThrowable(); - if ($exception instanceof UserFacingError) { - $message = $this->translator->trans( - $exception->translationId(), - $exception->translationParameters(), - $exception->translationDomain(), - ); - - $status = $this->getResponseStatus($exception); - $response = new JsonResponse([ - 'type' => 'https://symfony.com/errors/domain', - 'title' => $exception->translationId(), - 'detail' => $message, - 'status' => $status, - ], $status); - - $event->setResponse($response); - } - } - - public function getResponseStatus(UserFacingError $exception): int - { - return match (true) { - in_array($exception::class, self::NOT_FOUND_EXCEPTIONS) => Response::HTTP_NOT_FOUND, - in_array($exception::class, self::BAD_REQUEST_EXCEPTIONS) => Response::HTTP_BAD_REQUEST, - in_array($exception::class, self::FORBIDDEN_EXCEPTIONS) => Response::HTTP_FORBIDDEN, - in_array($exception::class, self::CONFLICT_EXCEPTIONS) => Response::HTTP_CONFLICT, - default => Response::HTTP_UNPROCESSABLE_ENTITY - }; - } -} diff --git a/apps/api-legacy/symfony.lock b/apps/api-legacy/symfony.lock deleted file mode 100644 index 2eab26f..0000000 --- a/apps/api-legacy/symfony.lock +++ /dev/null @@ -1,303 +0,0 @@ -{ - "doctrine/deprecations": { - "version": "1.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "87424683adc81d7dc305eefec1fced883084aab9" - } - }, - "doctrine/doctrine-bundle": { - "version": "2.13", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "2.12", - "ref": "7266981c201efbbe02ae53c87f8bb378e3f825ae" - }, - "files": [ - "config/packages/doctrine.yaml", - "src/Entity/.gitignore", - "src/Repository/.gitignore" - ] - }, - "doctrine/doctrine-fixtures-bundle": { - "version": "4.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "3.0", - "ref": "1f5514cfa15b947298df4d771e694e578d4c204d" - }, - "files": [ - "src/DataFixtures/AppFixtures.php" - ] - }, - "doctrine/doctrine-migrations-bundle": { - "version": "3.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "3.1", - "ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33" - }, - "files": [ - "config/packages/doctrine_migrations.yaml", - "migrations/.gitignore" - ] - }, - "friends-of-behat/symfony-extension": { - "version": "2.6", - "recipe": { - "repo": "github.com/symfony/recipes-contrib", - "branch": "main", - "version": "2.0", - "ref": "1e012e04f573524ca83795cd19df9ea690adb604" - } - }, - "gesdinet/jwt-refresh-token-bundle": { - "version": "1.4", - "recipe": { - "repo": "github.com/symfony/recipes-contrib", - "branch": "main", - "version": "1.0", - "ref": "2390b4ed5c195e0b3f6dea45221f3b7c0af523a0" - }, - "files": [ - "config/packages/gesdinet_jwt_refresh_token.yaml", - "config/routes/gesdinet_jwt_refresh_token.yaml", - "src/Entity/RefreshToken.php" - ] - }, - "knplabs/knp-paginator-bundle": { - "version": "v6.7.0" - }, - "lexik/jwt-authentication-bundle": { - "version": "3.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "2.5", - "ref": "e9481b233a11ef7e15fe055a2b21fd3ac1aa2bb7" - }, - "files": [ - "config/packages/lexik_jwt_authentication.yaml" - ] - }, - "phpstan/phpstan": { - "version": "1.10", - "recipe": { - "repo": "github.com/symfony/recipes-contrib", - "branch": "main", - "version": "1.0", - "ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767" - }, - "files": [ - "phpstan.dist.neon" - ] - }, - "phpunit/phpunit": { - "version": "10.4", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "9.6", - "ref": "7364a21d87e658eb363c5020c072ecfdc12e2326" - }, - "files": [ - ".env.test", - "phpunit.xml.dist", - "tests/bootstrap.php" - ] - }, - "sentry/sentry-symfony": { - "version": "5.2", - "recipe": { - "repo": "github.com/symfony/recipes-contrib", - "branch": "main", - "version": "5.0", - "ref": "f26c577142172082bb3aeef519af6b5944b86ac2" - }, - "files": [ - "config/packages/sentry.yaml" - ] - }, - "symfony/console": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.3", - "ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" - }, - "files": [ - "bin/console" - ] - }, - "symfony/flex": { - "version": "2.4", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" - }, - "files": [ - ".env" - ] - }, - "symfony/framework-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.2", - "ref": "af47254c5e4cd543e6af3e4508298ffebbdaddd3" - }, - "files": [ - "config/packages/cache.yaml", - "config/packages/framework.yaml", - "config/preload.php", - "config/routes/framework.yaml", - "config/services.yaml", - "public/index.php", - "src/Controller/.gitignore", - "src/Kernel.php" - ] - }, - "symfony/mailer": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "4.3", - "ref": "2bf89438209656b85b9a49238c4467bff1b1f939" - }, - "files": [ - "config/packages/mailer.yaml" - ] - }, - "symfony/maker-bundle": { - "version": "1.51", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" - } - }, - "symfony/messenger": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.0", - "ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee" - }, - "files": [ - "config/packages/messenger.yaml" - ] - }, - "symfony/monolog-bundle": { - "version": "3.10", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "3.7", - "ref": "aff23899c4440dd995907613c1dd709b6f59503f" - }, - "files": [ - "config/packages/monolog.yaml" - ] - }, - "symfony/routing": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.2", - "ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6" - }, - "files": [ - "config/packages/routing.yaml", - "config/routes.yaml" - ] - }, - "symfony/security-bundle": { - "version": "7.2", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.4", - "ref": "2ae08430db28c8eb4476605894296c82a642028f" - }, - "files": [ - "config/packages/security.yaml", - "config/routes/security.yaml" - ] - }, - "symfony/translation": { - "version": "7.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.3", - "ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b" - }, - "files": [ - "config/packages/translation.yaml", - "translations/.gitignore" - ] - }, - "symfony/twig-bundle": { - "version": "7.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.4", - "ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877" - }, - "files": [ - "config/packages/twig.yaml", - "templates/base.html.twig" - ] - }, - "symfony/uid": { - "version": "7.1", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "7.0", - "ref": "0df5844274d871b37fc3816c57a768ffc60a43a5" - } - }, - "symfony/validator": { - "version": "7.2", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "7.0", - "ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd" - }, - "files": [ - "config/packages/validator.yaml" - ] - }, - "symfony/web-profiler-bundle": { - "version": "7.2", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.1", - "ref": "8b51135b84f4266e3b4c8a6dc23c9d1e32e543b7" - }, - "files": [ - "config/packages/web_profiler.yaml", - "config/routes/web_profiler.yaml" - ] - }, - "twig/extra-bundle": { - "version": "v3.13.0" - } -} diff --git a/apps/api-legacy/templates/base.html.twig b/apps/api-legacy/templates/base.html.twig deleted file mode 100644 index 1069c14..0000000 --- a/apps/api-legacy/templates/base.html.twig +++ /dev/null @@ -1,16 +0,0 @@ - - - - - {% block title %}Welcome!{% endblock %} - - {% block stylesheets %} - {% endblock %} - - {% block javascripts %} - {% endblock %} - - - {% block body %}{% endblock %} - - diff --git a/apps/api-legacy/templates/emails/aggregator/source_crawled.html.twig b/apps/api-legacy/templates/emails/aggregator/source_crawled.html.twig deleted file mode 100644 index e57ecd8..0000000 --- a/apps/api-legacy/templates/emails/aggregator/source_crawled.html.twig +++ /dev/null @@ -1,5 +0,0 @@ -Hello There,

- -The source {{ source }} has been fetched and is now available for download.

- -performance : {{ event }} diff --git a/apps/api-legacy/templates/emails/aggregator/source_crawled.txt.twig b/apps/api-legacy/templates/emails/aggregator/source_crawled.txt.twig deleted file mode 100644 index 9b7b4ad..0000000 --- a/apps/api-legacy/templates/emails/aggregator/source_crawled.txt.twig +++ /dev/null @@ -1,5 +0,0 @@ -Hello There, - -The source {{ source }} has been fetched and is now available for download. - -performance : {{ event }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.html.twig b/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.html.twig deleted file mode 100644 index e268e62..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.html.twig +++ /dev/null @@ -1,2 +0,0 @@ -Votre compte a été confirmé avec succès. -Bienvenue sur {{ application.name }}. diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.txt.twig deleted file mode 100644 index e268e62..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_confirmed.txt.twig +++ /dev/null @@ -1,2 +0,0 @@ -Votre compte a été confirmé avec succès. -Bienvenue sur {{ application.name }}. diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_locked.html.twig b/apps/api-legacy/templates/emails/identity_and_access/account_locked.html.twig deleted file mode 100644 index 18b95d4..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_locked.html.twig +++ /dev/null @@ -1,5 +0,0 @@ -Après plusieurs tentatives infructueuses de connexion, votre compte a été bloqué pour des raisons de sécurité.

- -Utilisez le lien ci-dessous pour réinitialiser votre mot de passe et débloquer votre compte.

- -{{ url('identity_and_access_unlock_account', {'token': token}) }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_locked.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/account_locked.txt.twig deleted file mode 100644 index 45eb472..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_locked.txt.twig +++ /dev/null @@ -1,5 +0,0 @@ -Après plusieurs tentatives infructueuses de connexion, votre compte a été bloqué pour des raisons de sécurité. - -Utilisez le lien ci-dessous pour réinitialiser votre mot de passe et débloquer votre compte. - -{{ url('identity_and_access_unlock_account', {'token': token}) }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.html.twig b/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.html.twig deleted file mode 100644 index 1425553..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.html.twig +++ /dev/null @@ -1 +0,0 @@ -Votre compte {{ application.name }} a été déverrouillé avec succès. diff --git a/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.txt.twig deleted file mode 100644 index 1425553..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/account_unlocked.txt.twig +++ /dev/null @@ -1 +0,0 @@ -Votre compte {{ application.name }} a été déverrouillé avec succès. diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.html.twig b/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.html.twig deleted file mode 100644 index 3fe85b4..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.html.twig +++ /dev/null @@ -1,4 +0,0 @@ -Nous avons reçu une demande de réinitialisation de votre mot de passe {{ application.name }}.

- -Ce lien ne sera plus valide après **2 heure**, -{{ url('identity_and_access_reset_password', {token: token}) }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.txt.twig deleted file mode 100644 index ec8c819..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_forgotten.txt.twig +++ /dev/null @@ -1,4 +0,0 @@ -Nous avons reçu une demande de réinitialisation de votre mot de passe {{ application.name }}. - -Ce lien ne sera plus valide après **2 heure**, -{{ url('identity_and_access_reset_password', {token: token}) }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_reset.html.twig b/apps/api-legacy/templates/emails/identity_and_access/password_reset.html.twig deleted file mode 100644 index 359efb8..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_reset.html.twig +++ /dev/null @@ -1 +0,0 @@ -Ceci est une confirmation que le mot de passe de votre compte {{ application.name }} vient d'être réinitialisé. diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_reset.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/password_reset.txt.twig deleted file mode 100644 index 359efb8..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_reset.txt.twig +++ /dev/null @@ -1 +0,0 @@ -Ceci est une confirmation que le mot de passe de votre compte {{ application.name }} vient d'être réinitialisé. diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_updated.html.twig b/apps/api-legacy/templates/emails/identity_and_access/password_updated.html.twig deleted file mode 100644 index 0a01305..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_updated.html.twig +++ /dev/null @@ -1 +0,0 @@ -Ceci est une confirmation que le mot de passe de votre compte {{ application.name }} vient d'être mis à jour. diff --git a/apps/api-legacy/templates/emails/identity_and_access/password_updated.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/password_updated.txt.twig deleted file mode 100644 index 0a01305..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/password_updated.txt.twig +++ /dev/null @@ -1 +0,0 @@ -Ceci est une confirmation que le mot de passe de votre compte {{ application.name }} vient d'être mis à jour. diff --git a/apps/api-legacy/templates/emails/identity_and_access/user_registered.html.twig b/apps/api-legacy/templates/emails/identity_and_access/user_registered.html.twig deleted file mode 100644 index a444db6..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/user_registered.html.twig +++ /dev/null @@ -1,5 +0,0 @@ -Merci pour l'intérêt que vous portez à {{ application.name }}.

- -pour finaliser votre inscription, veuillez cliquer sur le lien ci-dessous :

- -{{ url('identity_and_access_confirm_account', {token: token}) }} diff --git a/apps/api-legacy/templates/emails/identity_and_access/user_registered.txt.twig b/apps/api-legacy/templates/emails/identity_and_access/user_registered.txt.twig deleted file mode 100644 index 5f0e0ae..0000000 --- a/apps/api-legacy/templates/emails/identity_and_access/user_registered.txt.twig +++ /dev/null @@ -1,5 +0,0 @@ -Merci pour l'intérêt que vous portez à {{ application.name }}. - -pour finaliser votre inscription, veuillez cliquer sur le lien ci-dessous : - -{{ url('identity_and_access_confirm_account', {token: token}) }} diff --git a/apps/api-legacy/tests/Behat/Context/AbstractContext.php b/apps/api-legacy/tests/Behat/Context/AbstractContext.php deleted file mode 100644 index cf19bf5..0000000 --- a/apps/api-legacy/tests/Behat/Context/AbstractContext.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class AbstractContext implements Context, ServiceSubscriberInterface -{ - use ServiceMethodsSubscriberTrait; - - #[\Override] - public static function getSubscribedServices(): array - { - return [CommandBus::class, QueryBus::class, SharedStorage::class]; - } -} diff --git a/apps/api-legacy/tests/Behat/Hook/DatabasePurger.php b/apps/api-legacy/tests/Behat/Hook/DatabasePurger.php deleted file mode 100644 index 7dc8800..0000000 --- a/apps/api-legacy/tests/Behat/Hook/DatabasePurger.php +++ /dev/null @@ -1,31 +0,0 @@ -entityManager->getConnection() - ->getConfiguration() - ->setMiddlewares([]); - - $purger = new ORMPurger($this->entityManager); - $purger->purge(); - - $this->entityManager->clear(); - } -} diff --git a/apps/api-legacy/tests/Behat/State/SharedStorage.php b/apps/api-legacy/tests/Behat/State/SharedStorage.php deleted file mode 100644 index bc1a209..0000000 --- a/apps/api-legacy/tests/Behat/State/SharedStorage.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -final class SharedStorage -{ - private array $storage = []; - - public function get(string $key): mixed - { - return $this->storage[$key] ?? null; - } - - public function set(string $key, mixed $value): void - { - $this->storage[$key] = $value; - } - - public function has(string $key): bool - { - return isset($this->storage[$key]); - } - - public function remove(string $key): void - { - if ($this->has($key)) { - unset($this->storage[$key]); - } - } -} diff --git a/apps/api-legacy/tests/Unit/SharedKernel/Domain/Model/ValueObject/DateRangeTest.php b/apps/api-legacy/tests/Unit/SharedKernel/Domain/Model/ValueObject/DateRangeTest.php deleted file mode 100644 index f67d99e..0000000 --- a/apps/api-legacy/tests/Unit/SharedKernel/Domain/Model/ValueObject/DateRangeTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -final class DateRangeTest extends TestCase -{ - public function testItShouldCreateDateRange(): void - { - $dateRange = DateRange::from( - '2021-10-01 00:00:00--2021-10-10 00:00:00', - 'Y-m-d H:i:s', - '--' - ); - - $this->assertEquals(1633046400, $dateRange->start); - $this->assertEquals(1633824000, $dateRange->end); - } - - public function testEndShouldBeGreaterThanStart(): void - { - $this->expectException(InvalidArgument::class); - DateRange::from('2021-10-10:2021-10-01'); - } -} diff --git a/apps/api-legacy/tests/bootstrap.php b/apps/api-legacy/tests/bootstrap.php deleted file mode 100644 index 8b7a9de..0000000 --- a/apps/api-legacy/tests/bootstrap.php +++ /dev/null @@ -1,11 +0,0 @@ -bootEnv(dirname(__DIR__) . '/.env'); -} diff --git a/apps/api-legacy/tests/object-manager.php b/apps/api-legacy/tests/object-manager.php deleted file mode 100644 index cdd4389..0000000 --- a/apps/api-legacy/tests/object-manager.php +++ /dev/null @@ -1,18 +0,0 @@ -bootEnv(__DIR__ . '/../.env'); - -$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); -$kernel->boot(); - -/** @var Doctrine\Bundle\DoctrineBundle\Registry $doctrine */ -$doctrine = $kernel->getContainer()->get('doctrine'); - -return $doctrine->getManager(); diff --git a/apps/api-legacy/translations/aggregator.fr.yaml b/apps/api-legacy/translations/aggregator.fr.yaml deleted file mode 100644 index cf37989..0000000 --- a/apps/api-legacy/translations/aggregator.fr.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Emails -aggregator.emails.source_crawled.subject: "[DRC News] source crawled successfully" - -# Exceptions -aggregator.exceptions.article_not_found: Désolé nous n'avons pas trouvé cet article dans nos enregistrements -aggregator.exceptions.duplicated_article: Cet article a déjà été enregistré -aggregator.exceptions.article_out_of_range: Article en déhors de l'intervalle de dates d'enregistrement -aggregator.exceptions.source_not_found: Désolé impossible d'obtenir des informations sur cette source diff --git a/apps/api-legacy/translations/feed_management.fr.yaml b/apps/api-legacy/translations/feed_management.fr.yaml deleted file mode 100644 index 35476f7..0000000 --- a/apps/api-legacy/translations/feed_management.fr.yaml +++ /dev/null @@ -1,12 +0,0 @@ - -# Exception -feed_management.exceptions.article_already_bookmarked: L'article a déjà été ajouté au signet -feed_management.exceptions.bookmarked_article_not_found: L'article n'a pas été trouvé dans le signet -feed_management.exceptions.bookmark_not_found: Le signet n'a pas été trouvé -feed_management.exceptions.cannot_add_article_to_bookmark: Vous n'avez pas la permission d'ajouter cet article au signet -feed_management.exceptions.cannot_delete_bookmark: Vous n'avez pas la permission de supprimer ce signet -feed_management.exceptions.cannot_update_bookmark: Vous n'avez pas la permission de mettre à jour ce signet -feed_management.exceptions.followed_source_not_found: La source suivie n'a pas été trouvée -feed_management.exceptions.source_already_followed: La source est déjà suivie -feed_management.exceptions.cannot_delete_comment: Vous n'avez pas la permission de supprimer ce commentaire -feed_management.exceptions.comment_not_found: Le commentaire n'a pas été trouvé diff --git a/apps/api-legacy/translations/identity_and_access.fr.yaml b/apps/api-legacy/translations/identity_and_access.fr.yaml deleted file mode 100644 index c047f72..0000000 --- a/apps/api-legacy/translations/identity_and_access.fr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Validations -identity_and_access.validations.password_must_match: Les deux mots de passe ne sont pas identiques ! -identity_and_access.validations.empty_role: Veuillez définir au moins un rôle -identity_and_access.validations.empty_username: Le nom d'utilisateur ne doit pas être vide -identity_and_access.validations.invalid_username_pattern: Le nom d'utilisateur ne peut contenir que des lettre et chiffre, (_) et (.), sans espace -identity_and_access.validations.long_username: Ce nom d'utilisateur est trop long (maximum 30 caractères) -identity_and_access.validations.short_username: Ce nom d'utilisateur est trop court (maximum 5 caractères) - -# Exceptions -identity_and_access.exceptions.user_not_found: Désolé nous n'avons pas trouvé d'utilisateur avec ces informations. -identity_and_access.exceptions.invalid_current_password: Le mot de passe actuel est incorrecte. -identity_and_access.exceptions.email_already_used: Impossible d'utiliser cette address email, essayez avec une autre. -identity_and_access.exceptions.invalid_verification_token: Désolé le jeton de sécurité n'est pas valide ! -identity_and_access.exceptions.password_already_defined: Désolé un mot de passe a déjà été défini ! -identity_and_access.exceptions.account_is_locked: Pour des raisons de sécurité, votre compte a été verrouillé. Suivez les instructions envoyées à votre adresse email pour le déverrouiller. -identity_and_access.exceptions.account_not_confirmed: Votre compte n'est pas encore confirmé. Veuillez suivre les instructions envoyées à votre adresse email pour le confirmer. -Invalid credentials.: Identifiants incorrects. -identity_and_access.exceptions.permission_not_granted: Impossible de continuer, {reason}. - -# Emails -identity_and_access.emails.subjects.password_created: "[DRC News] Connectez-vous à votre compte avec ce mot de passe par défaut" -identity_and_access.emails.subjects.password_forgotten: "[DRC News] Instruction de réinitialisation de mot de passe" -identity_and_access.emails.subjects.password_reset: "[DRC News] Votre mot de passe a été mis à jour" -identity_and_access.emails.subjects.password_updated: "[DRC News] Votre mot de passe a été mis à jour" -identity_and_access.emails.subjects.account_confirmed: "[DRC News] Votre compte a été confirmé" -identity_and_access.emails.subjects.account_locked: "[DRC News] Votre compte a été verrouillé" -identity_and_access.emails.subjects.account_unlocked: "[DRC News] Votre compte a été déverrouillé" -identity_and_access.emails.subjects.confirmation_requested: "[DRC News] Instruction de confirmation de compte" -identity_and_access.emails.subjects.login_profile_changed: "[DRC News] Nouvelle connexion à votre compte" -identity_and_access.emails.subjects.email_updated: "[DRC News] Votre adresse email a été mise à jour" diff --git a/apps/api-legacy/translations/messages.fr.yaml b/apps/api-legacy/translations/messages.fr.yaml deleted file mode 100644 index 96a4a7a..0000000 --- a/apps/api-legacy/translations/messages.fr.yaml +++ /dev/null @@ -1,4 +0,0 @@ -generic.form_error: Certains champs sont invalides -generic.error: Désolé une erreur est survenue, veuillez réessayer -generic.success: Action effectuée avec succès ! -generic.invalid_argument: Désolé certaines données fournis sont invalides. diff --git a/apps/api-legacy/translations/shared_kernel.fr.yaml b/apps/api-legacy/translations/shared_kernel.fr.yaml deleted file mode 100644 index 4ad30d9..0000000 --- a/apps/api-legacy/translations/shared_kernel.fr.yaml +++ /dev/null @@ -1,3 +0,0 @@ -# Exceptions -shared_kernel.exceptions.invalid_email_address: Cet adresse email n'est pas valide ! -shared_kernel.exceptions.invalid_argument: Les informations fournis sont invalides ! diff --git a/apps/api-legacy/translations/validators.fr.yaml b/apps/api-legacy/translations/validators.fr.yaml deleted file mode 100644 index 557812e..0000000 --- a/apps/api-legacy/translations/validators.fr.yaml +++ /dev/null @@ -1 +0,0 @@ -identity_and_access.exceptions.passwords_do_not_match: Les mots de passe ne correspondent pas. \ No newline at end of file diff --git a/apps/api/.env b/apps/api/.env index 5c75532..bc898b8 100644 --- a/apps/api/.env +++ b/apps/api/.env @@ -3,5 +3,5 @@ BASANGO_API_HOST=localhost BASANGO_API_PORT=3080 BASANGO_API_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000 BASANGO_API_KEY=your_api_key_here -BASANGO_CRAWLER_KEY=dev +BASANGO_CRAWLER_TOKEN=dev BASANGO_JWT_SECRET=your_jwt_secret_here diff --git a/apps/api/package.json b/apps/api/package.json index e14d789..4ad01b8 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -11,7 +11,6 @@ "ai": "^5.0.89", "camelcase-keys": "^10.0.1", "date-fns": "catalog:", - "hono": "^4.10.4", "hono-rate-limiter": "^0.4.2", "jose": "^6.1.0", "zod": "catalog:", diff --git a/apps/api/src/config.ts b/apps/api/src/config.ts index 520f923..d57128b 100644 --- a/apps/api/src/config.ts +++ b/apps/api/src/config.ts @@ -27,7 +27,7 @@ export const { env, config } = defineConfig({ "BASANGO_API_PORT", "BASANGO_API_ALLOWED_ORIGINS", "BASANGO_API_KEY", - "BASANGO_CRAWLER_KEY", + "BASANGO_CRAWLER_TOKEN", "BASANGO_JWT_SECRET", ], path: path.join(PROJECT_DIR, ".env"), diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 6cc9ac9..53f594a 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -2,15 +2,28 @@ import { trpcServer } from "@hono/trpc-server"; import { OpenAPIHono } from "@hono/zod-openapi"; import { Scalar } from "@scalar/hono-api-reference"; import { cors } from "hono/cors"; +import { logger } from "hono/logger"; import { secureHeaders } from "hono/secure-headers"; -import { config, env } from "@/config"; -import { routers } from "@/rest/routers"; -import { createTRPCContext } from "@/trpc/init"; -import { appRouter } from "@/trpc/routers/_app"; +import { config, env } from "#api/config"; +import { routers } from "#api/rest/routers"; +import { createTRPCContext } from "#api/trpc/init"; +import { appRouter } from "#api/trpc/routers/_app"; const app = new OpenAPIHono(); +app.use(async (c, next) => { + const data = await c.req.json(); + + console.log("Incoming Request:", { + data: data, + headers: c.req.header, + method: c.req.method, + url: c.req.url, + }); + + return next(); +}); app.use(secureHeaders()); app.use( diff --git a/apps/api/src/rest/middlewares/crawler.ts b/apps/api/src/rest/middlewares/crawler.ts index 43e9208..e8551ee 100644 --- a/apps/api/src/rest/middlewares/crawler.ts +++ b/apps/api/src/rest/middlewares/crawler.ts @@ -1,7 +1,7 @@ import type { MiddlewareHandler } from "hono"; import { HTTPException } from "hono/http-exception"; -import { env } from "@/config"; +import { env } from "#api/config"; export const withCrawlerAuth: MiddlewareHandler = async (c, next) => { const token = c.req.header("Authorization"); @@ -10,7 +10,7 @@ export const withCrawlerAuth: MiddlewareHandler = async (c, next) => { throw new HTTPException(401, { message: "Authorization header required" }); } - if (token !== env("BASANGO_CRAWLER_KEY")) { + if (token !== env("BASANGO_CRAWLER_TOKEN")) { throw new HTTPException(403, { message: "Invalid token" }); } diff --git a/apps/api/src/rest/middlewares/scope.ts b/apps/api/src/rest/middlewares/scope.ts index ea07677..0afa600 100644 --- a/apps/api/src/rest/middlewares/scope.ts +++ b/apps/api/src/rest/middlewares/scope.ts @@ -1,6 +1,6 @@ import type { MiddlewareHandler } from "hono"; -import type { Scope } from "@/utils/scopes"; +import type { Scope } from "#api/utils/scopes"; export const withRequiredScope = (...requiredScopes: Scope[]): MiddlewareHandler => { return async (c, next) => { diff --git a/apps/api/src/rest/routers/articles.ts b/apps/api/src/rest/routers/articles.ts index 030210d..33b817d 100644 --- a/apps/api/src/rest/routers/articles.ts +++ b/apps/api/src/rest/routers/articles.ts @@ -1,10 +1,11 @@ import { createArticle } from "@basango/db/queries"; import { OpenAPIHono, createRoute } from "@hono/zod-openapi"; -import { withCrawlerAuth } from "@/rest/middlewares/crawler"; -import type { Context } from "@/rest/types"; -import { createArticleResponseSchema, createArticleSchema } from "@/schemas/articles"; -import { validateResponse } from "@/utils/response"; +import { withCrawlerAuth } from "#api/rest/middlewares/crawler"; +import { withDatabase } from "#api/rest/middlewares/db"; +import type { Context } from "#api/rest/types"; +import { createArticleResponseSchema, createArticleSchema } from "#api/schemas/articles"; +import { validateResponse } from "#api/utils/response"; const app = new OpenAPIHono(); @@ -12,7 +13,7 @@ app.openapi( createRoute({ description: "Store a new crawled article in the database.", method: "post", - middleware: [withCrawlerAuth], + middleware: [withCrawlerAuth, withDatabase], operationId: "CreateArticle", path: "/", request: { @@ -40,8 +41,8 @@ app.openapi( }), async (c) => { const db = c.get("db"); - const body = c.req.valid("json"); - const result = await createArticle(db, { ...body }); + const input = c.req.valid("json"); + const result = await createArticle(db, input); return c.json( validateResponse(result, createArticleResponseSchema) as { id: string; sourceId: string }, diff --git a/apps/api/src/rest/routers/index.ts b/apps/api/src/rest/routers/index.ts index 9cb2f41..8ce8050 100644 --- a/apps/api/src/rest/routers/index.ts +++ b/apps/api/src/rest/routers/index.ts @@ -1,8 +1,8 @@ import { OpenAPIHono } from "@hono/zod-openapi"; -import { articlesRouter } from "@/rest/routers/articles"; +import { articlesRouter } from "#api/rest/routers/articles"; -const routers = new OpenAPIHono(); +const routers: OpenAPIHono = new OpenAPIHono(); routers.route("/articles", articlesRouter); diff --git a/apps/api/src/schemas/articles.ts b/apps/api/src/schemas/articles.ts index 4af58b3..651feea 100644 --- a/apps/api/src/schemas/articles.ts +++ b/apps/api/src/schemas/articles.ts @@ -1,38 +1,5 @@ import { z } from "@hono/zod-openapi"; -const sentimentSchema = z.enum(["positive", "neutral", "negative"]).openapi({ - default: "neutral", - description: "The sentiment of the article content.", -}); - -const readingTimeSchema = z.number().min(1).openapi({ - description: "The estimated reading time of the article in minutes.", - example: 5, -}); - -const tokenStatisticsSchema = z.object({ - body: z.number().min(0).openapi({ - description: "The number of tokens in the article body.", - example: 350, - }), - categories: z.number().min(0).openapi({ - description: "The number of tokens in the article categories.", - example: 25, - }), - excerpt: z.number().min(0).openapi({ - description: "The number of tokens in the article excerpt.", - example: 50, - }), - title: z.number().min(0).openapi({ - description: "The number of tokens in the article title.", - example: 15, - }), - total: z.number().min(0).openapi({ - description: "The total number of tokens in the article.", - example: 440, - }), -}); - const metadataSchema = z.object({ description: z.string().optional().openapi({ description: "A brief description or summary of the article.", @@ -54,10 +21,14 @@ export const createArticleSchema = z description: "The main content of the article.", example: "This is the body of the article...", }), - categories: z.array(z.string()).openapi({ - description: "The categories or tags associated with the article.", - example: ["Technology", "AI"], - }), + categories: z + .array(z.string()) + .openapi({ + description: "The categories or tags associated with the article.", + example: ["Technology", "AI"], + }) + .optional() + .default([]), hash: z.string().min(1).openapi({ description: "The unique hash of the article link.", example: "d41d8cd98f00b204e9800998ecf8427e", @@ -71,17 +42,14 @@ export const createArticleSchema = z description: "The publication date of the article.", example: "2023-01-01T00:00:00Z", }), - readingTime: readingTimeSchema.optional(), - sentiment: sentimentSchema.optional().optional().default("neutral"), sourceId: z.string().openapi({ description: "The unique identifier of the source from which the article was crawled.", - example: "source-123", + example: "radiookapi.net", }), title: z.string().min(1).openapi({ description: "The title of the article.", example: "The Rise of AI", }), - tokenStatistics: tokenStatisticsSchema.optional(), }) .openapi("CreateArticle"); diff --git a/apps/api/src/trpc/init.ts b/apps/api/src/trpc/init.ts index 3858361..61a7b44 100644 --- a/apps/api/src/trpc/init.ts +++ b/apps/api/src/trpc/init.ts @@ -3,10 +3,10 @@ import { initTRPC } from "@trpc/server"; import type { Context } from "hono"; import superjson from "superjson"; -import { withAuthentication } from "@/trpc/middlewares/auth"; -import { withDatabase } from "@/trpc/middlewares/db"; -import { Session, verifyAccessToken } from "@/utils/auth"; -import { getGeoContext } from "@/utils/geo"; +import { withAuthentication } from "#api/trpc/middlewares/auth"; +import { withDatabase } from "#api/trpc/middlewares/db"; +import { Session, verifyAccessToken } from "#api/utils/auth"; +import { getGeoContext } from "#api/utils/geo"; type TRPCContext = { session: Session | null; diff --git a/apps/api/src/trpc/middlewares/auth.ts b/apps/api/src/trpc/middlewares/auth.ts index 45bb854..bcb3187 100644 --- a/apps/api/src/trpc/middlewares/auth.ts +++ b/apps/api/src/trpc/middlewares/auth.ts @@ -2,7 +2,7 @@ import type { Database } from "@basango/db/client"; // import { TRPCError } from "@trpc/server"; -import type { Session } from "@/utils/auth"; +import type { Session } from "#api/utils/auth"; export const withAuthentication = async (opts: { ctx: { diff --git a/apps/api/src/trpc/middlewares/db.ts b/apps/api/src/trpc/middlewares/db.ts index 0405702..46047d9 100644 --- a/apps/api/src/trpc/middlewares/db.ts +++ b/apps/api/src/trpc/middlewares/db.ts @@ -1,6 +1,6 @@ import { type Database, db } from "@basango/db/client"; -import type { Session } from "@/utils/auth"; +import type { Session } from "#api/utils/auth"; export const withDatabase = async (opts: { ctx: { @@ -17,7 +17,5 @@ export const withDatabase = async (opts: { const { ctx, next } = opts; ctx.db = db; - const result = await next({ ctx }); - - return result; + return await next({ ctx }); }; diff --git a/apps/api/src/trpc/routers/_app.ts b/apps/api/src/trpc/routers/_app.ts index 3aa851d..d65a41e 100644 --- a/apps/api/src/trpc/routers/_app.ts +++ b/apps/api/src/trpc/routers/_app.ts @@ -1,13 +1,14 @@ import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server"; -import { createTRPCRouter } from "@/trpc/init"; -import { sourcesRouter } from "@/trpc/routers/sources"; +import { createTRPCRouter } from "#api/trpc/init"; +import { articlesRouter } from "#api/trpc/routers/articles"; +import { sourcesRouter } from "#api/trpc/routers/sources"; export const appRouter = createTRPCRouter({ + articles: articlesRouter, sources: sourcesRouter, }); -// export type definition of API export type AppRouter = typeof appRouter; export type RouterOutputs = inferRouterOutputs; export type RouterInputs = inferRouterInputs; diff --git a/apps/api/src/trpc/routers/articles.ts b/apps/api/src/trpc/routers/articles.ts new file mode 100644 index 0000000..05e0e00 --- /dev/null +++ b/apps/api/src/trpc/routers/articles.ts @@ -0,0 +1,10 @@ +import { createArticle } from "@basango/db/queries"; + +import { createArticleSchema } from "#api/schemas/articles"; +import { createTRPCRouter, protectedProcedure } from "#api/trpc/init"; + +export const articlesRouter = createTRPCRouter({ + create: protectedProcedure.input(createArticleSchema).mutation(async ({ ctx, input }) => { + return createArticle(ctx.db, input); + }), +}); diff --git a/apps/api/src/trpc/routers/sources.ts b/apps/api/src/trpc/routers/sources.ts index 1adc07f..90c5326 100644 --- a/apps/api/src/trpc/routers/sources.ts +++ b/apps/api/src/trpc/routers/sources.ts @@ -1,11 +1,18 @@ -import { createSource, getSourceById, getSources, updateSource } from "@basango/db/queries"; +import { + createSource, + getSourceById, + getSourceCategoryShares, + getSourcePublicationGraph, + getSources, + updateSource, +} from "@basango/db/queries"; -import { createSourceSchema, getSourceSchema, updateSourceSchema } from "@/schemas/sources"; -import { createTRPCRouter, protectedProcedure } from "@/trpc/init"; +import { createSourceSchema, getSourceSchema, updateSourceSchema } from "#api/schemas/sources"; +import { createTRPCRouter, protectedProcedure } from "#api/trpc/init"; export const sourcesRouter = createTRPCRouter({ create: protectedProcedure.input(createSourceSchema).mutation(async ({ ctx, input }) => { - return createSource(ctx.db, { ...input }); + return createSource(ctx.db, input); }), get: protectedProcedure.query(async ({ ctx }) => getSources(ctx.db)), @@ -14,7 +21,15 @@ export const sourcesRouter = createTRPCRouter({ return getSourceById(ctx.db, input.id); }), + getCategoryShares: protectedProcedure.input(getSourceSchema).query(async ({ ctx, input }) => { + return getSourceCategoryShares(ctx.db, input.id); + }), + + getPublicationGraph: protectedProcedure.input(getSourceSchema).query(async ({ ctx, input }) => { + return getSourcePublicationGraph(ctx.db, input.id); + }), + update: protectedProcedure.input(updateSourceSchema).mutation(async ({ ctx, input }) => { - return updateSource(ctx.db, { ...input }); + return updateSource(ctx.db, input); }), }); diff --git a/apps/api/src/utils/auth.ts b/apps/api/src/utils/auth.ts index 902b296..d55c6a8 100644 --- a/apps/api/src/utils/auth.ts +++ b/apps/api/src/utils/auth.ts @@ -1,6 +1,6 @@ import { type JWTPayload, jwtVerify } from "jose"; -import { env } from "@/config"; +import { env } from "#api/config"; export type Session = { user: { diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index c56a57a..58bae02 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -1,11 +1,14 @@ { "compilerOptions": { "baseUrl": ".", + "composite": true, + "incremental": true, "paths": { - "@/*": ["./src/*", "../../packages/db/src/*"] + "@basango/db": ["../../packages/db/src/*"], + "#api/*": ["./src/*"], + "#db/*": ["../../packages/db/src/*"] } }, "extends": "@basango/tsconfig/base.json", - "include": ["src"], - "references": [] + "include": ["src"] } diff --git a/apps/crawler/.env b/apps/crawler/.env index b13fcc1..e69875d 100644 --- a/apps/crawler/.env +++ b/apps/crawler/.env @@ -17,4 +17,5 @@ BASANGO_CRAWLER_ASYNC_QUEUE_LISTING="listing" BASANGO_CRAWLER_ASYNC_QUEUE_DETAILS="details" BASANGO_CRAWLER_ASYNC_QUEUE_PROCESSING="processing" -BASANGO_CRAWLER_BACKEND_API_ENDPOINT="http://localhost:3000/api/aggregator/articles?token=dev" +BASANGO_CRAWLER_TOKEN="dev" +BASANGO_CRAWLER_BACKEND_API_ENDPOINT="http://localhost:3080/articles" diff --git a/apps/crawler/package.json b/apps/crawler/package.json index b51da94..6f56b14 100644 --- a/apps/crawler/package.json +++ b/apps/crawler/package.json @@ -6,7 +6,6 @@ "date-fns": "catalog:", "ioredis": "^5.8.2", "node-html-parser": "^7.0.1", - "tiktoken": "^1.0.22", "turndown": "^7.2.2", "zod": "catalog:" }, @@ -19,8 +18,10 @@ "scripts": { "clean": "rm -rf .turbo node_modules", "crawler:async": "bun run src/scripts/queue.ts", + "crawler:push": "bun run src/scripts/sync.ts", "crawler:sync": "bun run src/scripts/crawl.ts", "crawler:worker": "bun run src/scripts/worker.ts", + "dev": "bun run src/scripts/worker.ts", "test": "vitest --run", "typecheck": "tsc --noEmit" }, diff --git a/apps/crawler/src/config.ts b/apps/crawler/src/config.ts index 83ab3f0..a94969b 100644 --- a/apps/crawler/src/config.ts +++ b/apps/crawler/src/config.ts @@ -9,7 +9,7 @@ import { PageRangeSchema, UpdateDirectionSchema, WordPressSourceConfigSchema, -} from "@/schema"; +} from "#crawler/schema"; export const PROJECT_DIR = path.resolve(__dirname, "../"); diff --git a/apps/crawler/src/http/http-client.ts b/apps/crawler/src/http/http-client.ts index 8ecd2c5..d97c37d 100644 --- a/apps/crawler/src/http/http-client.ts +++ b/apps/crawler/src/http/http-client.ts @@ -1,12 +1,12 @@ import { setTimeout as delay } from "node:timers/promises"; -import { FetchClientConfig } from "@/config"; +import { FetchClientConfig } from "#crawler/config"; import { DEFAULT_RETRY_AFTER_HEADER, DEFAULT_USER_AGENT, TRANSIENT_HTTP_STATUSES, -} from "@/constants"; -import { UserAgents } from "@/http/user-agent"; +} from "#crawler/constants"; +import { UserAgents } from "#crawler/http/user-agent"; export type HttpHeaders = Record; export type HttpParams = Record; diff --git a/apps/crawler/src/http/open-graph.ts b/apps/crawler/src/http/open-graph.ts index f6acf69..4dbe018 100644 --- a/apps/crawler/src/http/open-graph.ts +++ b/apps/crawler/src/http/open-graph.ts @@ -1,10 +1,10 @@ import { parse } from "node-html-parser"; -import { config } from "@/config"; -import { OPEN_GRAPH_USER_AGENT } from "@/constants"; -import { SyncHttpClient } from "@/http/http-client"; -import { UserAgents } from "@/http/user-agent"; -import { ArticleMetadata } from "@/schema"; +import { config } from "#crawler/config"; +import { OPEN_GRAPH_USER_AGENT } from "#crawler/constants"; +import { SyncHttpClient } from "#crawler/http/http-client"; +import { UserAgents } from "#crawler/http/user-agent"; +import { ArticleMetadata } from "#crawler/schema"; /** * Picks the first non-empty value from the provided array. diff --git a/apps/crawler/src/http/user-agent.ts b/apps/crawler/src/http/user-agent.ts index 09a4c34..6b66037 100644 --- a/apps/crawler/src/http/user-agent.ts +++ b/apps/crawler/src/http/user-agent.ts @@ -1,4 +1,4 @@ -import { DEFAULT_USER_AGENT, OPEN_GRAPH_USER_AGENT } from "@/constants"; +import { DEFAULT_USER_AGENT, OPEN_GRAPH_USER_AGENT } from "#crawler/constants"; /** * User agent provider with optional rotation. diff --git a/apps/crawler/src/process/async/handlers.ts b/apps/crawler/src/process/async/handlers.ts index cda017b..a9ed9ad 100644 --- a/apps/crawler/src/process/async/handlers.ts +++ b/apps/crawler/src/process/async/handlers.ts @@ -1,19 +1,24 @@ import { logger } from "@basango/logger"; -import { config, env } from "@/config"; -import { UnsupportedSourceKindError } from "@/errors"; -import { SyncHttpClient } from "@/http/http-client"; -import { QueueManager, createQueueManager } from "@/process/async/queue"; +import { config, env } from "#crawler/config"; +import { UnsupportedSourceKindError } from "#crawler/errors"; +import { SyncHttpClient } from "#crawler/http/http-client"; +import { QueueManager, createQueueManager } from "#crawler/process/async/queue"; import { DetailsTaskPayload, ListingTaskPayload, ProcessingTaskPayload, -} from "@/process/async/schemas"; -import { createPersistors, resolveCrawlerConfig } from "@/process/crawler"; -import { HtmlCrawler } from "@/process/parsers/html"; -import { WordPressCrawler } from "@/process/parsers/wordpress"; -import { Article, HtmlSourceConfig, SourceKindSchema, WordPressSourceConfig } from "@/schema"; -import { createDateRange, formatDateRange, formatPageRange, resolveSourceConfig } from "@/utils"; +} from "#crawler/process/async/schemas"; +import { createPersistors, resolveCrawlerConfig } from "#crawler/process/crawler"; +import { HtmlCrawler } from "#crawler/process/parsers/html"; +import { WordPressCrawler } from "#crawler/process/parsers/wordpress"; +import { Article, HtmlSourceConfig, WordPressSourceConfig } from "#crawler/schema"; +import { + createDateRange, + formatDateRange, + formatPageRange, + resolveSourceConfig, +} from "#crawler/utils"; export const collectHtmlListing = async ( payload: ListingTaskPayload, @@ -107,7 +112,7 @@ export const collectArticle = async ( }); const persistors = createPersistors(source); - if (source.sourceKind === SourceKindSchema.enum.html) { + if (source.sourceKind === "html") { const crawler = new HtmlCrawler(settings, { persistors }); const html = await crawler.crawl(payload.url); @@ -118,7 +123,7 @@ export const collectArticle = async ( } as ProcessingTaskPayload); } - if (source.sourceKind === SourceKindSchema.enum.wordpress) { + if (source.sourceKind === "wordpress") { const crawler = new WordPressCrawler(settings, { persistors }); const article = await crawler.fetchOne(payload.data ?? {}, settings.dateRange); @@ -134,11 +139,24 @@ export const collectArticle = async ( export const forwardForProcessing = async (payload: ProcessingTaskPayload): Promise
=> { logger.info({ article: payload.article.title }, "Ready for downstream processing"); - const client = new SyncHttpClient(config.fetch.client); - const endpoint = env("BASANGO_CRAWLER_BACKEND_API_ENDPOINT"); + try { + logger.info({ article: payload.article.title }, "Forwarding article to API"); - await client.post(endpoint, { json: payload.article }); - logger.info({ article: payload.article.title }, "Forwarded article to API"); + const client = new SyncHttpClient(config.fetch.client); + const response = await client.post(env("BASANGO_CRAWLER_BACKEND_API_ENDPOINT"), { + headers: { + Authorization: `${env("BASANGO_CRAWLER_TOKEN")}`, + }, + json: payload.article, + }); + + if (response.ok) { + const data = await response.json(); + logger.info({ ...data }, "Article successfully forwarded to API"); + } + } catch (error) { + logger.error({ error }, "Failed to forward article to API"); + } return payload.article; }; diff --git a/apps/crawler/src/process/async/queue.ts b/apps/crawler/src/process/async/queue.ts index 9660522..9d8afaf 100644 --- a/apps/crawler/src/process/async/queue.ts +++ b/apps/crawler/src/process/async/queue.ts @@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto"; import { JobsOptions, Queue, QueueOptions } from "bullmq"; import IORedis from "ioredis"; -import { FetchAsyncConfig, config } from "@/config"; +import { FetchAsyncConfig, config } from "#crawler/config"; import { DetailsTaskPayload, DetailsTaskPayloadSchema, @@ -11,8 +11,8 @@ import { ListingTaskPayloadSchema, ProcessingTaskPayload, ProcessingTaskPayloadSchema, -} from "@/process/async/schemas"; -import { parseRedisUrl } from "@/utils"; +} from "#crawler/process/async/schemas"; +import { parseRedisUrl } from "#crawler/utils"; export interface QueueBackend { add: (name: string, data: T, opts?: JobsOptions) => Promise<{ id: string }>; diff --git a/apps/crawler/src/process/async/schemas.ts b/apps/crawler/src/process/async/schemas.ts index e62fdde..356fb7c 100644 --- a/apps/crawler/src/process/async/schemas.ts +++ b/apps/crawler/src/process/async/schemas.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { ArticleSchema, DateRangeSchema, PageRangeSchema } from "@/schema"; +import { ArticleSchema, DateRangeSchema, PageRangeSchema } from "#crawler/schema"; export const ListingTaskPayloadSchema = z.object({ category: z.string().optional(), diff --git a/apps/crawler/src/process/async/tasks.ts b/apps/crawler/src/process/async/tasks.ts index 188509a..2781754 100644 --- a/apps/crawler/src/process/async/tasks.ts +++ b/apps/crawler/src/process/async/tasks.ts @@ -1,13 +1,13 @@ import { logger } from "@basango/logger"; -import * as handlers from "@/process/async/handlers"; -import { createQueueManager } from "@/process/async/queue"; +import * as handlers from "#crawler/process/async/handlers"; +import { createQueueManager } from "#crawler/process/async/queue"; import { DetailsTaskPayloadSchema, ListingTaskPayloadSchema, ProcessingTaskPayloadSchema, -} from "@/process/async/schemas"; -import { CrawlingOptions } from "@/process/crawler"; +} from "#crawler/process/async/schemas"; +import { CrawlingOptions } from "#crawler/process/crawler"; export const collectListing = async (payload: unknown): Promise => { const data = ListingTaskPayloadSchema.parse(payload); diff --git a/apps/crawler/src/process/async/worker.ts b/apps/crawler/src/process/async/worker.ts index a80381f..85155db 100644 --- a/apps/crawler/src/process/async/worker.ts +++ b/apps/crawler/src/process/async/worker.ts @@ -1,8 +1,8 @@ import { QueueEvents, Worker } from "bullmq"; import IORedis from "ioredis"; -import { QueueFactory, QueueManager } from "@/process/async/queue"; -import { collectArticle, collectListing, forwardForProcessing } from "@/process/async/tasks"; +import { QueueFactory, QueueManager } from "#crawler/process/async/queue"; +import { collectArticle, collectListing, forwardForProcessing } from "#crawler/process/async/tasks"; export interface WorkerOptions { queueNames?: string[]; diff --git a/apps/crawler/src/process/crawler.ts b/apps/crawler/src/process/crawler.ts index 2f4f13d..a2ea2dd 100644 --- a/apps/crawler/src/process/crawler.ts +++ b/apps/crawler/src/process/crawler.ts @@ -1,9 +1,9 @@ import logger from "@basango/logger"; -import { FetchCrawlerConfig, config } from "@/config"; -import { JsonlPersistor, Persistor } from "@/process/persistence"; -import { AnySourceConfig } from "@/schema"; -import { createDateRange, createPageRange } from "@/utils"; +import { FetchCrawlerConfig, config } from "#crawler/config"; +import { JsonlPersistor, Persistor } from "#crawler/process/persistence"; +import { AnySourceConfig } from "#crawler/schema"; +import { createDateRange, createPageRange } from "#crawler/utils"; export interface CrawlingOptions { sourceId: string; diff --git a/apps/crawler/src/process/parsers/base.ts b/apps/crawler/src/process/parsers/base.ts index d69ca49..5a7a5cd 100644 --- a/apps/crawler/src/process/parsers/base.ts +++ b/apps/crawler/src/process/parsers/base.ts @@ -1,10 +1,10 @@ import { HTMLElement, parse as parseHtml } from "node-html-parser"; -import { FetchCrawlerConfig, config } from "@/config"; -import { SyncHttpClient } from "@/http/http-client"; -import { OpenGraph } from "@/http/open-graph"; -import type { Persistor } from "@/process/persistence"; -import { AnySourceConfig, Article } from "@/schema"; +import { FetchCrawlerConfig, config } from "#crawler/config"; +import { SyncHttpClient } from "#crawler/http/http-client"; +import { OpenGraph } from "#crawler/http/open-graph"; +import type { Persistor } from "#crawler/process/persistence"; +import { AnySourceConfig, Article } from "#crawler/schema"; export interface CrawlerOptions { persistors?: Persistor[]; diff --git a/apps/crawler/src/process/parsers/html.ts b/apps/crawler/src/process/parsers/html.ts index 40eeab6..8504c2d 100644 --- a/apps/crawler/src/process/parsers/html.ts +++ b/apps/crawler/src/process/parsers/html.ts @@ -3,17 +3,17 @@ import { getUnixTime, isMatch as isDateMatch, parse as parseDateFns } from "date import { HTMLElement } from "node-html-parser"; import TurndownService from "turndown"; -import { FetchCrawlerConfig } from "@/config"; +import { FetchCrawlerConfig } from "#crawler/config"; import { ArticleOutOfDateRangeError, InvalidArticleError, InvalidSourceSelectorsError, UnsupportedSourceKindError, -} from "@/errors"; -import { BaseCrawler } from "@/process/parsers/base"; -import { Persistor, persist } from "@/process/persistence"; -import { Article, DateRange, HtmlSourceConfig } from "@/schema"; -import { createAbsoluteUrl, isTimestampInRange } from "@/utils"; +} from "#crawler/errors"; +import { BaseCrawler } from "#crawler/process/parsers/base"; +import { Persistor, persist } from "#crawler/process/persistence"; +import { Article, DateRange, HtmlSourceConfig } from "#crawler/schema"; +import { createAbsoluteUrl, isTimestampInRange } from "#crawler/utils"; const md = new TurndownService({ bulletListMarker: "-", @@ -148,8 +148,8 @@ export class HtmlCrawler extends BaseCrawler { body, categories, link, - source: this.source.sourceId, - timestamp, + publishedAt: new Date(timestamp * 1000), + sourceId: this.source.sourceId, title, }, link, diff --git a/apps/crawler/src/process/parsers/wordpress.ts b/apps/crawler/src/process/parsers/wordpress.ts index 9d3dab8..54f0391 100644 --- a/apps/crawler/src/process/parsers/wordpress.ts +++ b/apps/crawler/src/process/parsers/wordpress.ts @@ -1,16 +1,16 @@ import { logger } from "@basango/logger"; import TurndownService from "turndown"; -import { FetchCrawlerConfig } from "@/config"; +import { FetchCrawlerConfig } from "#crawler/config"; import { ArticleOutOfDateRangeError, InvalidArticleError, UnsupportedSourceKindError, -} from "@/errors"; -import { BaseCrawler } from "@/process/parsers/base"; -import { Persistor, persist } from "@/process/persistence"; -import { Article, DateRange, PageRange, WordPressSourceConfig } from "@/schema"; -import { isTimestampInRange } from "@/utils"; +} from "#crawler/errors"; +import { BaseCrawler } from "#crawler/process/parsers/base"; +import { Persistor, persist } from "#crawler/process/persistence"; +import { Article, DateRange, PageRange, WordPressSourceConfig } from "#crawler/schema"; +import { isTimestampInRange } from "#crawler/utils"; const md = new TurndownService({ bulletListMarker: "-", @@ -148,8 +148,8 @@ export class WordPressCrawler extends BaseCrawler { body, categories, link, - source: this.source.sourceId, - timestamp, + publishedAt: new Date(timestamp * 1000), + sourceId: this.source.sourceId, title, }, link, diff --git a/apps/crawler/src/process/persistence.ts b/apps/crawler/src/process/persistence.ts index 466e48a..43e47ed 100644 --- a/apps/crawler/src/process/persistence.ts +++ b/apps/crawler/src/process/persistence.ts @@ -4,8 +4,7 @@ import path from "node:path"; import { md5 } from "@basango/encryption"; import logger from "@basango/logger"; -import { Article } from "@/schema"; -import { countTokens } from "@/utils"; +import { Article } from "#crawler/schema"; export interface Persistor { persist(record: Article): Promise | void; @@ -47,12 +46,6 @@ export const persist = async (payload: Article, persistors: Persistor[]): Promis const article = { ...data, hash: md5(data.link), - tokenStatistics: { - body: countTokens(data.body), - categories: countTokens(data.categories.join(",")), - excerpt: countTokens(data.body.substring(0, 200)), - title: countTokens(data.title), - }, } as Article; for (const persistor of persistors) { diff --git a/apps/crawler/src/process/sync/tasks.ts b/apps/crawler/src/process/sync/tasks.ts index 38b5380..63e6088 100644 --- a/apps/crawler/src/process/sync/tasks.ts +++ b/apps/crawler/src/process/sync/tasks.ts @@ -5,10 +5,10 @@ import { closePersistors, createPersistors, resolveCrawlerConfig, -} from "@/process/crawler"; -import { HtmlCrawler } from "@/process/parsers/html"; -import { WordPressCrawler } from "@/process/parsers/wordpress"; -import { resolveSourceConfig } from "@/utils"; +} from "#crawler/process/crawler"; +import { HtmlCrawler } from "#crawler/process/parsers/html"; +import { WordPressCrawler } from "#crawler/process/parsers/wordpress"; +import { resolveSourceConfig } from "#crawler/utils"; export const runSyncCrawl = async (options: CrawlingOptions): Promise => { const source = resolveSourceConfig(options.sourceId); diff --git a/apps/crawler/src/schema.ts b/apps/crawler/src/schema.ts index df7274a..aef3a57 100644 --- a/apps/crawler/src/schema.ts +++ b/apps/crawler/src/schema.ts @@ -112,8 +112,8 @@ export const ArticleSchema = z.object({ hash: z.string().optional(), link: z.url(), metadata: ArticleMetadataSchema.optional(), - source: z.string(), - timestamp: z.number().int(), + publishedAt: z.date(), + sourceId: z.string(), title: z.string(), tokenStatistics: ArticleTokenStatisticsSchema.optional(), }); diff --git a/apps/crawler/src/scripts/crawl.ts b/apps/crawler/src/scripts/crawl.ts index f352bf3..2911eff 100644 --- a/apps/crawler/src/scripts/crawl.ts +++ b/apps/crawler/src/scripts/crawl.ts @@ -1,7 +1,7 @@ import { logger } from "@basango/logger"; -import { runSyncCrawl } from "@/process/sync/tasks"; -import { CRAWLING_USAGE, parseCrawlingCliArgs } from "@/scripts/utils"; +import { runSyncCrawl } from "#crawler/process/sync/tasks"; +import { CRAWLING_USAGE, parseCrawlingCliArgs } from "#crawler/scripts/utils"; const main = async (): Promise => { const options = parseCrawlingCliArgs(); diff --git a/apps/crawler/src/scripts/queue.ts b/apps/crawler/src/scripts/queue.ts index f154bff..f754e19 100644 --- a/apps/crawler/src/scripts/queue.ts +++ b/apps/crawler/src/scripts/queue.ts @@ -1,7 +1,7 @@ import { logger } from "@basango/logger"; -import { scheduleAsyncCrawl } from "@/process/async/tasks"; -import { CRAWLING_USAGE, parseCrawlingCliArgs } from "@/scripts/utils"; +import { scheduleAsyncCrawl } from "#crawler/process/async/tasks"; +import { CRAWLING_USAGE, parseCrawlingCliArgs } from "#crawler/scripts/utils"; const main = async (): Promise => { const options = parseCrawlingCliArgs(); diff --git a/apps/crawler/src/scripts/sync.ts b/apps/crawler/src/scripts/sync.ts new file mode 100644 index 0000000..9b0a1cd --- /dev/null +++ b/apps/crawler/src/scripts/sync.ts @@ -0,0 +1,103 @@ +import fs from "node:fs"; +import path from "node:path"; +import { createInterface } from "node:readline"; +import { parseArgs } from "node:util"; + +import { logger } from "@basango/logger"; + +import { config, env } from "#crawler/config"; +import { SyncHttpClient } from "#crawler/http/http-client"; +import type { Article } from "#crawler/schema"; + +const USAGE = ` + Usage: bun run crawler:sync -- --sourceId +`; + +const parseCliArgs = (): { sourceId?: string } => { + const { values } = parseArgs({ + options: { + sourceId: { type: "string" }, + }, + }); + return values as { sourceId?: string }; +}; + +const forwardArticle = async (article: Article): Promise => { + const client = new SyncHttpClient(config.fetch.client); + const endpoint = env("BASANGO_CRAWLER_BACKEND_API_ENDPOINT"); + const token = env("BASANGO_CRAWLER_TOKEN"); + + try { + const response = await client.post(endpoint, { + headers: { + Authorization: `${token}`, + }, + json: article, + }); + + if (response.ok) { + const data = await response.json(); + logger.info({ ...data }, "Article forwarded"); + return; + } + + logger.error({ link: article.link, status: response.status }, "Forwarding failed"); + } catch (error) { + logger.error({ error, link: article.link }, "Failed to forward article"); + } +}; + +const main = async (): Promise => { + const { sourceId } = parseCliArgs(); + if (!sourceId) { + console.log(USAGE); + process.exitCode = 1; + return; + } + + const filePath = path.join(config.paths.data, `${sourceId}.jsonl`); + + if (!fs.existsSync(filePath)) { + logger.error({ filePath, sourceId }, "Source must be crawled first; JSONL not found"); + process.exitCode = 1; + return; + } + + const stat = fs.statSync(filePath); + if (stat.size === 0) { + logger.error({ filePath, sourceId }, "Source must be crawled first; JSONL is empty"); + process.exitCode = 1; + return; + } + + logger.info({ filePath, sourceId }, "Syncing articles from JSONL to backend"); + + const stream = fs.createReadStream(filePath, { encoding: "utf-8" }); + const rl = createInterface({ crlfDelay: Infinity, input: stream }); + + let count = 0; + try { + for await (const raw of rl) { + const line = raw.trim(); + if (!line) continue; + + try { + const article = JSON.parse(line) as Article & { publishedAt: string }; + await forwardArticle({ + ...article, + publishedAt: new Date(article.publishedAt), + }); + + count += 1; + } catch (error) { + logger.error({ error, linePreview: line.slice(0, 100) }, "Invalid JSONL line"); + } + } + } finally { + rl.close(); + } + + logger.info({ forwarded: count, sourceId }, "Sync completed"); +}; + +void main(); diff --git a/apps/crawler/src/scripts/utils.ts b/apps/crawler/src/scripts/utils.ts index 5a30729..bd73e57 100644 --- a/apps/crawler/src/scripts/utils.ts +++ b/apps/crawler/src/scripts/utils.ts @@ -1,6 +1,6 @@ import { parseArgs } from "node:util"; -import { CrawlingOptions } from "@/process/crawler"; +import { CrawlingOptions } from "#crawler/process/crawler"; interface WorkerCliOptions { queue?: string[]; diff --git a/apps/crawler/src/scripts/worker.ts b/apps/crawler/src/scripts/worker.ts index 373090c..b9564f4 100644 --- a/apps/crawler/src/scripts/worker.ts +++ b/apps/crawler/src/scripts/worker.ts @@ -1,8 +1,8 @@ import { logger } from "@basango/logger"; -import { createQueueManager } from "@/process/async/queue"; -import { startWorker } from "@/process/async/worker"; -import { parseWorkerCliArgs } from "@/scripts/utils"; +import { createQueueManager } from "#crawler/process/async/queue"; +import { startWorker } from "#crawler/process/async/worker"; +import { parseWorkerCliArgs } from "#crawler/scripts/utils"; const main = async (): Promise => { const options = parseWorkerCliArgs(); diff --git a/apps/crawler/src/utils.ts b/apps/crawler/src/utils.ts index dcfe192..ebac549 100644 --- a/apps/crawler/src/utils.ts +++ b/apps/crawler/src/utils.ts @@ -1,9 +1,8 @@ import { format, getUnixTime, isMatch, parse } from "date-fns"; import type { RedisOptions } from "ioredis"; -import { TiktokenEncoding, get_encoding } from "tiktoken"; -import { config } from "@/config"; -import { DEFAULT_DATE_FORMAT } from "@/constants"; +import { config } from "#crawler/config"; +import { DEFAULT_DATE_FORMAT } from "#crawler/constants"; import { AnySourceConfig, CreateDateRangeOptions, @@ -15,7 +14,7 @@ import { PageRangeSchema, PageRangeSpecSchema, WordPressSourceConfig, -} from "@/schema"; +} from "#crawler/schema"; /** * Resolve a source configuration by its ID. @@ -66,22 +65,6 @@ const parseDate = (value: string, format: string): Date => { return parsed; }; -/** - * Count the number of tokens in the given text using the specified encoding. - * @param text - The input text - * @param encoding - The token encoding (default: "cl100k_base") - */ -export const countTokens = (text: string, encoding: TiktokenEncoding = "cl100k_base"): number => { - try { - const encoder = get_encoding(encoding); - const tokens = encoder.encode(text); - encoder.free(); - return tokens.length; - } catch { - return text.length; - } -}; - /** * Create a page range from a string specification. * @param spec - The page range specification (e.g., "1:10") diff --git a/apps/crawler/tsconfig.json b/apps/crawler/tsconfig.json index d14326b..06f4264 100644 --- a/apps/crawler/tsconfig.json +++ b/apps/crawler/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "#crawler/*": ["./src/*"] } }, "extends": "@basango/tsconfig/base.json", diff --git a/apps/dashboard/components.json b/apps/dashboard/components.json index 64644b3..85a4fe4 100644 --- a/apps/dashboard/components.json +++ b/apps/dashboard/components.json @@ -1,9 +1,9 @@ { "$schema": "https://ui.shadcn.com/schema.json", "aliases": { - "components": "@/components", - "hooks": "@/hooks", - "lib": "@/lib", + "components": "#dashboard/components", + "hooks": "#dashboard/hooks", + "lib": "#dashboard/lib", "ui": "@basango/ui/components", "utils": "@basango/ui/lib/utils" }, diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 0e1550e..138d49f 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -4,10 +4,13 @@ "@basango/ui": "workspace:*", "@date-fns/tz": "^1.4.1", "@hookform/resolvers": "^5.2.2", - "@tanstack/react-query": "^5.90.7", + "@tanstack/react-query": "^5.90.8", "@tanstack/react-table": "^8.21.3", "@trpc/client": "^11.7.1", + "@trpc/react-query": "^11.7.1", + "@trpc/server": "^11.7.1", "@trpc/tanstack-react-query": "^11.7.1", + "client-only": "^0.0.1", "date-fns": "^4.1.0", "lucide-react": "^0.553.0", "next": "catalog:", @@ -18,6 +21,7 @@ "react-dom": "catalog:", "react-hook-form": "^7.66.0", "recharts": "^3.4.1", + "server-only": "^0.0.1", "superjson": "^2.2.5", "zod": "^4.1.12", "zustand": "^5.0.8" diff --git a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/articles/page.tsx b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/articles/page.tsx index f4725d0..1d7e544 100644 --- a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/articles/page.tsx +++ b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/articles/page.tsx @@ -1,18 +1,22 @@ import { Metadata } from "next"; +import { PageLayout } from "#dashboard/components/shell/page-layout"; + export const metadata: Metadata = { title: "Articles | Basango Dashboard", }; export default function Page() { return ( -
-
-
-
-
+ +
+
+
+
+
+
+
-
-
+ ); } diff --git a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/layout.tsx b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/layout.tsx index 80fe938..41e9cef 100644 --- a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/layout.tsx +++ b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/layout.tsx @@ -1,8 +1,8 @@ import { SidebarInset, SidebarProvider } from "@basango/ui/components/sidebar"; -import { PageHeader } from "@/components/shell/page-header"; -import { AppSidebar } from "@/components/sidebar/app-sidebar"; -import { HydrateClient } from "@/trpc/server"; +import { PageHeader } from "#dashboard/components/shell/page-header"; +import { AppSidebar } from "#dashboard/components/sidebar/app-sidebar"; +import { HydrateClient } from "#dashboard/trpc/server"; export default async function Layout({ children }: { children: React.ReactNode }) { return ( diff --git a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/sources/page.tsx b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/sources/page.tsx index 8d70347..af2a7fb 100644 --- a/apps/dashboard/src/app/[locale]/(app)/(sidebar)/sources/page.tsx +++ b/apps/dashboard/src/app/[locale]/(app)/(sidebar)/sources/page.tsx @@ -1,26 +1,31 @@ +import { RouterOutputs } from "@basango/api/trpc/routers/_app"; import { Metadata } from "next"; -import { PageLayout } from "@/components/shell/page-layout"; -import { SourceCard } from "@/components/source-card"; -import { batchPrefetch, getQueryClient, trpc } from "@/trpc/server"; +import { PageLayout } from "#dashboard/components/shell/page-layout"; +import { SourceCard } from "#dashboard/components/source-card"; +import { HydrateClient, getQueryClient, prefetch, trpc } from "#dashboard/trpc/server"; export const metadata: Metadata = { title: "Sources | Basango Dashboard", }; +type SourceDetails = RouterOutputs["sources"]["get"][number]; + export default async function Page() { const queryClient = getQueryClient(); - batchPrefetch([trpc.sources.get.queryOptions()]); + prefetch(trpc.sources.get.queryOptions()); const sources = await queryClient.fetchQuery(trpc.sources.get.queryOptions()); return ( - -
- {sources.map((source) => ( - - ))} -
-
+ + +
+ {sources.map((source: SourceDetails) => ( + + ))} +
+
+
); } diff --git a/apps/dashboard/src/app/[locale]/(public)/login/page.tsx b/apps/dashboard/src/app/[locale]/(public)/login/page.tsx index cb9c391..229d6e4 100644 --- a/apps/dashboard/src/app/[locale]/(public)/login/page.tsx +++ b/apps/dashboard/src/app/[locale]/(public)/login/page.tsx @@ -1,6 +1,6 @@ import { GalleryVerticalEnd } from "lucide-react"; -import { LoginForm } from "@/components/forms/login-form"; +import { LoginForm } from "#dashboard/components/forms/login-form"; export default function LoginPage() { return ( diff --git a/apps/dashboard/src/app/[locale]/providers.tsx b/apps/dashboard/src/app/[locale]/providers.tsx index 0cc3398..81ce315 100644 --- a/apps/dashboard/src/app/[locale]/providers.tsx +++ b/apps/dashboard/src/app/[locale]/providers.tsx @@ -3,8 +3,8 @@ import { ThemeProvider } from "next-themes"; import type { ReactNode } from "react"; -import { I18nProviderClient } from "@/locales/client"; -import { TRPCReactProvider } from "@/trpc/client"; +import { I18nProviderClient } from "#dashboard/locales/client"; +import { TRPCReactProvider } from "#dashboard/trpc/client"; type ProviderProps = { locale: string; diff --git a/apps/dashboard/src/components/source-card.tsx b/apps/dashboard/src/components/source-card.tsx index ab47534..d3909c9 100644 --- a/apps/dashboard/src/components/source-card.tsx +++ b/apps/dashboard/src/components/source-card.tsx @@ -1,10 +1,10 @@ "use client"; -import { Badge } from "@basango/ui/components/badge"; import { Card, CardContent, CardDescription, + CardFooter, CardHeader, CardTitle, } from "@basango/ui/components/card"; @@ -14,49 +14,9 @@ import { ChartTooltip, ChartTooltipContent, } from "@basango/ui/components/chart"; -import { Separator } from "@basango/ui/components/separator"; import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"; -interface CredibilityMetric { - bias: string; - reliability: string; - transparency: string; -} - -interface PublicationItem { - date: string; - count: number; -} - -interface SourceCardProps { - id: string; - name: string; - displayName: string | null; - url: string; - description: string; - publicationGraph: { - items: PublicationItem[]; - total: number; - }; - credibility: CredibilityMetric; -} - -const credibilityColors = { - high: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200", - low: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200", - medium: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200", -}; - -function getCredibilityColor(value: string): string { - const lower = value.toLowerCase(); - if (lower.includes("high") || lower.includes("strong") || lower.includes("good")) { - return credibilityColors.high; - } - if (lower.includes("medium") || lower.includes("moderate")) { - return credibilityColors.medium; - } - return credibilityColors.low; -} +import { formatNumber } from "#dashboard/utils/utils"; const chartConfig = { count: { @@ -68,50 +28,34 @@ const chartConfig = { }, } satisfies ChartConfig; -export function SourceCard({ - id, - name, - displayName, - url, - description, - publicationGraph, - credibility, -}: SourceCardProps) { - const chartData = publicationGraph.items; +type SourceDetails = { + id: string; + name: string; + displayName: string | null; + url: string; + description: string; + publicationGraph: { + items: { date: string; count: number }[]; + total: number; + }; + credibility: { + bias: string; + reliability: string; + transparency: string; + }; + articles: number; +}; +export function SourceCard({ source }: { source: SourceDetails }) { return ( - - -
-
- - {description} -

ID: {id}

-
-
+ + + {source.name} + {source.id} - - - - + + + - { - return new Date(value).toLocaleDateString("en-US", { - day: "numeric", - month: "short", - year: "numeric", - }); - }} - nameKey="views" - /> - } - /> - + } cursor={false} /> + - - -
-

Credibility Metrics

-
-
-

Bias

- - {credibility.bias} - -
-
-

Reliability

- - {credibility.reliability} - -
-
-

Transparency

- - {credibility.transparency} - -
-
-
- - -
-

Summary

-
-
-

Total Publications

-

{publicationGraph.total}

-
-
-

Timeline Entries

-

{publicationGraph.items.length}

-
-
-
+ +
+ {formatNumber(source.articles)} articles crawled +
+
+ Showing last {source.publicationGraph.total} days +
+
); } diff --git a/apps/dashboard/src/trpc/client.tsx b/apps/dashboard/src/trpc/client.tsx index ee1fd5f..a49b197 100644 --- a/apps/dashboard/src/trpc/client.tsx +++ b/apps/dashboard/src/trpc/client.tsx @@ -2,8 +2,8 @@ import type { AppRouter } from "@basango/api/trpc/routers/_app"; import type { QueryClient } from "@tanstack/react-query"; -import { QueryClientProvider, isServer } from "@tanstack/react-query"; -import { createTRPCClient, httpBatchLink, loggerLink } from "@trpc/client"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { createTRPCClient, httpBatchLink } from "@trpc/client"; import { createTRPCContext } from "@trpc/tanstack-react-query"; import { useState } from "react"; import superjson from "superjson"; @@ -15,7 +15,7 @@ export const { TRPCProvider, useTRPC } = createTRPCContext(); let browserQueryClient: QueryClient; function getQueryClient() { - if (isServer) { + if (typeof window === "undefined") { // Server: always make a new query client return makeQueryClient(); } @@ -34,25 +34,25 @@ export function TRPCReactProvider( children: React.ReactNode; }>, ) { + // NOTE: Avoid useState when initializing the query client if you don't + // have a suspense boundary between this and the code that may + // suspend because React will throw away the client on the initial + // render if it suspends and there is no boundary const queryClient = getQueryClient(); const [trpcClient] = useState(() => createTRPCClient({ links: [ httpBatchLink({ - async headers() { - const token = window.localStorage.getItem("auth_token"); + headers: async () => { + //const token = window.localStorage.getItem("auth_token"); + return { - Authorization: `Bearer ${token}`, + //Authorization: `Bearer ${token}`, }; }, transformer: superjson, url: `${process.env.NEXT_PUBLIC_API_URL}/trpc`, }), - loggerLink({ - enabled: (opts) => - process.env.NODE_ENV === "development" || - (opts.direction === "down" && opts.result instanceof Error), - }), ], }), ); diff --git a/apps/dashboard/src/trpc/server.tsx b/apps/dashboard/src/trpc/server.tsx index 9da7731..720ddff 100644 --- a/apps/dashboard/src/trpc/server.tsx +++ b/apps/dashboard/src/trpc/server.tsx @@ -1,7 +1,7 @@ +/** biome-ignore-all lint/suspicious/noExplicitAny: needed for tRPC type inference */ import "server-only"; import type { AppRouter } from "@basango/api/trpc/routers/_app"; -//import { getCountryCode, getLocale, getTimezone } from "@basango/location"; import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; import { createTRPCClient, httpBatchLink, loggerLink } from "@trpc/client"; import { type TRPCQueryOptions, createTRPCOptionsProxy } from "@trpc/tanstack-react-query"; @@ -43,38 +43,14 @@ export const trpc = createTRPCOptionsProxy({ export function HydrateClient(props: { children: React.ReactNode }) { const queryClient = getQueryClient(); - return {props.children}; } -export function prefetch>>(queryOptions: T) { +export function prefetch>>(queryOptions: T) { const queryClient = getQueryClient(); - if (queryOptions.queryKey[1]?.type === "infinite") { - void queryClient.prefetchInfiniteQuery( - queryOptions as unknown as Parameters[0], - ); + void queryClient.prefetchInfiniteQuery(queryOptions as any); } else { - void queryClient.prefetchQuery( - queryOptions as unknown as Parameters[0], - ); - } -} - -export function batchPrefetch>>( - queryOptionsArray: T[], -) { - const queryClient = getQueryClient(); - - for (const queryOptions of queryOptionsArray) { - if (queryOptions.queryKey[1]?.type === "infinite") { - void queryClient.prefetchInfiniteQuery( - queryOptions as unknown as Parameters[0], - ); - } else { - void queryClient.prefetchQuery( - queryOptions as unknown as Parameters[0], - ); - } + void queryClient.prefetchQuery(queryOptions); } } diff --git a/apps/dashboard/src/utils/utils.ts b/apps/dashboard/src/utils/utils.ts new file mode 100644 index 0000000..bfacd3d --- /dev/null +++ b/apps/dashboard/src/utils/utils.ts @@ -0,0 +1,110 @@ +import type { TZDate } from "@date-fns/tz"; +import { format, isSameYear } from "date-fns"; + +export function formatSize(bytes: number): string { + const units = ["byte", "kilobyte", "megabyte", "gigabyte", "terabyte"]; + + const unitIndex = Math.max( + 0, + Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1), + ); + + return Intl.NumberFormat("en-US", { + style: "unit", + unit: units[unitIndex], + }).format(+Math.round(bytes / 1024 ** unitIndex)); +} + +export function secondsToHoursAndMinutes(seconds: number) { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + + if (hours && minutes) { + return `${hours}h ${minutes}m`; + } + + if (hours) { + return `${hours}h`; + } + + if (minutes) { + return `${minutes}m`; + } + + return "0m"; +} + +export function formatDate(date: string, dateFormat?: string | null, checkYear = true) { + if (checkYear && isSameYear(new Date(), new Date(date))) { + return format(new Date(date), "MMM d"); + } + + return format(new Date(date), dateFormat ?? "P"); +} + +export function formatNumber(value: number): string { + return Intl.NumberFormat("en-US").format(value); +} + +export function getInitials(value: string) { + const formatted = value.toUpperCase().replace(/[\s.-]/g, ""); + + if (formatted.split(" ").length > 1) { + return `${formatted.charAt(0)}${formatted.charAt(1)}`; + } + + if (value.length > 1) { + return formatted.charAt(0) + formatted.charAt(1); + } + + return formatted.charAt(0); +} + +export function formatDateRange(dates: TZDate[]): string { + if (!dates.length) return ""; + + const formatFullDate = (date: TZDate) => format(date, "MMM d"); + const formatDay = (date: TZDate) => format(date, "d"); + + const startDate = dates[0]; + const endDate = dates[1]; + + if (!startDate) return ""; + + if (dates.length === 1 || !endDate || startDate.getTime() === endDate.getTime()) { + return formatFullDate(startDate); + } + + if (startDate.getMonth() === endDate.getMonth()) { + // Same month + return `${format(startDate, "MMM")} ${formatDay(startDate)} - ${formatDay(endDate)}`; + } + // Different months + return `${formatFullDate(startDate)} - ${formatFullDate(endDate)}`; +} + +export function formatRelativeTime(date: Date): string { + const now = new Date(); + const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); + + if (diffInSeconds < 60) { + return "just now"; + } + + const intervals = [ + { label: "y", seconds: 31536000 }, + { label: "mo", seconds: 2592000 }, + { label: "d", seconds: 86400 }, + { label: "h", seconds: 3600 }, + { label: "m", seconds: 60 }, + ] as const; + + for (const interval of intervals) { + const count = Math.floor(diffInSeconds / interval.seconds); + if (count > 0) { + return `${count}${interval.label} ago`; + } + } + + return "just now"; +} diff --git a/apps/dashboard/tsconfig.json b/apps/dashboard/tsconfig.json index f4b282d..49bd31a 100644 --- a/apps/dashboard/tsconfig.json +++ b/apps/dashboard/tsconfig.json @@ -2,8 +2,9 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./src/*"], - "@basango/ui/*": ["../../packages/ui/src/*"] + "@basango/api/*": ["../api/src/*"], + "@basango/ui/*": ["../../packages/ui/src/*"], + "#dashboard/*": ["./src/*"] }, "plugins": [ { @@ -13,12 +14,10 @@ }, "exclude": ["node_modules"], "extends": "@basango/tsconfig/nextjs.json", - "include": [ - "next-env.d.ts", - "next.config.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - "../../packages/ui/src/hooks/use-mobile.ts" + "include": ["next-env.d.ts", "next.config.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "references": [ + { + "path": "../api" + } ] } diff --git a/apps/mobile-legacy/.env b/apps/mobile-legacy/.env deleted file mode 100644 index bf1805b..0000000 --- a/apps/mobile-legacy/.env +++ /dev/null @@ -1,3 +0,0 @@ -EXPO_PUBLIC_API_URL=http://172.20.10.2:8000/api -EXPO_PUBLIC_SENTRY_DSN= -SENTRY_AUTH_TOKEN= diff --git a/apps/mobile-legacy/.gitignore b/apps/mobile-legacy/.gitignore deleted file mode 100644 index 9393cd6..0000000 --- a/apps/mobile-legacy/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files - -# dependencies -node_modules/ - -# Expo -.expo/ -dist/ -web-build/ -expo-env.d.ts - -# Native -*.orig.* -*.jks -*.p8 -*.p12 -*.key -*.mobileprovision - -# Metro -.metro-health-check* - -# debug -npm-debug.* -yarn-debug.* -yarn-error.* - -# macOS -.idea -.DS_Store -*.pem - -# local env files -.env*.local - -# typescript -*.tsbuildinfo - -app-example - -.env.local diff --git a/apps/mobile-legacy/.prettierignore b/apps/mobile-legacy/.prettierignore deleted file mode 100644 index 6d06de5..0000000 --- a/apps/mobile-legacy/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -# Ignore artifacts: -build -coverage -dist -android -ios diff --git a/apps/mobile-legacy/.prettierrc b/apps/mobile-legacy/.prettierrc deleted file mode 100644 index 6e1efde..0000000 --- a/apps/mobile-legacy/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "semi": true, - "trailingComma": "es5", - "singleQuote": false, - "tabWidth": 4, - "useTabs": false, - "printWidth": 120, - "bracketSpacing": true, - "arrowParens": "avoid" -} \ No newline at end of file diff --git a/apps/mobile-legacy/README.md b/apps/mobile-legacy/README.md deleted file mode 100644 index b029512..0000000 --- a/apps/mobile-legacy/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Mobile - -![Coding Standard](https://github.com/bernard-ng/basango/actions/workflows/quality.yaml/badge.svg) - ---- - -### Get started - -1. Install dependencies - -```bash -bun install -``` - -2. Start the app - -```bash -bunx expo start -``` - -In the output, you'll find options to open the app in a - -- [development build](https://docs.expo.dev/develop/development-builds/introduction/) -- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/) -- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/) -- [Expo Go](https://expo.dev/go) diff --git a/apps/mobile-legacy/_package.json b/apps/mobile-legacy/_package.json deleted file mode 100644 index 1bff74f..0000000 --- a/apps/mobile-legacy/_package.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "commitlint": { - "extends": ["@commitlint/config-conventional"] - }, - "config": { - "commitizen": { - "path": "cz-conventional-changelog" - } - }, - "dependencies": { - "@expo-google-fonts/inter": "^0.3.0", - "@expo/vector-icons": "^14.0.2", - "@hookform/resolvers": "^5.1.1", - "@react-navigation/bottom-tabs": "^7.2.0", - "@react-navigation/native": "^7.0.14", - "@sentry/react-native": "^6.15.1", - "@shopify/flash-list": "1.7.3", - "@tamagui/colors": "^1.126.1", - "@tamagui/config": "^1.126.1", - "@tamagui/linear-gradient": "^1.126.1", - "@tamagui/lucide-icons": "^1.129.2", - "@tamagui/theme-builder": "^1.126.1", - "@tanstack/react-query": "^5.74.4", - "axios": "^1.9.0", - "date-fns": "^4.1.0", - "expo": "~52.0.46", - "expo-blur": "~14.0.3", - "expo-build-properties": "~0.13.2", - "expo-constants": "~17.0.8", - "expo-dev-client": "~5.0.20", - "expo-font": "~13.0.4", - "expo-haptics": "~14.0.1", - "expo-linear-gradient": "~14.0.2", - "expo-linking": "~7.0.5", - "expo-localization": "~16.0.1", - "expo-network": "~7.0.5", - "expo-router": "~4.0.20", - "expo-secure-store": "^14.0.1", - "expo-splash-screen": "~0.29.24", - "expo-status-bar": "~2.0.1", - "expo-symbols": "~0.2.2", - "expo-system-ui": "~4.0.9", - "expo-web-browser": "~14.0.2", - "joi": "^17.13.3", - "qs": "^6.14.0", - "react": "18.3.1", - "react-content-loader": "^7.0.2", - "react-dom": "18.3.1", - "react-hook-form": "^7.58.1", - "react-native": "0.76.9", - "react-native-gesture-handler": "~2.20.2", - "react-native-reanimated": "~3.16.1", - "react-native-safe-area-context": "^5.4.0", - "react-native-screens": "~4.4.0", - "react-native-svg": "^15.11.2", - "react-native-toast-message": "^2.3.0", - "react-native-web": "~0.19.13", - "react-native-webview": "13.12.5", - "tamagui": "^1.126.1", - "zustand": "^5.0.5" - }, - "devDependencies": { - "@babel/core": "^7.25.2", - "@commitlint/cli": "^19.8.1", - "@commitlint/config-conventional": "^19.8.1", - "@types/jest": "^29.5.12", - "@types/qs": "^6.9.18", - "@types/react": "~18.3.12", - "@types/react-test-renderer": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "commitizen": "^4.3.1", - "cz-conventional-changelog": "^3.3.0", - "husky": "^9.1.7", - "jest": "^29.2.1", - "jest-expo": "~52.0.6", - "lint-staged": "^16.0.0", - "prettier": "^3.5.3", - "react-test-renderer": "18.3.1", - "typescript": "^5.3.3" - }, - "jest": { - "preset": "jest-expo" - }, - "lint-staged": { - "*.ts": ["prettier --write", "eslint --fix"], - "*.tsx": ["prettier --write", "eslint --fix"] - }, - "main": "expo-router/entry", - "name": "drc-news", - "overrides": { - "globals": "14.0.0" - }, - "private": true, - "scripts": { - "=========== CODE STYLE ============": "", - "============= EAS BUILD =============": "", - "============= HUSKY =============": "", - "============= MISCELLANEOUS =============": "", - "===================== EAS SUBMIT =====================": "", - "android": "expo run:android", - "build:android:dev": "eas build --profile development --platform android", - "build:android:e2e": "eas build --profile android-e2e --platform android", - "build:android:prev": "eas build --profile preview --platform android", - "build:android:prod": "eas build --profile production --platform android", - "build:android:sim": "eas build --profile dev-sim --platform android", - "build:ios:dev": "eas build --profile development --platform ios", - "build:ios:e2e": "eas build --profile ios-e2e --platform ios", - "build:ios:prev": "eas build --profile preview --platform ios", - "build:ios:prod": "eas build --profile production --platform ios", - "build:ios:sim": "eas build --profile dev-sim --platform ios", - "check": "prettier src --check", - "check-types": "tsc --noEmit", - "commit": "cz", - "delete:dstore": "find -name '.DS_Store' -type f -delete", - "eas:android:submit": "eas submit -p android --profile production", - "eas:ios:submit": "eas submit -p ios --profile production", - "format": "prettier src --write", - "ios": "expo run:ios", - "lint:check": "eslint src --debug", - "lint:fix": "eslint src --fix", - "prepare": "husky", - "start": "expo start", - "test": "jest --watchAll", - "web": "expo start --web" - }, - "version": "1.0.0" -} diff --git a/apps/mobile-legacy/app.json b/apps/mobile-legacy/app.json deleted file mode 100644 index 82adf55..0000000 --- a/apps/mobile-legacy/app.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "expo": { - "android": { - "adaptiveIcon": { - "backgroundColor": "#ffffff", - "foregroundImage": "./src/assets/images/logo.png", - "package": "dev.ngandu.basango" - }, - "package": "dev.ngandu.basango" - }, - "experiments": { - "typedRoutes": true - }, - "extra": { - "eas": { - "projectId": "57281e7a-46e3-4aac-8715-5165fa0bf560" - }, - "router": { - "origin": false - } - }, - "githubUrl": "https://github.com/bernard-ng/basango", - "icon": "./src/assets/images/logo.png", - "ios": { - "bundleIdentifier": "dev.ngandu.basango", - "supportsTablet": true - }, - "name": "basango", - "newArchEnabled": true, - "orientation": "portrait", - "owner": "bernard-ng", - "plugins": [ - "expo-router", - [ - "expo-splash-screen", - { - "backgroundColor": "#ffffff", - "image": "./src/assets/images/logo.png", - "imageWidth": 200, - "resizeMode": "contain" - } - ], - "expo-build-properties", - "expo-localization", - [ - "@sentry/react-native/expo", - { - "organization": "devscast-software", - "project": "basango", - "url": "https://glitchtip.devscast.tech/" - } - ] - ], - "scheme": "basango", - "slug": "basango", - "userInterfaceStyle": "automatic", - "version": "1.0.0", - "web": { - "bundler": "metro", - "favicon": "./src/assets/images/logo.png", - "output": "static" - } - } -} diff --git a/apps/mobile-legacy/babel.config.js b/apps/mobile-legacy/babel.config.js deleted file mode 100644 index 9ee4747..0000000 --- a/apps/mobile-legacy/babel.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = (api) => { - api.cache(true); - return { - plugins: ["react-native-reanimated/plugin"], - presets: [["babel-preset-expo", { jsxRuntime: "automatic" }]], - }; -}; diff --git a/apps/mobile-legacy/commitlint.config.js b/apps/mobile-legacy/commitlint.config.js deleted file mode 100644 index 3185047..0000000 --- a/apps/mobile-legacy/commitlint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - extends: ["@commitlint/config-conventional"], - rules: { - "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]], - "type-enum": [ - 2, - "always", - [ - "feat", // New feature - "fix", // Bug fix - "docs", // Documentation only changes - "style", // Changes that do not affect the meaning of the code (white-space, formatting, etc) - "refactor", // Code changes that neither fixes a bug nor adds a feature - "perf", // Performance improvements - "test", // Adding missing tests or correcting existing tests - "build", // Changes that affect the build system or external dependencies - "ci", // Changes to CI configuration files and scripts - "chore", // Other changes that don't modify src or test files - "revert", // Reverts a previous commit - ], - ], - }, -}; diff --git a/apps/mobile-legacy/eas.json b/apps/mobile-legacy/eas.json deleted file mode 100644 index b7967bb..0000000 --- a/apps/mobile-legacy/eas.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "build": { - "development": { - "developmentClient": true, - "distribution": "internal" - }, - "preview": { - "distribution": "internal" - }, - "production": { - "autoIncrement": true - } - }, - "cli": { - "appVersionSource": "remote", - "version": ">= 16.3.1" - }, - "submit": { - "production": {} - } -} diff --git a/apps/mobile-legacy/ios/.gitignore b/apps/mobile-legacy/ios/.gitignore deleted file mode 100644 index 8beb344..0000000 --- a/apps/mobile-legacy/ios/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -# OSX -# -.DS_Store - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -project.xcworkspace -.xcode.env.local - -# Bundle artifacts -*.jsbundle - -# CocoaPods -/Pods/ diff --git a/apps/mobile-legacy/ios/.xcode.env b/apps/mobile-legacy/ios/.xcode.env deleted file mode 100644 index 3d5782c..0000000 --- a/apps/mobile-legacy/ios/.xcode.env +++ /dev/null @@ -1,11 +0,0 @@ -# This `.xcode.env` file is versioned and is used to source the environment -# used when running script phases inside Xcode. -# To customize your local environment, you can create an `.xcode.env.local` -# file that is not versioned. - -# NODE_BINARY variable contains the PATH to the node executable. -# -# Customize the NODE_BINARY variable here. -# For example, to use nvm with brew, add the following line -# . "$(brew --prefix nvm)/nvm.sh" --no-use -export NODE_BINARY=$(command -v node) diff --git a/apps/mobile-legacy/ios/Podfile b/apps/mobile-legacy/ios/Podfile deleted file mode 100644 index bd73634..0000000 --- a/apps/mobile-legacy/ios/Podfile +++ /dev/null @@ -1,66 +0,0 @@ -require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") -require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods") - -require 'json' -podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} - -ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0' -ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR'] - -platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1' -install! 'cocoapods', - :deterministic_uuids => false - -prepare_react_native_project! - -target 'basango' do - use_expo_modules! - - if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1' - config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"]; - else - config_command = [ - 'node', - '--no-warnings', - '--eval', - 'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))', - 'react-native-config', - '--json', - '--platform', - 'ios' - ] - end - - config = use_native_modules!(config_command) - - use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks'] - use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS'] - - use_react_native!( - :path => config[:reactNativePath], - :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes', - # An absolute path to your application root. - :app_path => "#{Pod::Config.instance.installation_root}/..", - :privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false', - ) - - post_install do |installer| - react_native_post_install( - installer, - config[:reactNativePath], - :mac_catalyst_enabled => false, - :ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true', - ) - - # This is necessary for Xcode 14, because it signs resource bundles by default - # when building for devices. - installer.target_installation_results.pod_target_installation_results - .each do |pod_name, target_installation_result| - target_installation_result.resource_bundle_targets.each do |resource_bundle_target| - resource_bundle_target.build_configurations.each do |config| - config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO' - end - end - end - end -end diff --git a/apps/mobile-legacy/ios/Podfile.lock b/apps/mobile-legacy/ios/Podfile.lock deleted file mode 100644 index 943da44..0000000 --- a/apps/mobile-legacy/ios/Podfile.lock +++ /dev/null @@ -1,2573 +0,0 @@ -PODS: - - boost (1.84.0) - - DoubleConversion (1.1.6) - - EXConstants (17.0.8): - - ExpoModulesCore - - EXJSONUtils (0.14.0) - - EXManifests (0.15.8): - - ExpoModulesCore - - Expo (52.0.46): - - ExpoModulesCore - - expo-dev-client (5.0.20): - - EXManifests - - expo-dev-launcher - - expo-dev-menu - - expo-dev-menu-interface - - EXUpdatesInterface - - expo-dev-launcher (5.0.35): - - DoubleConversion - - EXManifests - - expo-dev-launcher/Main (= 5.0.35) - - expo-dev-menu - - expo-dev-menu-interface - - ExpoModulesCore - - EXUpdatesInterface - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsinspector - - React-NativeModulesApple - - React-RCTAppDelegate - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-launcher/Main (5.0.35): - - DoubleConversion - - EXManifests - - expo-dev-launcher/Unsafe - - expo-dev-menu - - expo-dev-menu-interface - - ExpoModulesCore - - EXUpdatesInterface - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsinspector - - React-NativeModulesApple - - React-RCTAppDelegate - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-launcher/Unsafe (5.0.35): - - DoubleConversion - - EXManifests - - expo-dev-menu - - expo-dev-menu-interface - - ExpoModulesCore - - EXUpdatesInterface - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsinspector - - React-NativeModulesApple - - React-RCTAppDelegate - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-menu (6.0.25): - - DoubleConversion - - expo-dev-menu/Main (= 6.0.25) - - expo-dev-menu/ReactNativeCompatibles (= 6.0.25) - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-menu-interface (1.9.3) - - expo-dev-menu/Main (6.0.25): - - DoubleConversion - - EXManifests - - expo-dev-menu-interface - - expo-dev-menu/Vendored - - ExpoModulesCore - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsinspector - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-menu/ReactNativeCompatibles (6.0.25): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-menu/SafeAreaView (6.0.25): - - DoubleConversion - - ExpoModulesCore - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - expo-dev-menu/Vendored (6.0.25): - - DoubleConversion - - expo-dev-menu/SafeAreaView - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - ExpoAsset (11.0.5): - - ExpoModulesCore - - ExpoBlur (14.0.3): - - ExpoModulesCore - - ExpoFileSystem (18.0.12): - - ExpoModulesCore - - ExpoFont (13.0.4): - - ExpoModulesCore - - ExpoHaptics (14.0.1): - - ExpoModulesCore - - ExpoHead (4.0.21): - - ExpoModulesCore - - ExpoKeepAwake (14.0.3): - - ExpoModulesCore - - ExpoLinearGradient (14.0.2): - - ExpoModulesCore - - ExpoLinking (7.0.5): - - ExpoModulesCore - - ExpoLocalization (16.0.1): - - ExpoModulesCore - - ExpoModulesCore (2.2.3): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsinspector - - React-NativeModulesApple - - React-RCTAppDelegate - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - ExpoNetwork (7.0.5): - - ExpoModulesCore - - ExpoSecureStore (14.2.3): - - ExpoModulesCore - - ExpoSplashScreen (0.29.24): - - ExpoModulesCore - - ExpoSymbols (0.2.2): - - ExpoModulesCore - - ExpoSystemUI (4.0.9): - - ExpoModulesCore - - ExpoWebBrowser (14.0.2): - - ExpoModulesCore - - EXUpdatesInterface (1.0.0): - - ExpoModulesCore - - fast_float (6.1.4) - - FBLazyVector (0.76.9) - - fmt (11.0.2) - - glog (0.3.5) - - hermes-engine (0.76.9): - - hermes-engine/Pre-built (= 0.76.9) - - hermes-engine/Pre-built (0.76.9) - - RCT-Folly (2024.10.14.00): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - RCT-Folly/Default (= 2024.10.14.00) - - RCT-Folly/Default (2024.10.14.00): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - RCT-Folly/Fabric (2024.10.14.00): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - RCTDeprecation (0.76.9) - - RCTRequired (0.76.9) - - RCTTypeSafety (0.76.9): - - FBLazyVector (= 0.76.9) - - RCTRequired (= 0.76.9) - - React-Core (= 0.76.9) - - React (0.76.9): - - React-Core (= 0.76.9) - - React-Core/DevSupport (= 0.76.9) - - React-Core/RCTWebSocket (= 0.76.9) - - React-RCTActionSheet (= 0.76.9) - - React-RCTAnimation (= 0.76.9) - - React-RCTBlob (= 0.76.9) - - React-RCTImage (= 0.76.9) - - React-RCTLinking (= 0.76.9) - - React-RCTNetwork (= 0.76.9) - - React-RCTSettings (= 0.76.9) - - React-RCTText (= 0.76.9) - - React-RCTVibration (= 0.76.9) - - React-callinvoker (0.76.9) - - React-Core (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default (= 0.76.9) - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/CoreModulesHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/Default (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/DevSupport (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default (= 0.76.9) - - React-Core/RCTWebSocket (= 0.76.9) - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTActionSheetHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTAnimationHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTBlobHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTImageHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTLinkingHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTNetworkHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTSettingsHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTTextHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTVibrationHeaders (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-Core/RCTWebSocket (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTDeprecation - - React-Core/Default (= 0.76.9) - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimescheduler - - React-utils - - SocketRocket (= 0.7.1) - - Yoga - - React-CoreModules (0.76.9): - - DoubleConversion - - fast_float - - fmt - - RCT-Folly - - RCTTypeSafety - - React-Core/CoreModulesHeaders - - React-jsi - - React-jsinspector - - React-NativeModulesApple - - React-RCTBlob - - React-RCTImage - - ReactCodegen - - ReactCommon - - SocketRocket - - React-cxxreact (0.76.9): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-callinvoker - - React-debug - - React-jsi - - React-jsinspector - - React-logger - - React-perflogger - - React-runtimeexecutor - - React-timing - - React-debug (0.76.9) - - React-defaultsnativemodule (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-domnativemodule - - React-Fabric - - React-featureflags - - React-featureflagsnativemodule - - React-graphics - - React-idlecallbacksnativemodule - - React-ImageManager - - React-microtasksnativemodule - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - React-domnativemodule (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-FabricComponents - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - React-Fabric (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric/animations (= 0.76.9) - - React-Fabric/attributedstring (= 0.76.9) - - React-Fabric/componentregistry (= 0.76.9) - - React-Fabric/componentregistrynative (= 0.76.9) - - React-Fabric/components (= 0.76.9) - - React-Fabric/core (= 0.76.9) - - React-Fabric/dom (= 0.76.9) - - React-Fabric/imagemanager (= 0.76.9) - - React-Fabric/leakchecker (= 0.76.9) - - React-Fabric/mounting (= 0.76.9) - - React-Fabric/observers (= 0.76.9) - - React-Fabric/scheduler (= 0.76.9) - - React-Fabric/telemetry (= 0.76.9) - - React-Fabric/templateprocessor (= 0.76.9) - - React-Fabric/uimanager (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/animations (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/attributedstring (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/componentregistry (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/componentregistrynative (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/components (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric/components/legacyviewmanagerinterop (= 0.76.9) - - React-Fabric/components/root (= 0.76.9) - - React-Fabric/components/view (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/components/legacyviewmanagerinterop (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/components/root (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/components/view (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - Yoga - - React-Fabric/core (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/dom (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/imagemanager (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/leakchecker (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/mounting (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/observers (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric/observers/events (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/observers/events (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/scheduler (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric/observers/events - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-performancetimeline - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/telemetry (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/templateprocessor (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/uimanager (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric/uimanager/consistency (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererconsistency - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-Fabric/uimanager/consistency (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererconsistency - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCommon/turbomodule/core - - React-FabricComponents (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-FabricComponents/components (= 0.76.9) - - React-FabricComponents/textlayoutmanager (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-FabricComponents/components/inputaccessory (= 0.76.9) - - React-FabricComponents/components/iostextinput (= 0.76.9) - - React-FabricComponents/components/modal (= 0.76.9) - - React-FabricComponents/components/rncore (= 0.76.9) - - React-FabricComponents/components/safeareaview (= 0.76.9) - - React-FabricComponents/components/scrollview (= 0.76.9) - - React-FabricComponents/components/text (= 0.76.9) - - React-FabricComponents/components/textinput (= 0.76.9) - - React-FabricComponents/components/unimplementedview (= 0.76.9) - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/inputaccessory (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/iostextinput (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/modal (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/rncore (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/safeareaview (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/scrollview (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/text (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/textinput (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/unimplementedview (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/textlayoutmanager (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-cxxreact - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/core - - Yoga - - React-FabricImage (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly/Fabric - - RCTRequired - - RCTTypeSafety - - React-Fabric - - React-graphics - - React-ImageManager - - React-jsi - - React-jsiexecutor - - React-logger - - React-rendererdebug - - React-utils - - ReactCommon - - Yoga - - React-featureflags (0.76.9) - - React-featureflagsnativemodule (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - React-graphics (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - RCT-Folly/Fabric - - React-jsi - - React-jsiexecutor - - React-utils - - React-hermes (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-cxxreact - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-perflogger - - React-runtimeexecutor - - React-idlecallbacksnativemodule (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - React-ImageManager (0.76.9): - - glog - - RCT-Folly/Fabric - - React-Core/Default - - React-debug - - React-Fabric - - React-graphics - - React-rendererdebug - - React-utils - - React-jserrorhandler (0.76.9): - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - React-cxxreact - - React-debug - - React-jsi - - React-jsi (0.76.9): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-jsiexecutor (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-cxxreact - - React-jsi - - React-jsinspector - - React-perflogger - - React-jsinspector (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly - - React-featureflags - - React-jsi - - React-perflogger - - React-runtimeexecutor - - React-jsitracing (0.76.9): - - React-jsi - - React-logger (0.76.9): - - glog - - React-Mapbuffer (0.76.9): - - glog - - React-debug - - React-microtasksnativemodule (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - react-native-safe-area-context (5.4.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - react-native-safe-area-context/common (= 5.4.0) - - react-native-safe-area-context/fabric (= 5.4.0) - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - react-native-safe-area-context/common (5.4.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - react-native-safe-area-context/fabric (5.4.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - react-native-safe-area-context/common - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - react-native-webview (13.12.5): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - React-nativeconfig (0.76.9) - - React-NativeModulesApple (0.76.9): - - glog - - hermes-engine - - React-callinvoker - - React-Core - - React-cxxreact - - React-jsi - - React-jsinspector - - React-runtimeexecutor - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - React-perflogger (0.76.9): - - DoubleConversion - - RCT-Folly (= 2024.10.14.00) - - React-performancetimeline (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - React-cxxreact - - React-timing - - React-RCTActionSheet (0.76.9): - - React-Core/RCTActionSheetHeaders (= 0.76.9) - - React-RCTAnimation (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - RCTTypeSafety - - React-Core/RCTAnimationHeaders - - React-jsi - - React-NativeModulesApple - - ReactCodegen - - ReactCommon - - React-RCTAppDelegate (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-CoreModules - - React-debug - - React-defaultsnativemodule - - React-Fabric - - React-featureflags - - React-graphics - - React-hermes - - React-nativeconfig - - React-NativeModulesApple - - React-RCTFabric - - React-RCTImage - - React-RCTNetwork - - React-rendererdebug - - React-RuntimeApple - - React-RuntimeCore - - React-RuntimeHermes - - React-runtimescheduler - - React-utils - - ReactCodegen - - ReactCommon - - React-RCTBlob (0.76.9): - - DoubleConversion - - fast_float - - fmt - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - React-Core/RCTBlobHeaders - - React-Core/RCTWebSocket - - React-jsi - - React-jsinspector - - React-NativeModulesApple - - React-RCTNetwork - - ReactCodegen - - ReactCommon - - React-RCTFabric (0.76.9): - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - React-Core - - React-debug - - React-Fabric - - React-FabricComponents - - React-FabricImage - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsi - - React-jsinspector - - React-nativeconfig - - React-performancetimeline - - React-RCTImage - - React-RCTText - - React-rendererconsistency - - React-rendererdebug - - React-runtimescheduler - - React-utils - - Yoga - - React-RCTImage (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - RCTTypeSafety - - React-Core/RCTImageHeaders - - React-jsi - - React-NativeModulesApple - - React-RCTNetwork - - ReactCodegen - - ReactCommon - - React-RCTLinking (0.76.9): - - React-Core/RCTLinkingHeaders (= 0.76.9) - - React-jsi (= 0.76.9) - - React-NativeModulesApple - - ReactCodegen - - ReactCommon - - ReactCommon/turbomodule/core (= 0.76.9) - - React-RCTNetwork (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - RCTTypeSafety - - React-Core/RCTNetworkHeaders - - React-jsi - - React-NativeModulesApple - - ReactCodegen - - ReactCommon - - React-RCTSettings (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - RCTTypeSafety - - React-Core/RCTSettingsHeaders - - React-jsi - - React-NativeModulesApple - - ReactCodegen - - ReactCommon - - React-RCTText (0.76.9): - - React-Core/RCTTextHeaders (= 0.76.9) - - Yoga - - React-RCTVibration (0.76.9): - - RCT-Folly (= 2024.10.14.00) - - React-Core/RCTVibrationHeaders - - React-jsi - - React-NativeModulesApple - - ReactCodegen - - ReactCommon - - React-rendererconsistency (0.76.9) - - React-rendererdebug (0.76.9): - - DoubleConversion - - fast_float - - fmt - - RCT-Folly - - React-debug - - React-rncore (0.76.9) - - React-RuntimeApple (0.76.9): - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - React-callinvoker - - React-Core/Default - - React-CoreModules - - React-cxxreact - - React-jserrorhandler - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-Mapbuffer - - React-NativeModulesApple - - React-RCTFabric - - React-RuntimeCore - - React-runtimeexecutor - - React-RuntimeHermes - - React-runtimescheduler - - React-utils - - React-RuntimeCore (0.76.9): - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - React-cxxreact - - React-featureflags - - React-jserrorhandler - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-performancetimeline - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - React-runtimeexecutor (0.76.9): - - React-jsi (= 0.76.9) - - React-RuntimeHermes (0.76.9): - - hermes-engine - - RCT-Folly/Fabric (= 2024.10.14.00) - - React-featureflags - - React-hermes - - React-jsi - - React-jsinspector - - React-jsitracing - - React-nativeconfig - - React-RuntimeCore - - React-utils - - React-runtimescheduler (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - React-callinvoker - - React-cxxreact - - React-debug - - React-featureflags - - React-jsi - - React-performancetimeline - - React-rendererconsistency - - React-rendererdebug - - React-runtimeexecutor - - React-timing - - React-utils - - React-timing (0.76.9) - - React-utils (0.76.9): - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - React-debug - - React-jsi (= 0.76.9) - - ReactCodegen (0.76.9): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-FabricImage - - React-featureflags - - React-graphics - - React-jsi - - React-jsiexecutor - - React-NativeModulesApple - - React-rendererdebug - - React-utils - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - ReactCommon (0.76.9): - - ReactCommon/turbomodule (= 0.76.9) - - ReactCommon/turbomodule (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-callinvoker - - React-cxxreact - - React-jsi - - React-logger - - React-perflogger - - ReactCommon/turbomodule/bridging (= 0.76.9) - - ReactCommon/turbomodule/core (= 0.76.9) - - ReactCommon/turbomodule/bridging (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-callinvoker - - React-cxxreact - - React-jsi (= 0.76.9) - - React-logger - - React-perflogger - - ReactCommon/turbomodule/core (0.76.9): - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - React-callinvoker - - React-cxxreact - - React-debug (= 0.76.9) - - React-featureflags (= 0.76.9) - - React-jsi - - React-logger - - React-perflogger - - React-utils (= 0.76.9) - - RNFlashList (1.7.3): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - RNGestureHandler (2.20.2): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - RNReanimated (3.16.7): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - RNReanimated/reanimated (= 3.16.7) - - RNReanimated/worklets (= 3.16.7) - - Yoga - - RNReanimated/reanimated (3.16.7): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - RNReanimated/reanimated/apple (= 3.16.7) - - Yoga - - RNReanimated/reanimated/apple (3.16.7): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - RNReanimated/worklets (3.16.7): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - RNScreens (4.4.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-RCTImage - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - RNScreens/common (= 4.4.0) - - Yoga - - RNScreens/common (4.4.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-RCTImage - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - RNSentry (6.15.1): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-hermes - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Sentry/HybridSDK (= 8.52.1) - - Yoga - - RNSVG (15.12.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - RNSVG/common (= 15.12.0) - - Yoga - - RNSVG/common (15.12.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - Sentry/HybridSDK (8.52.1) - - SocketRocket (0.7.1) - - Yoga (0.0.0) - -DEPENDENCIES: - - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - EXConstants (from `../node_modules/expo-constants/ios`) - - EXJSONUtils (from `../node_modules/expo-json-utils/ios`) - - EXManifests (from `../node_modules/expo-manifests/ios`) - - Expo (from `../node_modules/expo`) - - expo-dev-client (from `../node_modules/expo-dev-client/ios`) - - expo-dev-launcher (from `../node_modules/expo-dev-launcher`) - - expo-dev-menu (from `../node_modules/expo-dev-menu`) - - expo-dev-menu-interface (from `../node_modules/expo-dev-menu-interface/ios`) - - ExpoAsset (from `../node_modules/expo-asset/ios`) - - ExpoBlur (from `../node_modules/expo-blur/ios`) - - ExpoFileSystem (from `../node_modules/expo-file-system/ios`) - - ExpoFont (from `../node_modules/expo-font/ios`) - - ExpoHaptics (from `../node_modules/expo-haptics/ios`) - - ExpoHead (from `../node_modules/expo-router/ios`) - - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) - - ExpoLinearGradient (from `../node_modules/expo-linear-gradient/ios`) - - ExpoLinking (from `../node_modules/expo-linking/ios`) - - ExpoLocalization (from `../node_modules/expo-localization/ios`) - - ExpoModulesCore (from `../node_modules/expo-modules-core`) - - ExpoNetwork (from `../node_modules/expo-network/ios`) - - ExpoSecureStore (from `../node_modules/expo-secure-store/ios`) - - ExpoSplashScreen (from `../node_modules/expo-splash-screen/ios`) - - ExpoSymbols (from `../node_modules/expo-symbols/ios`) - - ExpoSystemUI (from `../node_modules/expo-system-ui/ios`) - - ExpoWebBrowser (from `../node_modules/expo-web-browser/ios`) - - EXUpdatesInterface (from `../node_modules/expo-updates-interface/ios`) - - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - - React (from `../node_modules/react-native/`) - - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - - React-Core (from `../node_modules/react-native/`) - - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) - - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) - - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) - - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) - - React-Fabric (from `../node_modules/react-native/ReactCommon`) - - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) - - React-FabricImage (from `../node_modules/react-native/ReactCommon`) - - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) - - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) - - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) - - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) - - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) - - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) - - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) - - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) - - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) - - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) - - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) - - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - - react-native-webview (from `../node_modules/react-native-webview`) - - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) - - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) - - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) - - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) - - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) - - React-RCTFabric (from `../node_modules/react-native/React`) - - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) - - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) - - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) - - React-rncore (from `../node_modules/react-native/ReactCommon`) - - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - - React-timing (from `../node_modules/react-native/ReactCommon/react/timing`) - - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - - ReactCodegen (from `build/generated/ios`) - - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - - RNReanimated (from `../node_modules/react-native-reanimated`) - - RNScreens (from `../node_modules/react-native-screens`) - - "RNSentry (from `../node_modules/@sentry/react-native`)" - - RNSVG (from `../node_modules/react-native-svg`) - - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) - -SPEC REPOS: - trunk: - - Sentry - - SocketRocket - -EXTERNAL SOURCES: - boost: - :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" - DoubleConversion: - :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" - EXConstants: - :path: "../node_modules/expo-constants/ios" - EXJSONUtils: - :path: "../node_modules/expo-json-utils/ios" - EXManifests: - :path: "../node_modules/expo-manifests/ios" - Expo: - :path: "../node_modules/expo" - expo-dev-client: - :path: "../node_modules/expo-dev-client/ios" - expo-dev-launcher: - :path: "../node_modules/expo-dev-launcher" - expo-dev-menu: - :path: "../node_modules/expo-dev-menu" - expo-dev-menu-interface: - :path: "../node_modules/expo-dev-menu-interface/ios" - ExpoAsset: - :path: "../node_modules/expo-asset/ios" - ExpoBlur: - :path: "../node_modules/expo-blur/ios" - ExpoFileSystem: - :path: "../node_modules/expo-file-system/ios" - ExpoFont: - :path: "../node_modules/expo-font/ios" - ExpoHaptics: - :path: "../node_modules/expo-haptics/ios" - ExpoHead: - :path: "../node_modules/expo-router/ios" - ExpoKeepAwake: - :path: "../node_modules/expo-keep-awake/ios" - ExpoLinearGradient: - :path: "../node_modules/expo-linear-gradient/ios" - ExpoLinking: - :path: "../node_modules/expo-linking/ios" - ExpoLocalization: - :path: "../node_modules/expo-localization/ios" - ExpoModulesCore: - :path: "../node_modules/expo-modules-core" - ExpoNetwork: - :path: "../node_modules/expo-network/ios" - ExpoSecureStore: - :path: "../node_modules/expo-secure-store/ios" - ExpoSplashScreen: - :path: "../node_modules/expo-splash-screen/ios" - ExpoSymbols: - :path: "../node_modules/expo-symbols/ios" - ExpoSystemUI: - :path: "../node_modules/expo-system-ui/ios" - ExpoWebBrowser: - :path: "../node_modules/expo-web-browser/ios" - EXUpdatesInterface: - :path: "../node_modules/expo-updates-interface/ios" - fast_float: - :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" - FBLazyVector: - :path: "../node_modules/react-native/Libraries/FBLazyVector" - fmt: - :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" - glog: - :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" - hermes-engine: - :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" - :tag: hermes-2024-11-12-RNv0.76.2-5b4aa20c719830dcf5684832b89a6edb95ac3d64 - RCT-Folly: - :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" - RCTDeprecation: - :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" - RCTRequired: - :path: "../node_modules/react-native/Libraries/Required" - RCTTypeSafety: - :path: "../node_modules/react-native/Libraries/TypeSafety" - React: - :path: "../node_modules/react-native/" - React-callinvoker: - :path: "../node_modules/react-native/ReactCommon/callinvoker" - React-Core: - :path: "../node_modules/react-native/" - React-CoreModules: - :path: "../node_modules/react-native/React/CoreModules" - React-cxxreact: - :path: "../node_modules/react-native/ReactCommon/cxxreact" - React-debug: - :path: "../node_modules/react-native/ReactCommon/react/debug" - React-defaultsnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" - React-domnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" - React-Fabric: - :path: "../node_modules/react-native/ReactCommon" - React-FabricComponents: - :path: "../node_modules/react-native/ReactCommon" - React-FabricImage: - :path: "../node_modules/react-native/ReactCommon" - React-featureflags: - :path: "../node_modules/react-native/ReactCommon/react/featureflags" - React-featureflagsnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" - React-graphics: - :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" - React-hermes: - :path: "../node_modules/react-native/ReactCommon/hermes" - React-idlecallbacksnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" - React-ImageManager: - :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" - React-jserrorhandler: - :path: "../node_modules/react-native/ReactCommon/jserrorhandler" - React-jsi: - :path: "../node_modules/react-native/ReactCommon/jsi" - React-jsiexecutor: - :path: "../node_modules/react-native/ReactCommon/jsiexecutor" - React-jsinspector: - :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" - React-jsitracing: - :path: "../node_modules/react-native/ReactCommon/hermes/executor/" - React-logger: - :path: "../node_modules/react-native/ReactCommon/logger" - React-Mapbuffer: - :path: "../node_modules/react-native/ReactCommon" - React-microtasksnativemodule: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" - react-native-safe-area-context: - :path: "../node_modules/react-native-safe-area-context" - react-native-webview: - :path: "../node_modules/react-native-webview" - React-nativeconfig: - :path: "../node_modules/react-native/ReactCommon" - React-NativeModulesApple: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" - React-perflogger: - :path: "../node_modules/react-native/ReactCommon/reactperflogger" - React-performancetimeline: - :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" - React-RCTActionSheet: - :path: "../node_modules/react-native/Libraries/ActionSheetIOS" - React-RCTAnimation: - :path: "../node_modules/react-native/Libraries/NativeAnimation" - React-RCTAppDelegate: - :path: "../node_modules/react-native/Libraries/AppDelegate" - React-RCTBlob: - :path: "../node_modules/react-native/Libraries/Blob" - React-RCTFabric: - :path: "../node_modules/react-native/React" - React-RCTImage: - :path: "../node_modules/react-native/Libraries/Image" - React-RCTLinking: - :path: "../node_modules/react-native/Libraries/LinkingIOS" - React-RCTNetwork: - :path: "../node_modules/react-native/Libraries/Network" - React-RCTSettings: - :path: "../node_modules/react-native/Libraries/Settings" - React-RCTText: - :path: "../node_modules/react-native/Libraries/Text" - React-RCTVibration: - :path: "../node_modules/react-native/Libraries/Vibration" - React-rendererconsistency: - :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" - React-rendererdebug: - :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" - React-rncore: - :path: "../node_modules/react-native/ReactCommon" - React-RuntimeApple: - :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" - React-RuntimeCore: - :path: "../node_modules/react-native/ReactCommon/react/runtime" - React-runtimeexecutor: - :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" - React-RuntimeHermes: - :path: "../node_modules/react-native/ReactCommon/react/runtime" - React-runtimescheduler: - :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" - React-timing: - :path: "../node_modules/react-native/ReactCommon/react/timing" - React-utils: - :path: "../node_modules/react-native/ReactCommon/react/utils" - ReactCodegen: - :path: build/generated/ios - ReactCommon: - :path: "../node_modules/react-native/ReactCommon" - RNFlashList: - :path: "../node_modules/@shopify/flash-list" - RNGestureHandler: - :path: "../node_modules/react-native-gesture-handler" - RNReanimated: - :path: "../node_modules/react-native-reanimated" - RNScreens: - :path: "../node_modules/react-native-screens" - RNSentry: - :path: "../node_modules/@sentry/react-native" - RNSVG: - :path: "../node_modules/react-native-svg" - Yoga: - :path: "../node_modules/react-native/ReactCommon/yoga" - -SPEC CHECKSUMS: - boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 - EXConstants: fcfc75800824ac2d5c592b5bc74130bad17b146b - EXJSONUtils: 01fc7492b66c234e395dcffdd5f53439c5c29c93 - EXManifests: a19d50504b8826546a4782770317bc83fffec87d - Expo: a6ff273c618506b12129a0d06f2a08201bfbcf43 - expo-dev-client: db44302cdbe0ec55b0ef1849c9a23a76dec6dbac - expo-dev-launcher: 792cd1c83fbec4a1a66fe91a0c283368dbad851c - expo-dev-menu: dd3197d2b0107ee036ffd85f95e75a950ab52ada - expo-dev-menu-interface: 00dc42302a72722fdecec3fa048de84a9133bcc4 - ExpoAsset: 48386d40d53a8c1738929b3ed509bcad595b5516 - ExpoBlur: 392c1207f71d0ecf22371621c1fbd44ba84d9742 - ExpoFileSystem: 42d363d3b96f9afab980dcef60d5657a4443c655 - ExpoFont: f354e926f8feae5e831ec8087f36652b44a0b188 - ExpoHaptics: 8d199b2f33245ea85289ff6c954c7ee7c00a5b5d - ExpoHead: df924203fbf8e0913fc38b0f6aec71f9a9115482 - ExpoKeepAwake: b0171a73665bfcefcfcc311742a72a956e6aa680 - ExpoLinearGradient: 35ebd83b16f80b3add053a2fd68cc328ed927f60 - ExpoLinking: 8d12bee174ba0cdf31239706578e29e74a417402 - ExpoLocalization: 7776ea3bdb112125390745bbaf919b734b2ad1c7 - ExpoModulesCore: c25d77625038b1968ea1afefc719862c0d8dd993 - ExpoNetwork: 16083eb5ed34ce1c8e916fb6292fdb6e9daac0ca - ExpoSecureStore: b367d9f62c9102d808afbeb1561636d4276e439d - ExpoSplashScreen: 8261985ce9778f904abc7e31bed3538dce67ed4d - ExpoSymbols: f3002db15156cd4e505c77b6ea1df5c984db9965 - ExpoSystemUI: b82a45cf0f6a4fa18d07c46deba8725dd27688b4 - ExpoWebBrowser: a212e6b480d8857d3e441fba51e0c968333803b3 - EXUpdatesInterface: 7c977640bdd8b85833c19e3959ba46145c5719db - fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 - FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 - fmt: 01b82d4ca6470831d1cc0852a1af644be019e8f6 - glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a - hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 - RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 - RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 - RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 - RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f - React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d - React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea - React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245 - React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c - React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab - React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: 18a684542f82ce1897552a1c4b847be414c9566e - React-domnativemodule: 90bdd4ec3ab38c47cfc3461c1e9283a8507d613f - React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b - React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520 - React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576 - React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 742a8325b3c821d2a1ca13a6d2a0fc72d04555e0 - React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121 - React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf - React-idlecallbacksnativemodule: d61d9c9816131bf70d3d80cd04889fc625ee523f - React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020 - React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6 - React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d - React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893 - React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086 - React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f - React-logger: c4052eb941cca9a097ef01b59543a656dc088559 - React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de - React-microtasksnativemodule: d80ff86c8902872d397d9622f1a97aadcc12cead - react-native-safe-area-context: c68127652d8b9a26a28ac9597167a3ad90bcd713 - react-native-webview: 6b9fc65c1951203a3e958ff3cc0a858d4b6be901 - React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e - React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358 - React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc - React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 - React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585 - React-RCTAppDelegate: 345a6f1b82abc578437df0ce7e9c48740eca827c - React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6 - React-RCTFabric: 007b1a98201cc49b5bc6e1417d7fe3f6fc6e2b78 - React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8 - React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa - React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7 - React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223 - React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf - React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78 - React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec - React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd - React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb - React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385 - React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d - React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f - ReactCodegen: f853a20cc9125c5521c8766b4b49375fec20648b - ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9 - RNFlashList: 648e2273693600985aaa72a2ef4700e815500901 - RNGestureHandler: fffddeb8af59709c6d8de11b6461a6af63cad532 - RNReanimated: 2e5069649cbab2c946652d3b97589b2ae0526220 - RNScreens: 362f4c861dd155f898908d5035d97b07a3f1a9d1 - RNSentry: ac378c5d235ecca7b574e09d9b293bb54217702d - RNSVG: 43aff28bae846abe9c45625fe8b4816b7ac73ffd - Sentry: 2cbbe3592f30050c60e916c63c7f5a2fa584005e - SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a - -PODFILE CHECKSUM: 7a7ccff6bc339e796d8f4af447bc877134e30656 - -COCOAPODS: 1.16.2 diff --git a/apps/mobile-legacy/ios/Podfile.properties.json b/apps/mobile-legacy/ios/Podfile.properties.json deleted file mode 100644 index 4f49b45..0000000 --- a/apps/mobile-legacy/ios/Podfile.properties.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "apple.ccacheEnabled": "false", - "apple.extraPods": "[]", - "apple.privacyManifestAggregationEnabled": "true", - "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true", - "expo.jsEngine": "hermes", - "newArchEnabled": "true" -} diff --git a/apps/mobile-legacy/ios/basango.xcodeproj/project.pbxproj b/apps/mobile-legacy/ios/basango.xcodeproj/project.pbxproj deleted file mode 100644 index 03f3d68..0000000 --- a/apps/mobile-legacy/ios/basango.xcodeproj/project.pbxproj +++ /dev/null @@ -1,565 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 0D69ABF8EEB29427A043785F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 9DE5E024F189A356EEB9F5D1 /* PrivacyInfo.xcprivacy */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; - 96905EF65AED1B983A6B3ABC /* libPods-basango.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-basango.a */; }; - B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; - BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; - D6C1E8B6278B4781963A5DB0 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4814CA95824883B35DE226 /* noop-file.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 13B07F961A680F5B00A75B9A /* basango.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = basango.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = basango/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = basango/AppDelegate.mm; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = basango/Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = basango/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = basango/main.m; sourceTree = ""; }; - 2264613BCB764C70A47FCD56 /* basango-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "basango-Bridging-Header.h"; path = "basango/basango-Bridging-Header.h"; sourceTree = ""; }; - 4C4814CA95824883B35DE226 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "basango/noop-file.swift"; sourceTree = ""; }; - 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-basango.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-basango.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6C2E3173556A471DD304B334 /* Pods-basango.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-basango.debug.xcconfig"; path = "Target Support Files/Pods-basango/Pods-basango.debug.xcconfig"; sourceTree = ""; }; - 7A4D352CD337FB3A3BF06240 /* Pods-basango.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-basango.release.xcconfig"; path = "Target Support Files/Pods-basango/Pods-basango.release.xcconfig"; sourceTree = ""; }; - 9DE5E024F189A356EEB9F5D1 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = basango/PrivacyInfo.xcprivacy; sourceTree = ""; }; - AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = basango/SplashScreen.storyboard; sourceTree = ""; }; - BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; }; - ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; - FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-basango/ExpoModulesProvider.swift"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 96905EF65AED1B983A6B3ABC /* libPods-basango.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 13B07FAE1A68108700A75B9A /* basango */ = { - isa = PBXGroup; - children = ( - BB2F792B24A3F905000567C9 /* Supporting */, - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.mm */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, - 13B07FB61A68108700A75B9A /* Info.plist */, - 13B07FB71A68108700A75B9A /* main.m */, - AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */, - 4C4814CA95824883B35DE226 /* noop-file.swift */, - 2264613BCB764C70A47FCD56 /* basango-Bridging-Header.h */, - 9DE5E024F189A356EEB9F5D1 /* PrivacyInfo.xcprivacy */, - ); - name = basango; - sourceTree = ""; - }; - 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { - isa = PBXGroup; - children = ( - ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-basango.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 832341AE1AAA6A7D00B99B32 /* Libraries */ = { - isa = PBXGroup; - children = ( - ); - name = Libraries; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 13B07FAE1A68108700A75B9A /* basango */, - 832341AE1AAA6A7D00B99B32 /* Libraries */, - 83CBBA001A601CBA00E9B192 /* Products */, - 2D16E6871FA4F8E400B85C8A /* Frameworks */, - D65327D7A22EEC0BE12398D9 /* Pods */, - D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - usesTabs = 0; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 13B07F961A680F5B00A75B9A /* basango.app */, - ); - name = Products; - sourceTree = ""; - }; - 92DBD88DE9BF7D494EA9DA96 /* basango */ = { - isa = PBXGroup; - children = ( - FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */, - ); - name = basango; - sourceTree = ""; - }; - BB2F792B24A3F905000567C9 /* Supporting */ = { - isa = PBXGroup; - children = ( - BB2F792C24A3F905000567C9 /* Expo.plist */, - ); - name = Supporting; - path = basango/Supporting; - sourceTree = ""; - }; - D65327D7A22EEC0BE12398D9 /* Pods */ = { - isa = PBXGroup; - children = ( - 6C2E3173556A471DD304B334 /* Pods-basango.debug.xcconfig */, - 7A4D352CD337FB3A3BF06240 /* Pods-basango.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = { - isa = PBXGroup; - children = ( - 92DBD88DE9BF7D494EA9DA96 /* basango */, - ); - name = ExpoModulesProviders; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 13B07F861A680F5B00A75B9A /* basango */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "basango" */; - buildPhases = ( - 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, - 0A61F537D76D10E28EF7006E /* [Expo] Configure project */, - 13B07F871A680F5B00A75B9A /* Sources */, - 13B07F8C1A680F5B00A75B9A /* Frameworks */, - 13B07F8E1A680F5B00A75B9A /* Resources */, - 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */, - DE3CCC0BC1F2407AA25D401D /* Upload Debug Symbols to Sentry */, - D5E940B01E8D732996FFACA7 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = basango; - productName = basango; - productReference = 13B07F961A680F5B00A75B9A /* basango.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1130; - TargetAttributes = { - 13B07F861A680F5B00A75B9A = { - LastSwiftMigration = 1250; - }; - }; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "basango" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 13B07F861A680F5B00A75B9A /* basango */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 13B07F8E1A680F5B00A75B9A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BB2F792D24A3F905000567C9 /* Expo.plist in Resources */, - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, - 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */, - 0D69ABF8EEB29427A043785F /* PrivacyInfo.xcprivacy in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Bundle React Native code and images"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n/bin/sh `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"` `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; - }; - 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-basango-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 0A61F537D76D10E28EF7006E /* [Expo] Configure project */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "[Expo] Configure project"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-basango/expo-configure-project.sh\"\n"; - }; - 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-basango/Pods-basango-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoLocalization/ExpoLocalization_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/Sentry/Sentry.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoLocalization_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Sentry.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-basango/Pods-basango-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - D5E940B01E8D732996FFACA7 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-basango/Pods-basango-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-basango/Pods-basango-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - DE3CCC0BC1F2407AA25D401D /* Upload Debug Symbols to Sentry */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Upload Debug Symbols to Sentry"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh `${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 13B07F871A680F5B00A75B9A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, - B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */, - D6C1E8B6278B4781963A5DB0 /* noop-file.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 13B07F941A680F5B00A75B9A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-basango.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = basango/basango.entitlements; - CURRENT_PROJECT_VERSION = 1; - ENABLE_BITCODE = NO; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "FB_SONARKIT_ENABLED=1", - ); - INFOPLIST_FILE = basango/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-ObjC", - "-lc++", - ); - OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; - PRODUCT_BUNDLE_IDENTIFIER = dev.ngandu.basango; - PRODUCT_NAME = basango; - SWIFT_OBJC_BRIDGING_HEADER = "basango/basango-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 13B07F951A680F5B00A75B9A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-basango.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = basango/basango.entitlements; - CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = basango/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-ObjC", - "-lc++", - ); - OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; - PRODUCT_BUNDLE_IDENTIFIER = dev.ngandu.basango; - PRODUCT_NAME = basango; - SWIFT_OBJC_BRIDGING_HEADER = "basango/basango-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++20"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; - LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; - USE_HERMES = true; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++20"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; - LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; - SDKROOT = iphoneos; - USE_HERMES = true; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "basango" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug */, - 13B07F951A680F5B00A75B9A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "basango" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/apps/mobile-legacy/ios/basango.xcodeproj/xcshareddata/xcschemes/basango.xcscheme b/apps/mobile-legacy/ios/basango.xcodeproj/xcshareddata/xcschemes/basango.xcscheme deleted file mode 100644 index 5bc0c43..0000000 --- a/apps/mobile-legacy/ios/basango.xcodeproj/xcshareddata/xcschemes/basango.xcscheme +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile-legacy/ios/basango.xcworkspace/contents.xcworkspacedata b/apps/mobile-legacy/ios/basango.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 47b0cbf..0000000 --- a/apps/mobile-legacy/ios/basango.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/mobile-legacy/ios/basango/AppDelegate.h b/apps/mobile-legacy/ios/basango/AppDelegate.h deleted file mode 100644 index 1658a43..0000000 --- a/apps/mobile-legacy/ios/basango/AppDelegate.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import -#import - -@interface AppDelegate : EXAppDelegateWrapper - -@end diff --git a/apps/mobile-legacy/ios/basango/AppDelegate.mm b/apps/mobile-legacy/ios/basango/AppDelegate.mm deleted file mode 100644 index b27f832..0000000 --- a/apps/mobile-legacy/ios/basango/AppDelegate.mm +++ /dev/null @@ -1,62 +0,0 @@ -#import "AppDelegate.h" - -#import -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - self.moduleName = @"main"; - - // You can add your custom initial props in the dictionary below. - // They will be passed down to the ViewController used by React Native. - self.initialProps = @{}; - - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge -{ - return [self bundleURL]; -} - -- (NSURL *)bundleURL -{ -#if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"]; -#else - return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; -#endif -} - -// Linking API -- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options { - return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options]; -} - -// Universal Links -- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { - BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; - return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result; -} - -// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; -} - -// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries -- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error -{ - return [super application:application didFailToRegisterForRemoteNotificationsWithError:error]; -} - -// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler -{ - return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; -} - -@end diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png b/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png deleted file mode 100644 index 6bbd117..0000000 Binary files a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png and /dev/null differ diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 4da364a..0000000 --- a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "images": [ - { - "filename": "App-Icon-1024x1024@1x.png", - "idiom": "universal", - "platform": "ios", - "size": "1024x1024" - } - ], - "info": { - "author": "expo", - "version": 1 - } -} diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json deleted file mode 100644 index 0b946fb..0000000 --- a/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info": { - "author": "expo", - "version": 1 - } -} diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json deleted file mode 100644 index c640711..0000000 --- a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "colors": [ - { - "color": { - "color-space": "srgb", - "components": { - "alpha": "1.000", - "blue": "1.00000000000000", - "green": "1.00000000000000", - "red": "1.00000000000000" - } - }, - "idiom": "universal" - } - ], - "info": { - "author": "expo", - "version": 1 - } -} diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json deleted file mode 100644 index f5ad720..0000000 --- a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images": [ - { - "filename": "image.png", - "idiom": "universal", - "scale": "1x" - }, - { - "filename": "image@2x.png", - "idiom": "universal", - "scale": "2x" - }, - { - "filename": "image@3x.png", - "idiom": "universal", - "scale": "3x" - } - ], - "info": { - "author": "expo", - "version": 1 - } -} diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image.png b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image.png deleted file mode 100644 index f65f73d..0000000 Binary files a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image.png and /dev/null differ diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@2x.png b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@2x.png deleted file mode 100644 index 5bf009f..0000000 Binary files a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@2x.png and /dev/null differ diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@3x.png b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@3x.png deleted file mode 100644 index 470ce64..0000000 Binary files a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/image@3x.png and /dev/null differ diff --git a/apps/mobile-legacy/ios/basango/Info.plist b/apps/mobile-legacy/ios/basango/Info.plist deleted file mode 100644 index 91247bd..0000000 --- a/apps/mobile-legacy/ios/basango/Info.plist +++ /dev/null @@ -1,85 +0,0 @@ - - - - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - basango - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0.0 - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - basango - dev.ngandu.basango - - - - CFBundleURLSchemes - - exp+basango - - - - CFBundleVersion - 1 - LSMinimumSystemVersion - 12.0 - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - NSUserActivityTypes - - $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route - - UILaunchStoryboardName - SplashScreen - UIRequiredDeviceCapabilities - - arm64 - - UIRequiresFullScreen - - UIStatusBarStyle - UIStatusBarStyleDefault - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIUserInterfaceStyle - Automatic - UIViewControllerBasedStatusBarAppearance - - - \ No newline at end of file diff --git a/apps/mobile-legacy/ios/basango/PrivacyInfo.xcprivacy b/apps/mobile-legacy/ios/basango/PrivacyInfo.xcprivacy deleted file mode 100644 index 5bb83c5..0000000 --- a/apps/mobile-legacy/ios/basango/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,48 +0,0 @@ - - - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - 0A2A.1 - 3B52.1 - C617.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace - NSPrivacyAccessedAPITypeReasons - - E174.1 - 85F4.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - - NSPrivacyCollectedDataTypes - - NSPrivacyTracking - - - diff --git a/apps/mobile-legacy/ios/basango/SplashScreen.storyboard b/apps/mobile-legacy/ios/basango/SplashScreen.storyboard deleted file mode 100644 index 158767f..0000000 --- a/apps/mobile-legacy/ios/basango/SplashScreen.storyboard +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/apps/mobile-legacy/ios/basango/Supporting/Expo.plist b/apps/mobile-legacy/ios/basango/Supporting/Expo.plist deleted file mode 100644 index 750be02..0000000 --- a/apps/mobile-legacy/ios/basango/Supporting/Expo.plist +++ /dev/null @@ -1,12 +0,0 @@ - - - - - EXUpdatesCheckOnLaunch - ALWAYS - EXUpdatesEnabled - - EXUpdatesLaunchWaitMs - 0 - - \ No newline at end of file diff --git a/apps/mobile-legacy/ios/basango/basango-Bridging-Header.h b/apps/mobile-legacy/ios/basango/basango-Bridging-Header.h deleted file mode 100644 index e11d920..0000000 --- a/apps/mobile-legacy/ios/basango/basango-Bridging-Header.h +++ /dev/null @@ -1,3 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// diff --git a/apps/mobile-legacy/ios/basango/basango.entitlements b/apps/mobile-legacy/ios/basango/basango.entitlements deleted file mode 100644 index f683276..0000000 --- a/apps/mobile-legacy/ios/basango/basango.entitlements +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/apps/mobile-legacy/ios/basango/main.m b/apps/mobile-legacy/ios/basango/main.m deleted file mode 100644 index 25181b6..0000000 --- a/apps/mobile-legacy/ios/basango/main.m +++ /dev/null @@ -1,10 +0,0 @@ -#import - -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} - diff --git a/apps/mobile-legacy/ios/basango/noop-file.swift b/apps/mobile-legacy/ios/basango/noop-file.swift deleted file mode 100644 index b2ffafb..0000000 --- a/apps/mobile-legacy/ios/basango/noop-file.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// @generated -// A blank Swift file must be created for native modules with Swift files to work correctly. -// diff --git a/apps/mobile-legacy/ios/sentry.properties b/apps/mobile-legacy/ios/sentry.properties deleted file mode 100644 index de32d60..0000000 --- a/apps/mobile-legacy/ios/sentry.properties +++ /dev/null @@ -1,4 +0,0 @@ -defaults.url=https://glitchtip.devscast.tech/ -defaults.org=devscast-software -defaults.project=basango -# Using SENTRY_AUTH_TOKEN environment variable \ No newline at end of file diff --git a/apps/mobile-legacy/metro.config.js b/apps/mobile-legacy/metro.config.js deleted file mode 100644 index 15d922a..0000000 --- a/apps/mobile-legacy/metro.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const { getSentryExpoConfig } = require("@sentry/react-native/metro"); - -/** @type {import('expo/metro-config').MetroConfig} */ -const config = getSentryExpoConfig(__dirname); - -module.exports = config; diff --git a/apps/mobile-legacy/src/api/client.ts b/apps/mobile-legacy/src/api/client.ts deleted file mode 100644 index 508173d..0000000 --- a/apps/mobile-legacy/src/api/client.ts +++ /dev/null @@ -1,117 +0,0 @@ -import axios, { AxiosInstance } from "axios"; - -import { RefreshTokenPayload, RefreshTokenResponse } from "@/api/schema/identity-and-access/login"; -import { clearTokens, getAccessToken, getRefreshToken, setTokens } from "@/store/auth"; - -const endpoint = process.env.EXPO_PUBLIC_API_URL!; -const client: AxiosInstance = axios.create({ - baseURL: endpoint, - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, -}); - -let isAuthTokenRefreshing = false; -let failedRequestsQueue: ((token: string) => void)[] = []; - -const processFailedRequestsQueue = (token: string) => { - failedRequestsQueue.forEach((callback) => callback(token)); - failedRequestsQueue = []; -}; - -// Wait for 120 seconds before timing out -axios.interceptors.request.use((config) => { - config.timeout = 120_000; - return config; -}); - -// Add the Authorization header to all requests -client.interceptors.request.use(async (config) => { - const token = await getAccessToken(); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - - return config; -}); - -// Handle 401 errors and refresh the token -client.interceptors.response.use( - (response) => response, - async (error) => { - const originalRequest = error.config; - const status = error.response?.status; - - if (status === 401 && !originalRequest._retry) { - originalRequest._retry = true; - - if (isAuthTokenRefreshing) { - return new Promise((resolve) => { - failedRequestsQueue.push((token: string) => { - originalRequest.headers.Authorization = `Bearer ${token}`; - resolve(client(originalRequest)); - }); - }); - } - - isAuthTokenRefreshing = true; - - try { - const refreshToken = await getRefreshToken(); - if (!refreshToken) { - await clearTokens(); - return Promise.reject(error); - } - - const response = await axios.post(`${endpoint}/token/refresh`, { - refresh_token: refreshToken, - } as RefreshTokenPayload); - - const updatedToken = response.data.token; - await setTokens(updatedToken, refreshToken); - processFailedRequestsQueue(updatedToken); - - originalRequest.headers.Authorization = `Bearer ${updatedToken}`; - return client(originalRequest); - } catch (error) { - await clearTokens(); - return Promise.reject(error); - } finally { - isAuthTokenRefreshing = false; - } - } - - return Promise.reject(error); - }, -); - -if (__DEV__) { - // Log HTTP requests and responses - client.interceptors.request.use( - async (config) => { - console.log("HTTP REQUEST", { - baseURL: config.baseURL, - data: config.data, - url: config.url, - }); - - return config; - }, - (error) => console.log(JSON.stringify(error)), - ); - - client.interceptors.response.use( - (response) => { - console.log("HTTP RESPONSE", { - data: response.data, - stats: response.status, - }); - - return response; - }, - (error) => console.log(JSON.stringify(error)), - ); -} - -export default client; diff --git a/apps/mobile-legacy/src/api/endpoint.ts b/apps/mobile-legacy/src/api/endpoint.ts deleted file mode 100644 index b467d09..0000000 --- a/apps/mobile-legacy/src/api/endpoint.ts +++ /dev/null @@ -1,33 +0,0 @@ -export const endpoint = { - feedManagement: { - addArticleToBookmark: (bookmarkId: string, articleId: string) => - `feed/bookmarks/${bookmarkId}/articles/${articleId}`, - addCommentToArticle: (articleId: string) => `/feed/articles/${articleId}/comments`, - createBookmark: `/feed/bookmarks`, - deleteBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`, - followSource: (sourceId: string) => `/feed/sources/${sourceId}/follow`, - getArticleCommentList: (articleId: string) => `/feed/articles/${articleId}/comments`, - getArticleDetails: (articleId: string) => `/feed/articles/${articleId}`, - getArticleOverviewList: `/feed/articles`, - getBookmarkedArticlesList: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}/articles`, - getBookmarkList: `/feed/bookmarks`, - getSourceArticleOverviewList: (sourceId: string) => `/feed/sources/${sourceId}/articles`, - getSourceDetails: (sourceId: string) => `/feed/sources/${sourceId}`, - getSourceOverviewList: `/feed/sources`, - removeArticleFromBookmark: (bookmarkId: string, articleId: string) => - `/feed/bookmarks/${bookmarkId}/articles/${articleId}`, - unfollowSource: (sourceId: string) => `/feed/sources/${sourceId}/unfollow`, - updateBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`, - }, - identityAndAccess: { - confirmAccount: (token: string) => `/account/confirm/${token}`, - getUserProfile: "/me", - login: "/login_check", - logout: "/token/invalidate", - register: "/register", - requestPassword: "/password/request", - resetPassword: (token: string) => `/password/reset/${token}`, - unlockAccount: (token: string) => `/account/unlock/${token}`, - updatePassword: "/password/update", - }, -}; diff --git a/apps/mobile-legacy/src/api/request/feed-management/article.ts b/apps/mobile-legacy/src/api/request/feed-management/article.ts deleted file mode 100644 index 5b2c545..0000000 --- a/apps/mobile-legacy/src/api/request/feed-management/article.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { Article, ArticleOverview, TrendingArticle } from "@/api/schema/feed-management/article"; -import { - ArticleFilters, - useGetQuery, - usePaginatedInfiniteQuery, - usePaginatedQuery, -} from "@/api/shared"; - -export const useArticleTrendingList = (filters: ArticleFilters = {}) => { - return usePaginatedQuery("/feed/trending", filters); -}; - -export const useArticleDetails = (articleId: string) => { - return useGetQuery
(endpoint.feedManagement.getArticleDetails(articleId)); -}; - -export const useArticleOverviewList = (filters: ArticleFilters = {}) => { - return usePaginatedQuery( - endpoint.feedManagement.getArticleOverviewList, - filters, - ); -}; - -export const useInfiniteArticleOverviewList = (filters: ArticleFilters = {}) => { - return usePaginatedInfiniteQuery( - endpoint.feedManagement.getArticleOverviewList, - filters, - ); -}; diff --git a/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts b/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts deleted file mode 100644 index 168d3da..0000000 --- a/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { - Bookmark, - BookmarkPayload, - BookmarkedArticle, -} from "@/api/schema/feed-management/bookmark"; -import { - ArticleFilters, - useDeleteQuery, - usePaginatedInfiniteQuery, - usePostQuery, - usePutQuery, -} from "@/api/shared"; - -export const useCreateBookmark = () => { - return usePostQuery(endpoint.feedManagement.createBookmark); -}; - -export const useUpdateBookmark = (bookmarkId: string) => { - return usePutQuery(endpoint.feedManagement.updateBookmark(bookmarkId)); -}; - -export const useDeleteBookmark = (bookmarkId: string) => { - return useDeleteQuery(endpoint.feedManagement.deleteBookmark(bookmarkId)); -}; - -export const useAddArticleToBookmark = (bookmarkId: string, articleId: string) => { - return usePostQuery(endpoint.feedManagement.addArticleToBookmark(bookmarkId, articleId)); -}; - -export const useRemoveArticleFromBookmark = (bookmarkId: string, articleId: string) => { - return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(bookmarkId, articleId)); -}; - -export const useBookmarkList = (filters: ArticleFilters = {}) => { - return usePaginatedInfiniteQuery(endpoint.feedManagement.getBookmarkList, filters); -}; - -export const useBookmarkedArticlesList = (bookmarkId: string, filters: ArticleFilters = {}) => { - return usePaginatedInfiniteQuery( - endpoint.feedManagement.getBookmarkedArticlesList(bookmarkId), - filters, - ); -}; diff --git a/apps/mobile-legacy/src/api/request/feed-management/comment.ts b/apps/mobile-legacy/src/api/request/feed-management/comment.ts deleted file mode 100644 index 724d7ff..0000000 --- a/apps/mobile-legacy/src/api/request/feed-management/comment.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { Comment, CommentPayload } from "@/api/schema/feed-management/comment"; -import { useDeleteQuery, usePaginatedInfiniteQuery, usePostQuery } from "@/api/shared"; - -export const useArticleCommentList = (articleId: string) => { - return usePaginatedInfiniteQuery( - endpoint.feedManagement.getArticleCommentList(articleId), - ); -}; - -export const useAddCommentToArticle = (articleId: string) => { - return usePostQuery(endpoint.feedManagement.addCommentToArticle(articleId)); -}; - -export const useRemoveCommentFromArticle = (articleId: string, commentId: string) => { - return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(articleId, commentId)); -}; diff --git a/apps/mobile-legacy/src/api/request/feed-management/source.ts b/apps/mobile-legacy/src/api/request/feed-management/source.ts deleted file mode 100644 index 2fa8af7..0000000 --- a/apps/mobile-legacy/src/api/request/feed-management/source.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { SourceDetails, SourceOverview } from "@/api/schema/feed-management/source"; -import { - ArticleFilters, - useDeleteQuery, - useGetQuery, - usePaginatedInfiniteQuery, - usePostQuery, -} from "@/api/shared"; - -export const useSourceDetails = (sourceId: string) => { - return useGetQuery(endpoint.feedManagement.getSourceDetails(sourceId)); -}; - -export const useSourceOverviewList = (filters: ArticleFilters = {}) => { - return usePaginatedInfiniteQuery( - endpoint.feedManagement.getSourceOverviewList, - filters, - ); -}; - -export const useSourceArticleOverviewList = (sourceId: string, filters: ArticleFilters = {}) => { - return usePaginatedInfiniteQuery( - endpoint.feedManagement.getSourceArticleOverviewList(sourceId), - filters, - ); -}; - -export const useFollowSource = (sourceId: string) => { - return usePostQuery(endpoint.feedManagement.followSource(sourceId)); -}; - -export const useUnfollowSource = (sourceId: string) => { - return useDeleteQuery(endpoint.feedManagement.unfollowSource(sourceId)); -}; diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/login.ts b/apps/mobile-legacy/src/api/request/identity-and-access/login.ts deleted file mode 100644 index 802cf3f..0000000 --- a/apps/mobile-legacy/src/api/request/identity-and-access/login.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { LoginPayload, LoginResponse } from "@/api/schema/identity-and-access/login"; -import { useGetQuery, usePostQuery } from "@/api/shared"; - -export const useLogin = () => { - return usePostQuery(endpoint.identityAndAccess.login); -}; - -export const useLogout = () => { - return usePostQuery(endpoint.identityAndAccess.logout); -}; - -export const useUnlockAccount = (token: string) => { - return useGetQuery(endpoint.identityAndAccess.unlockAccount(token)); -}; diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/password.ts b/apps/mobile-legacy/src/api/request/identity-and-access/password.ts deleted file mode 100644 index 6f33b48..0000000 --- a/apps/mobile-legacy/src/api/request/identity-and-access/password.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { - RequestPasswordPayload, - ResetPasswordPayload, - UpdatePasswordPayload, -} from "@/api/schema/identity-and-access/password"; -import { usePostQuery, usePutQuery } from "@/api/shared"; - -export const usePasswordForgotten = () => { - return usePostQuery(endpoint.identityAndAccess.requestPassword); -}; - -export const usePasswordReset = (token: string) => { - return usePostQuery(endpoint.identityAndAccess.resetPassword(token)); -}; - -export const usePasswordUpdate = () => { - return usePutQuery(endpoint.identityAndAccess.updatePassword); -}; diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/register.ts b/apps/mobile-legacy/src/api/request/identity-and-access/register.ts deleted file mode 100644 index 528e371..0000000 --- a/apps/mobile-legacy/src/api/request/identity-and-access/register.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { endpoint } from "@/api/endpoint"; -import { RegisterPayload } from "@/api/schema/identity-and-access/register"; -import { useGetQuery, usePostQuery } from "@/api/shared"; - -export const useRegister = () => { - return usePostQuery(endpoint.identityAndAccess.register); -}; - -export const useConfirmAccount = (token: string) => { - return useGetQuery(endpoint.identityAndAccess.confirmAccount(token)); -}; diff --git a/apps/mobile-legacy/src/api/schema/feed-management/article.ts b/apps/mobile-legacy/src/api/schema/feed-management/article.ts deleted file mode 100644 index e890afb..0000000 --- a/apps/mobile-legacy/src/api/schema/feed-management/article.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { SourceReference } from "@/api/schema/feed-management/source"; - -export type ArticleOverview = { - id: string; - title: string; - link: string; - categories: string[]; - excerpt: string; - source: SourceReference; - publishedAt: string; - image?: string; - readingTime: number; - bookmarked: boolean; -}; - -export type Article = { - id: string; - title: string; - link: string; - categories: string[]; - body: string; - source: SourceReference; - hash: string; - credibility: { - bias: "neutral" | "slightly" | "partisan" | "extreme"; - reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust"; - transparency: "low" | "medium" | "high"; - }; - sentiment: "negative" | "positive" | "neutral"; - metadata?: { - title?: string; - description?: string; - image?: string; - video?: string; - audio?: string; - locale?: string; - }; - readingTime: number; - publishedAt: string; - crawledAt: string; - updatedAt: string; - bookmarked: boolean; -}; - -export type TrendingArticle = ArticleOverview; diff --git a/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts b/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts deleted file mode 100644 index 9689796..0000000 --- a/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts +++ /dev/null @@ -1,30 +0,0 @@ -import Joi from "joi"; - -import { ArticleOverview } from "@/api/schema/feed-management/article"; - -export type BookmarkPayload = { - name: string; - description?: string; - isPublic: boolean; -}; - -export type Bookmark = { - id: string; - name: string; - createdAt: string; - description?: string; - articlesCount: number; - isPublic: boolean; - updatedAt?: string; -}; - -export type BookmarkedArticle = ArticleOverview; - -export const BookmarkPayloadSchema = Joi.object({ - description: Joi.string().optional(), - isPublic: Joi.boolean().optional(), - name: Joi.string().required().messages({ - "any.required": "Le nom est requis", - "string.empty": "Le nom est requis", - }), -}); diff --git a/apps/mobile-legacy/src/api/schema/feed-management/comment.ts b/apps/mobile-legacy/src/api/schema/feed-management/comment.ts deleted file mode 100644 index e30ee8a..0000000 --- a/apps/mobile-legacy/src/api/schema/feed-management/comment.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type Comment = { - id: string; - content: string; - user: { - id: string; - name: string; - }; - sentiment: "positive" | "neutral" | "negative"; - createdAt: string; -}; - -export type CommentPayload = { - content: string; -}; diff --git a/apps/mobile-legacy/src/api/schema/feed-management/source.ts b/apps/mobile-legacy/src/api/schema/feed-management/source.ts deleted file mode 100644 index 1c02d57..0000000 --- a/apps/mobile-legacy/src/api/schema/feed-management/source.ts +++ /dev/null @@ -1,54 +0,0 @@ -export type SourceReference = { - id: string; - name: string; - displayName?: string; - image: string; - url: string; -}; - -export type SourceOverview = { - id: string; - name: string; - displayName?: string; - image: string; - url: string; - followed: boolean; -}; - -export type CategoryShare = { - name: string; - count: number; - percentage: number; -}; - -export type PublicationEntry = { - date: string; - count: number; -}; - -export type SourceDetails = { - id: string; - name: string; - url: string; - credibility: { - bias: "neutral" | "slightly" | "partisan" | "extreme"; - reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust"; - transparency: "low" | "medium" | "high"; - }; - publicationGraph: { - items: PublicationEntry[]; - total: number; - }; - categoryShares: { - items: CategoryShare[]; - total: number; - }; - articlesCount: number; - crawledAt: string; - displayName?: string; - description?: string; - updatedAt?: string; - metadataAvailable: number; - followed: boolean; - image: string; -}; diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts deleted file mode 100644 index 8348558..0000000 --- a/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts +++ /dev/null @@ -1,31 +0,0 @@ -import Joi from "joi"; - -export type LoginPayload = { - username: string; - password: string; -}; - -export type LoginResponse = { - token: string; - refresh_token: string; -}; - -export type RefreshTokenPayload = { - refresh_token: string; -}; - -export type RefreshTokenResponse = { - token: string; -}; - -export const LoginPayloadSchema = Joi.object({ - password: Joi.string().min(4).required().messages({ - "any.required": "Le mot de passe est requis", - "string.empty": "Le mot de passe est requis", - "string.min": "Le mot de passe doit comporter au moins 4 caractères", - }), - username: Joi.string().required().messages({ - "any.required": "L'email est requis", - "string.empty": "L'email est requis", - }), -}); diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts deleted file mode 100644 index ead279e..0000000 --- a/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts +++ /dev/null @@ -1,53 +0,0 @@ -import Joi from "joi"; - -export type RequestPasswordPayload = { - email: string; -}; - -export type ResetPasswordPayload = { - password: string; - confirm: string; -}; - -export type UpdatePasswordPayload = { - current: string; - password: string; - confirm: string; -}; - -export const RequestPasswordPayloadSchema = Joi.object({ - email: Joi.string().required().messages({ - "any.required": "L'email est requis", - "string.empty": "L'email est requis", - }), -}); - -export const ResetPasswordPayloadSchema = Joi.object({ - confirm: Joi.string().valid(Joi.ref("password")).required().messages({ - "any.only": "Les mots de passe ne correspondent pas", - "any.required": "La confirmation du mot de passe est requise", - "string.empty": "La confirmation du mot de passe est requise", - }), - password: Joi.string().min(6).required().messages({ - "any.required": "Le mot de passe est requis", - "string.empty": "Le mot de passe est requis", - "string.min": "Le mot de passe doit comporter au moins 6 caractères", - }), -}); - -export const UpdatePasswordPayloadSchema = Joi.object({ - confirm: Joi.string().valid(Joi.ref("password")).required().messages({ - "any.only": "Les mots de passe ne correspondent pas", - "any.required": "La confirmation du nouveau mot de passe est requise", - "string.empty": "La confirmation du nouveau mot de passe est requise", - }), - current: Joi.string().required().messages({ - "any.required": "Le mot de passe actuel est requis", - "string.empty": "Le mot de passe actuel est requis", - }), - password: Joi.string().min(6).required().messages({ - "any.required": "Le nouveau mot de passe est requis", - "string.empty": "Le nouveau mot de passe est requis", - "string.min": "Le nouveau mot de passe doit comporter au moins 6 caractères", - }), -}); diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts deleted file mode 100644 index d3268cf..0000000 --- a/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Joi from "joi"; - -export type RegisterPayload = { - name: string; - email: string; - password: string; -}; - -export const RegisterPayloadSchema = Joi.object({ - email: Joi.string().required().messages({ - "any.required": "L'email est requis", - "string.empty": "L'email est requis", - }), - name: Joi.string().required().messages({ - "any.required": "Le nom est requis", - "string.empty": "Le nom est requis", - }), - password: Joi.string().min(6).required().messages({ - "any.required": "Le mot de passe est requis", - "string.empty": "Le mot de passe est requis", - "string.min": "Le mot de passe doit comporter au moins 4 caractères", - }), -}); diff --git a/apps/mobile-legacy/src/api/shared.ts b/apps/mobile-legacy/src/api/shared.ts deleted file mode 100644 index d7cdad5..0000000 --- a/apps/mobile-legacy/src/api/shared.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - skipToken, - useInfiniteQuery, - useMutation, - useQuery, - useQueryClient, -} from "@tanstack/react-query"; -import { AxiosError } from "axios"; -import qs from "qs"; - -import client from "@/api/client"; - -export type PaginationFilters = { - page?: number; - limit?: number; - lastId?: string; -}; - -export type ArticleFilters = PaginationFilters & { - dateRange?: { - start: number; - end: number; - }; - search?: string; - sortDirection?: "asc" | "desc"; -}; - -export type PaginationInfo = { - current: number; - limit: number; - lastId?: string; - offset: number; -}; - -export type ClientDetailErrorResponse = { - type: string; - title: string; - detail: string; - status: number; -}; - -export type ClientErrorResponse = { - code: string; - message: string; -}; - -export type ErrorResponse = AxiosError; - -export type PaginatedResponse = { - items: TItem[]; - pagination: PaginationInfo; -}; - -export const safeMessage = ( - error: AxiosError | Error, -): string => { - if (error instanceof AxiosError && error.response) { - const response = error.response.data; - - if ("message" in response) { - return response.message; - } else if ("detail" in response) { - return response.detail; - } - } - - return "Une erreur est survenue"; -}; - -export const usePaginatedInfiniteQuery = ( - endpoint: string, - filters: PaginationFilters = {}, -) => { - return useInfiniteQuery, ErrorResponse>({ - getNextPageParam: (lastPage: PaginatedResponse) => { - const { lastId } = lastPage.pagination; - return lastId ? lastId : null; - }, - initialData: undefined, - initialPageParam: null, - queryFn: async ({ pageParam = null }) => { - const query = qs.stringify({ ...filters, lastId: pageParam }, { skipNulls: true }); - const url = `${endpoint}?${query}`; - const response = await client.get>(url); - return response.data; - }, - queryKey: [endpoint, filters], - staleTime: 1_000 * 60 * 10, - }); -}; - -export const usePaginatedQuery = (endpoint: string, filters: PaginationFilters = {}) => { - return useQuery, ErrorResponse>({ - queryFn: async (): Promise> => { - const query = qs.stringify({ ...filters, lastId: null }, { skipNulls: true }); - const url = `${endpoint}?${query}`; - const response = await client.get>(url); - return response.data; - }, - queryKey: [endpoint, filters], - staleTime: 1_000 * 60 * 10, - }); -}; - -export const useGetQuery = (endpoint: string, enabled: boolean = true) => { - return useQuery({ - queryFn: enabled - ? async (): Promise => { - const response = await client.get(endpoint); - return response.data; - } - : skipToken, - queryKey: [endpoint], - staleTime: 1_000 * 60 * 10, - }); -}; - -export const usePostQuery = ( - endpoint: string, - keys: string[] = [], -) => { - const queryClient = useQueryClient(); - return useMutation({ - mutationFn: async (data: TPayload): Promise => { - const response = await client.post(endpoint, data); - return response.data; - }, - onSuccess: async () => { - for (const key of keys) { - await queryClient.invalidateQueries({ queryKey: [key] }); - } - }, - }); -}; - -export const usePutQuery = ( - endpoint: string, - keys: string[] = [], -) => { - const queryClient = useQueryClient(); - return useMutation({ - mutationFn: async (data: TPayload): Promise => { - const response = await client.put(endpoint, data); - return response.data; - }, - onSuccess: async () => { - for (const key of keys) { - await queryClient.invalidateQueries({ queryKey: [key] }); - } - }, - }); -}; - -export const useDeleteQuery = (endpoint: string, keys: string[] = []) => { - const queryClient = useQueryClient(); - return useMutation({ - mutationFn: async (): Promise => { - const response = await client.delete(endpoint); - return response.data; - }, - onSuccess: async () => { - for (const key of keys) { - await queryClient.invalidateQueries({ queryKey: [key] }); - } - }, - }); -}; diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx deleted file mode 100644 index 1878fc2..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { BookMarked, Globe, Home, User } from "@tamagui/lucide-icons"; -import { Tabs } from "expo-router"; -import { useColorScheme } from "react-native"; -import { Paragraph } from "tamagui"; - -export default function TabLayout() { - const colorScheme = useColorScheme(); - - return ( - - , - tabBarLabel: ({ color }) => ( - - Actualités - - ), - }} - /> - , - tabBarLabel: ({ color }) => ( - - Sources - - ), - }} - /> - , - tabBarLabel: ({ color }) => ( - - Signets - - ), - }} - /> - , - tabBarLabel: ({ color }) => ( - - Profil - - ), - }} - /> - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx deleted file mode 100644 index ef76f39..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from "expo-router"; - -export default function Layout() { - return ; -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx deleted file mode 100644 index 82816fc..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { ChevronRight, Settings } from "@tamagui/lucide-icons"; -import { useRouter } from "expo-router"; -import { Label, ListItem, ScrollView, Separator, YGroup } from "tamagui"; - -import { ScreenView } from "@/ui/components/layout"; - -export default function Index() { - const router = useRouter(); - - return ( - - - - - - - - router.push("/account/settings")} - title="Settings" - /> - - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx deleted file mode 100644 index e96e781..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ActivityIndicator } from "react-native"; -import { Button, YStack } from "tamagui"; - -import { useLogout } from "@/api/request/identity-and-access/login"; -import { useAuth } from "@/providers/auth-provider"; -import { ScreenView } from "@/ui/components/layout"; - -export default function Index() { - const authState = useAuth(); - const { mutate, isPending } = useLogout(); - - const handleLogout = async () => { - mutate(undefined, { - onError: () => authState.logout(), - onSuccess: () => authState.logout(), - }); - }; - - return ( - - - - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx deleted file mode 100644 index 0172919..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { Bookmark, MoreVertical, Share } from "@tamagui/lucide-icons"; -import { useLocalSearchParams, useRouter } from "expo-router"; -import * as WebBrowser from "expo-web-browser"; -import Toast from "react-native-toast-message"; -import { Button, H5, ScrollView, Separator, XStack, YStack } from "tamagui"; - -import { useArticleDetails } from "@/api/request/feed-management/article"; -import { Article } from "@/api/schema/feed-management/article"; -import { safeMessage } from "@/api/shared"; -import { useRelativeTime } from "@/hooks/use-relative-time"; -import { ArticleCategoryPill, ArticleCoverImage } from "@/ui/components/content/article"; -import { SourceReferencePill } from "@/ui/components/content/source"; -import { BackButton } from "@/ui/components/controls/BackButton"; -import { IconButton } from "@/ui/components/controls/IconButton"; -import { LoadingView } from "@/ui/components/LoadingView"; -import { ScreenView } from "@/ui/components/layout"; -import { Caption, Text } from "@/ui/components/typography"; - -export default function ArticleDetails() { - const router = useRouter(); - const { id } = useLocalSearchParams(); - const { data, isLoading, error } = useArticleDetails(id as string); - const article: Article | undefined = data ?? undefined; - const relativeTime = useRelativeTime(article?.publishedAt); - - const handleReadIntegrality = async () => { - await WebBrowser.openBrowserAsync(article!.link); - }; - - if (error) { - Toast.show({ - text1: "Erreur", - text2: safeMessage(error), - type: "error", - }); - router.replace("/(authed)/(tabs)/articles"); - } - - if (isLoading || article === undefined) { - return ; - } - - return ( - - router.dismissTo("/(authed)/(tabs)/articles")} />} - trailingActions={ - <> - } onPress={() => {}} /> - } onPress={() => {}} /> - } onPress={() => {}} /> - - } - /> - - - {article.metadata?.image && ( - - )} - - - - {article.categories.map((category, index) => ( - - ))} - -
- {article.title} -
- - - - - {relativeTime} - - {article.readingTime} minutes de lecture - - - - - {article.body.trim()} - -
- -
-
- ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx deleted file mode 100644 index ef76f39..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from "expo-router"; - -export default function Layout() { - return ; -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx deleted file mode 100644 index fb5c8ff..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { ScrollView, YStack } from "tamagui"; - -import { useArticleOverviewList } from "@/api/request/feed-management/article"; -import { useSourceOverviewList } from "@/api/request/feed-management/source"; -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { SourceOverview } from "@/api/schema/feed-management/source"; -import { useFlattenedItems } from "@/hooks/use-flattened-items"; -import { ArticleList, ArticleSkeletonList } from "@/ui/components/content/article"; -import { SourceList, SourceSkeletonList } from "@/ui/components/content/source"; -import { ScreenView } from "@/ui/components/layout"; -import { Heading } from "@/ui/components/typography"; - -export default function Index() { - const { data: articles, isLoading: articlesLoading } = useArticleOverviewList({ limit: 10 }); - const { data: sources, isLoading: sourcesLoading } = useSourceOverviewList(); - const articleOverviews: ArticleOverview[] = useFlattenedItems(articles); - const sourcesOverviews: SourceOverview[] = useFlattenedItems(sources); - - return ( - - Actualités - - - - - - {articlesLoading && } - {!articlesLoading && ( - - )} - - - - - {sourcesLoading && } - {!sourcesLoading && ( - - )} - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx deleted file mode 100644 index fd84583..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { useRouter } from "expo-router"; - -import { useInfiniteArticleOverviewList } from "@/api/request/feed-management/article"; -import { TrendingArticle } from "@/api/schema/feed-management/article"; -import { useFlattenedItems } from "@/hooks/use-flattened-items"; -import { ArticleList, ArticleSkeletonList } from "@/ui/components/content/article"; -import { BackButton } from "@/ui/components/controls/BackButton"; -import { ScreenView } from "@/ui/components/layout"; - -export default function Trending() { - const router = useRouter(); - const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } = - useInfiniteArticleOverviewList({ limit: 20 }); - const articles: TrendingArticle[] = useFlattenedItems(data); - - return ( - - router.dismissTo("/(authed)/(tabs)/articles")} />} - title="Actualités" - /> - - {isLoading && } - {!isLoading && ( - - )} - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx deleted file mode 100644 index 25cef7a..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { useLocalSearchParams } from "expo-router"; -import { Paragraph } from "tamagui"; - -import { ScreenView } from "@/ui/components/layout"; -import { Heading } from "@/ui/components/typography"; - -export default function Details() { - const { id } = useLocalSearchParams(); - // const { data, isLoading } = useBookmarkedArticlesList(id as string); - // const articles: BookmarkedArticle[] = useFlattenedItems(data); - - return ( - - Bookmark Infos - {id} - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx deleted file mode 100644 index ef76f39..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from "expo-router"; - -export default function Layout() { - return ; -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx deleted file mode 100644 index 981318b..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Plus, Search } from "@tamagui/lucide-icons"; -import { YStack } from "tamagui"; - -import { useBookmarkList } from "@/api/request/feed-management/bookmark"; -import { Bookmark } from "@/api/schema/feed-management/bookmark"; -import { useFlattenedItems } from "@/hooks/use-flattened-items"; -import { BookmarkList } from "@/ui/components/content/bookmark"; -import { IconButton } from "@/ui/components/controls/IconButton"; -import { LoadingView } from "@/ui/components/LoadingView"; -import { ScreenView } from "@/ui/components/layout"; - -export default function Index() { - const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } = - useBookmarkList(); - const bookmarks: Bookmark[] = useFlattenedItems(data); - - return ( - - } onPress={() => {}} />} - title="Bookmarks" - trailingActions={} onPress={() => {}} />} - /> - - - {isLoading && } - {!isLoading && ( - - )} - - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx deleted file mode 100644 index da3c2d1..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { useLocalSearchParams } from "expo-router"; - -import { ScreenView } from "@/ui/components/layout"; -import { Heading, Text } from "@/ui/components/typography"; - -export default function SourceDetails() { - const { name } = useLocalSearchParams(); - - return ( - - Source Details - {name} - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx deleted file mode 100644 index ef76f39..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from "expo-router"; - -export default function Layout() { - return ; -} diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx deleted file mode 100644 index 1f5ebe3..0000000 --- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useSourceOverviewList } from "@/api/request/feed-management/source"; -import { SourceOverview } from "@/api/schema/feed-management/source"; -import { useFlattenedItems } from "@/hooks/use-flattened-items"; -import { SourceList, SourceSkeletonList } from "@/ui/components/content/source"; -import { ScreenView } from "@/ui/components/layout"; - -export default function Sources() { - const { data, isLoading } = useSourceOverviewList(); - const sources: SourceOverview[] = useFlattenedItems(data); - - return ( - - - - {isLoading && } - {!isLoading && } - - ); -} diff --git a/apps/mobile-legacy/src/app/(authed)/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/_layout.tsx deleted file mode 100644 index 21df812..0000000 --- a/apps/mobile-legacy/src/app/(authed)/_layout.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Redirect, Stack } from "expo-router"; - -import { useAuth } from "@/providers/auth-provider"; - -export default function AuthedLayout() { - const auth = useAuth(); - - if (!auth.isReady) { - return null; - } - - if (!auth.isLoggedIn) { - return ; - } - - return ; -} diff --git a/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx b/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx deleted file mode 100644 index b12aa2d..0000000 --- a/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Redirect, Stack } from "expo-router"; - -import { useAuth } from "@/providers/auth-provider"; - -export default function AuthedLayout() { - const auth = useAuth(); - - if (!auth.isReady) { - return null; - } - - if (auth.isLoggedIn) { - return ; - } - - return ; -} diff --git a/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx b/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx deleted file mode 100644 index fb7cf32..0000000 --- a/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { joiResolver } from "@hookform/resolvers/joi"; -import { Link, useRouter } from "expo-router"; -import { useForm } from "react-hook-form"; -import Toast from "react-native-toast-message"; -import { YStack } from "tamagui"; - -import { usePasswordForgotten } from "@/api/request/identity-and-access/password"; -import { - RequestPasswordPayload, - RequestPasswordPayloadSchema, -} from "@/api/schema/identity-and-access/password"; -import { ErrorResponse, safeMessage } from "@/api/shared"; -import { FormEmailInput } from "@/ui/components/controls/forms"; -import { SubmitButton } from "@/ui/components/controls/SubmitButton"; -import { ScreenView } from "@/ui/components/layout"; -import { Heading, Text } from "@/ui/components/typography"; - -export default function PasswordRequest() { - const { mutate, isPending } = usePasswordForgotten(); - const router = useRouter(); - - const { control, handleSubmit, formState } = useForm({ - resolver: joiResolver(RequestPasswordPayloadSchema), - }); - - const onSubmit = (data: RequestPasswordPayload) => { - mutate(data, { - onError: (error: ErrorResponse) => { - Toast.show({ - text1: "Erreur de connexion", - text2: safeMessage(error), - type: "error", - }); - }, - onSuccess: () => { - Toast.show({ - text1: "Succès", - text2: "Un mail avec les instructions vous a été envoyé", - type: "success", - }); - router.push("/(unauthed)/signin"); - }, - }); - }; - - return ( - - - - Mot de passe oublié ? - - Veuillez entrer votre adresse e-mail pour recevoir un lien de réinitialisation de mot de - passe. - - - - - - - Vous avez pas de compte ? Se connecter - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(unauthed)/signin.tsx b/apps/mobile-legacy/src/app/(unauthed)/signin.tsx deleted file mode 100644 index a137a74..0000000 --- a/apps/mobile-legacy/src/app/(unauthed)/signin.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { joiResolver } from "@hookform/resolvers/joi"; -import { Link, useRouter } from "expo-router"; -import { useForm } from "react-hook-form"; -import Toast from "react-native-toast-message"; -import { YStack } from "tamagui"; - -import { useLogin } from "@/api/request/identity-and-access/login"; -import { - LoginPayload, - LoginPayloadSchema, - LoginResponse, -} from "@/api/schema/identity-and-access/login"; -import { ErrorResponse, safeMessage } from "@/api/shared"; -import { useAuth } from "@/providers/auth-provider"; -import { FormEmailInput, FormPasswordInput } from "@/ui/components/controls/forms"; -import { SubmitButton } from "@/ui/components/controls/SubmitButton"; -import { ScreenView } from "@/ui/components/layout"; -import { Caption, Heading, Text } from "@/ui/components/typography"; - -export default function SignIn() { - const { mutate, isPending } = useLogin(); - const auth = useAuth(); - const router = useRouter(); - - if (auth.isLoggedIn) { - router.replace("/(authed)/(tabs)/articles"); - } - - const { control, handleSubmit, formState } = useForm({ - resolver: joiResolver(LoginPayloadSchema), - }); - - const onSubmit = (data: LoginPayload) => { - mutate(data, { - onError: (error: ErrorResponse) => { - Toast.show({ - text1: "Erreur de connexion", - text2: safeMessage(error), - type: "error", - }); - }, - onSuccess: async (data: LoginResponse) => { - auth.login(data.token, data.refresh_token); - Toast.show({ text1: "Connexion réussie", type: "success" }); - }, - }); - }; - - return ( - - - - Connexion - Bienvenue sur Basango, la plateforme d'actualités intelligente - - - - - - - - Mot de passe oublié ? - - - - - - En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez - avoir lu notre politique de confidentialité. - - - Vous n'avez pas de compte ? Créer un compte - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(unauthed)/signup.tsx b/apps/mobile-legacy/src/app/(unauthed)/signup.tsx deleted file mode 100644 index 18aeb52..0000000 --- a/apps/mobile-legacy/src/app/(unauthed)/signup.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { joiResolver } from "@hookform/resolvers/joi"; -import { User } from "@tamagui/lucide-icons"; -import { Link, useRouter } from "expo-router"; -import { useForm } from "react-hook-form"; -import Toast from "react-native-toast-message"; -import { YStack } from "tamagui"; - -import { useRegister } from "@/api/request/identity-and-access/register"; -import { RegisterPayload, RegisterPayloadSchema } from "@/api/schema/identity-and-access/register"; -import { ErrorResponse, safeMessage } from "@/api/shared"; -import { FormEmailInput, FormPasswordInput, FormTextInput } from "@/ui/components/controls/forms"; -import { SubmitButton } from "@/ui/components/controls/SubmitButton"; -import { ScreenView } from "@/ui/components/layout"; -import { Caption, Heading, Text } from "@/ui/components/typography"; - -export default function SingUp() { - const router = useRouter(); - const { mutate, isPending } = useRegister(); - - const { control, handleSubmit, formState } = useForm({ - resolver: joiResolver(RegisterPayloadSchema), - }); - - const onSubmit = (data: RegisterPayload) => { - mutate(data, { - onError: (error: ErrorResponse) => { - Toast.show({ - text1: "Erreur", - text2: safeMessage(error), - type: "error", - }); - }, - onSuccess: () => { - Toast.show({ - text1: "Félicitations !", - text2: "les détails de votre compte vous ont été envoyés par e-mail.", - type: "success", - }); - router.replace("/(unauthed)/signin"); - }, - }); - }; - - return ( - - - - Inscription - Rejoignez la communauté Basango et restez informé des dernières actualités - - - - - - - - - En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez - avoir lu notre politique de confidentialité. - - - Vous avez un compte ? Connectez-vous - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx b/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx deleted file mode 100644 index 2b9a34e..0000000 --- a/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Link, useRouter } from "expo-router"; -import { Button, YStack } from "tamagui"; - -import { AppIcon } from "@/ui/components/AppIcon"; -import { ScreenView } from "@/ui/components/layout"; -import { Caption, Display, Text } from "@/ui/components/typography"; - -export default function Welcome() { - const router = useRouter(); - - return ( - - - - - Bienvenue sur Basango - - La première plateforme d'actualités intelligente qui vous aide à rester informé sur - congolaise et internationale. - - - - - - - Ouvrir un compte - - - - - En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez - avoir lu notre politique de confidentialité. - - - - ); -} diff --git a/apps/mobile-legacy/src/app/+not-found.tsx b/apps/mobile-legacy/src/app/+not-found.tsx deleted file mode 100644 index bff11e6..0000000 --- a/apps/mobile-legacy/src/app/+not-found.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Link, Stack } from "expo-router"; -import { View, YStack } from "tamagui"; - -import { AppIcon } from "@/ui/components/AppIcon"; -import { ScreenView } from "@/ui/components/layout"; -import { Heading, Text } from "@/ui/components/typography"; - -export default function NotFoundScreen() { - return ( - - - - - - - - - Une erreur s'est produite - - - Nous avons une difficulté à charger la page que vous recherchez. - - - - - Recommencer - - - - - - ); -} diff --git a/apps/mobile-legacy/src/app/_layout.tsx b/apps/mobile-legacy/src/app/_layout.tsx deleted file mode 100644 index 2dd39c3..0000000 --- a/apps/mobile-legacy/src/app/_layout.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as Sentry from "@sentry/react-native"; -import { Stack } from "expo-router"; -import React from "react"; -import { useColorScheme } from "react-native"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; -import Toast from "react-native-toast-message"; -import { Theme } from "tamagui"; - -import { RootProviders } from "@/providers/root-providers"; - -export { ErrorBoundary } from "expo-router"; - -Sentry.init({ - debug: __DEV__, - dsn: process.env.EXPO_PUBLIC_SENTRY_DSN, - sendDefaultPii: true, - spotlight: __DEV__, - tracePropagationTargets: [/.*?/], - tracesSampleRate: 1.0, -}); - -function RootLayout() { - const colorScheme = useColorScheme(); - const insets = useSafeAreaInsets(); - - return ( - - - - - - - - - ); -} - -export default Sentry.wrap(RootLayout); diff --git a/apps/mobile-legacy/src/app/index.tsx b/apps/mobile-legacy/src/app/index.tsx deleted file mode 100644 index ff00fb1..0000000 --- a/apps/mobile-legacy/src/app/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Redirect } from "expo-router"; - -import { useAuth } from "@/providers/auth-provider"; - -export default function Index() { - const auth = useAuth(); - - if (!auth.isReady) { - return null; - } - - return auth.isLoggedIn ? ( - - ) : ( - - ); -} diff --git a/apps/mobile-legacy/src/assets/fonts/SpaceMono-Regular.ttf b/apps/mobile-legacy/src/assets/fonts/SpaceMono-Regular.ttf deleted file mode 100644 index 28d7ff7..0000000 Binary files a/apps/mobile-legacy/src/assets/fonts/SpaceMono-Regular.ttf and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx b/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx deleted file mode 100644 index 34a86ea..0000000 --- a/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx +++ /dev/null @@ -1,319 +0,0 @@ -import Svg, { Circle, G, Path, Rect, SvgProps } from "react-native-svg"; - -/** - * @see https://storyset.com/illustration/bookmarks/pana - * @param props - * @constructor - */ -export default function BookmarkIllustration(props: SvgProps) { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/apps/mobile-legacy/src/assets/images/adaptive-icon.png b/apps/mobile-legacy/src/assets/images/adaptive-icon.png deleted file mode 100644 index 8e37f86..0000000 Binary files a/apps/mobile-legacy/src/assets/images/adaptive-icon.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/images/favicon.png b/apps/mobile-legacy/src/assets/images/favicon.png deleted file mode 100644 index 8e37f86..0000000 Binary files a/apps/mobile-legacy/src/assets/images/favicon.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/images/icon.png b/apps/mobile-legacy/src/assets/images/icon.png deleted file mode 100644 index 8e37f86..0000000 Binary files a/apps/mobile-legacy/src/assets/images/icon.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/images/logo.png b/apps/mobile-legacy/src/assets/images/logo.png deleted file mode 100644 index d333443..0000000 Binary files a/apps/mobile-legacy/src/assets/images/logo.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/images/splash-icon.png b/apps/mobile-legacy/src/assets/images/splash-icon.png deleted file mode 100644 index 8e37f86..0000000 Binary files a/apps/mobile-legacy/src/assets/images/splash-icon.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/screenshots/1.png b/apps/mobile-legacy/src/assets/screenshots/1.png deleted file mode 100644 index 81deb10..0000000 Binary files a/apps/mobile-legacy/src/assets/screenshots/1.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/screenshots/2.png b/apps/mobile-legacy/src/assets/screenshots/2.png deleted file mode 100644 index 99e89b5..0000000 Binary files a/apps/mobile-legacy/src/assets/screenshots/2.png and /dev/null differ diff --git a/apps/mobile-legacy/src/assets/screenshots/3.png b/apps/mobile-legacy/src/assets/screenshots/3.png deleted file mode 100644 index af7f4c0..0000000 Binary files a/apps/mobile-legacy/src/assets/screenshots/3.png and /dev/null differ diff --git a/apps/mobile-legacy/src/hooks/use-flattened-items.ts b/apps/mobile-legacy/src/hooks/use-flattened-items.ts deleted file mode 100644 index 4b9e5ce..0000000 --- a/apps/mobile-legacy/src/hooks/use-flattened-items.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useMemo } from "react"; - -interface Page { - items: T[]; -} - -interface PaginatedResult { - pages?: Page[]; - items?: T[]; -} - -export const useFlattenedItems = (data: PaginatedResult | undefined | null): T[] => { - return useMemo((): T[] => { - if (!data) { - return []; - } - - if (data.pages && Array.isArray(data.pages) && data.pages.length > 0) { - return data.pages.flatMap((page) => page.items || []); - } else if (data.items && Array.isArray(data.items)) { - return data.items; - } else { - return []; - } - }, [data]); -}; diff --git a/apps/mobile-legacy/src/hooks/use-relative-time.ts b/apps/mobile-legacy/src/hooks/use-relative-time.ts deleted file mode 100644 index 77700ac..0000000 --- a/apps/mobile-legacy/src/hooks/use-relative-time.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Locale, formatDistanceToNowStrict } from "date-fns"; -import { fr } from "date-fns/locale"; -import { useEffect, useState } from "react"; - -export const useRelativeTime = ( - dateInput: string | Date | number | null | undefined, - options?: { - addSuffix?: boolean; - unit?: "second" | "minute" | "hour" | "day" | "month" | "year"; - locale?: Locale; - roundingMethod?: "floor" | "ceil" | "round"; - includeSeconds?: boolean; - }, - updateInterval: number = 60000, -): string => { - const [relativeTime, setRelativeTime] = useState(""); - - useEffect(() => { - if (dateInput === null || dateInput === undefined) { - setRelativeTime(""); - return; - } - - const date = new Date(dateInput); - - // Check if the date is valid - if (Number.isNaN(date.getTime())) { - setRelativeTime("Invalid Date"); - return; - } - - const updateTime = () => { - // Default options if none provided, ensures suffix is added - const effectiveOptions = { - addSuffix: true, - locale: fr, - ...options, - }; - - try { - const formattedTime = formatDistanceToNowStrict(date, effectiveOptions); - setRelativeTime(formattedTime); - } catch (error) { - console.error("Error formatting relative time:", error); - setRelativeTime(dateInput.toString()); // Handle potential errors during formatting - } - }; - - // Initial update - updateTime(); - - // Set up interval for periodic updates - const intervalId = setInterval(updateTime, updateInterval); - - // Clean up the interval when the component unmounts or dateInput changes - return () => clearInterval(intervalId); - }, [dateInput, options, updateInterval]); - - return relativeTime; -}; diff --git a/apps/mobile-legacy/src/providers/auth-provider.tsx b/apps/mobile-legacy/src/providers/auth-provider.tsx deleted file mode 100644 index 5aa7d82..0000000 --- a/apps/mobile-legacy/src/providers/auth-provider.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { SplashScreen, useRouter } from "expo-router"; -import React, { createContext, useContext, useEffect, useState } from "react"; - -import { clearTokens, getAccessToken, getRefreshToken, setTokens } from "@/store/auth"; - -SplashScreen.preventAutoHideAsync(); - -type AuthState = { - isReady: boolean; - isLoggedIn: boolean; - login: (accessToken: string, refreshToken: string) => void; - logout: () => void; - accessToken: string | null; - refreshToken: string | null; -}; - -const AuthContext = createContext({ - accessToken: null, - isLoggedIn: false, - isReady: false, - login: () => {}, - logout: () => {}, - refreshToken: null, -}); - -export function useAuth() { - return useContext(AuthContext); -} - -export function AuthProvider({ children }: React.PropsWithChildren) { - const [isReady, setIsReady] = useState(false); - const [accessToken, setAccessToken] = useState(null); - const [refreshToken, setRefreshToken] = useState(null); - const router = useRouter(); - - const isLoggedIn = !!(accessToken && refreshToken); - - const login = (access: string, refresh: string) => { - setAccessToken(access); - setRefreshToken(refresh); - setTokens(access, refresh); - router.replace("/(authed)/(tabs)/articles"); - }; - - const logout = () => { - setAccessToken(null); - setRefreshToken(null); - clearTokens(); - router.replace("/signin"); - }; - - useEffect(() => { - const loadTokens = async () => { - try { - const [storedAccess, storedRefresh] = await Promise.all([ - getAccessToken(), - getRefreshToken(), - ]); - - if (storedAccess && storedRefresh) { - setAccessToken(storedAccess); - setRefreshToken(storedRefresh); - } - } catch (error) { - console.error("Unable to retrieve auth tokens", error); - } finally { - setIsReady(true); - await SplashScreen.hideAsync(); - } - }; - loadTokens(); - }, []); - - return ( - - {children} - - ); -} diff --git a/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx b/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx deleted file mode 100644 index 3ca164c..0000000 --- a/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Inter_100Thin, - Inter_200ExtraLight, - Inter_300Light, - Inter_400Regular, - Inter_500Medium, - Inter_600SemiBold, - Inter_700Bold, - Inter_800ExtraBold, - Inter_900Black, - useFonts, -} from "@expo-google-fonts/inter"; -import { SplashScreen } from "expo-router"; -import type React from "react"; -import { useEffect } from "react"; - -SplashScreen.preventAutoHideAsync(); - -export const FontsLoaderProvider = ({ children }: React.PropsWithChildren) => { - const [fontsLoaded, fontError] = useFonts({ - Inter_100Thin, - Inter_200ExtraLight, - Inter_300Light, - Inter_400Regular, - Inter_500Medium, - Inter_600SemiBold, - Inter_700Bold, - Inter_800ExtraBold, - Inter_900Black, - }); - - useEffect(() => { - if (fontsLoaded || fontError) { - SplashScreen.hideAsync(); - } - }, [fontsLoaded, fontError]); - - if (!fontsLoaded && !fontError) { - return null; - } - - return <>{children}; -}; diff --git a/apps/mobile-legacy/src/providers/network-provider.tsx b/apps/mobile-legacy/src/providers/network-provider.tsx deleted file mode 100644 index cc8199a..0000000 --- a/apps/mobile-legacy/src/providers/network-provider.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as Network from "expo-network"; -import { NetworkStateEvent } from "expo-network"; -import React, { createContext, useContext, useEffect, useState } from "react"; - -type NetworkState = { - isConnected: boolean; -}; - -const NetworkContext = createContext({ - isConnected: true, -}); - -export const useNetwork = () => useContext(NetworkContext); - -export const NetworkProvider = ({ children }: React.PropsWithChildren) => { - const [isConnected, setIsConnected] = useState(true); - - useEffect(() => { - let subscription: { remove: () => any }; - - const subscribeToNetworkChanges = async () => { - const state = await Network.getNetworkStateAsync(); - updateConnection(state); - - subscription = Network.addNetworkStateListener(updateConnection); - }; - - const updateConnection = (state: NetworkStateEvent) => { - const connected = state.isConnected && state.isInternetReachable === true; - setIsConnected(connected === undefined ? false : connected); - }; - - subscribeToNetworkChanges(); - - return () => { - subscription?.remove(); - }; - }, []); - - return {children}; -}; diff --git a/apps/mobile-legacy/src/providers/root-providers.tsx b/apps/mobile-legacy/src/providers/root-providers.tsx deleted file mode 100644 index 4bb3e2e..0000000 --- a/apps/mobile-legacy/src/providers/root-providers.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type React from "react"; -import { GestureHandlerRootView } from "react-native-gesture-handler"; -import { SafeAreaProvider } from "react-native-safe-area-context"; - -import { AuthProvider } from "@/providers/auth-provider"; -import { FontsLoaderProvider } from "@/providers/fonts-loader-provider"; -import { NetworkProvider } from "@/providers/network-provider"; -import { TamaguiConfigProvider } from "@/providers/tamagui-config-provider"; -import { TanstackQueryProvider } from "@/providers/tanstack-query-provider"; - -export const RootProviders = ({ children }: React.PropsWithChildren) => ( - - - - - - - {children} - - - - - - -); diff --git a/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx b/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx deleted file mode 100644 index d90c20f..0000000 --- a/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import type React from "react"; -import { TamaguiProvider } from "tamagui"; - -import { config } from "~/tamagui.config"; - -export const TamaguiConfigProvider = ({ children }: React.PropsWithChildren) => ( - {children} -); diff --git a/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx b/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx deleted file mode 100644 index 7a10949..0000000 --- a/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import type React from "react"; - -export const queryClient = new QueryClient(); - -export const TanstackQueryProvider = ({ children }: React.PropsWithChildren) => ( - {children} -); diff --git a/apps/mobile-legacy/src/store/auth.ts b/apps/mobile-legacy/src/store/auth.ts deleted file mode 100644 index 9febd98..0000000 --- a/apps/mobile-legacy/src/store/auth.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as SecureStore from "expo-secure-store"; - -export const getAccessToken = () => SecureStore.getItemAsync("user_access_token"); -export const getRefreshToken = () => SecureStore.getItemAsync("user_refresh_token"); - -export const setTokens = async (access: string, refresh: string) => { - try { - await Promise.all([ - SecureStore.setItemAsync("user_access_token", access), - SecureStore.setItemAsync("user_refresh_token", refresh), - ]); - } catch (error) { - console.log(access, refresh); - console.error("Unable to save auth tokens", error); - } -}; - -export const clearTokens = async () => { - try { - await Promise.all([ - SecureStore.deleteItemAsync("user_access_token"), - SecureStore.deleteItemAsync("user_refresh_token"), - ]); - } catch (error) { - console.error("Unable to clear auth tokens", error); - } -}; diff --git a/apps/mobile-legacy/src/ui/components/AppIcon.tsx b/apps/mobile-legacy/src/ui/components/AppIcon.tsx deleted file mode 100644 index 9326652..0000000 --- a/apps/mobile-legacy/src/ui/components/AppIcon.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Image } from "tamagui"; - -type AppLogoProps = { - width?: number; - height?: number; -}; - -export const AppIcon = (props: AppLogoProps) => { - const { width = 80, height = 80 } = props; - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/LoadingView.tsx b/apps/mobile-legacy/src/ui/components/LoadingView.tsx deleted file mode 100644 index 7bfb953..0000000 --- a/apps/mobile-legacy/src/ui/components/LoadingView.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ActivityIndicator } from "react-native"; -import { View } from "tamagui"; - -import { Caption } from "@/ui/components/typography"; - -export const LoadingView = () => ( - - - Chargement... - -); diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx deleted file mode 100644 index f00f648..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Caption } from "@/ui/components/typography"; - -type ArticleCategoryPillProps = { - category: string; -}; - -export const ArticleCategoryPill = (props: ArticleCategoryPillProps) => { - const { category } = props; - - return {category}; -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx deleted file mode 100644 index ce38a0d..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { GetProps, Image, styled } from "tamagui"; - -const StyledImage = styled(Image, { - backgroundColor: "$gray3", - borderRadius: "$4", - objectFit: "cover", -}); - -type ArticleCoverImageProps = GetProps & { - uri: string; - width: string | number; - height: number; -}; - -export const ArticleCoverImage = (props: ArticleCoverImageProps) => { - const { width, height, uri, ...rest } = props; - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx deleted file mode 100644 index 2030516..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { useCallback } from "react"; -import { ActivityIndicator, Dimensions, FlatList, FlatListProps } from "react-native"; -import { View, XStack, YStack } from "tamagui"; - -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { ArticleMagazineCard } from "@/ui/components/content/article/ArticleMagazineCard"; -import { ArticleOverviewCard } from "@/ui/components/content/article/ArticleOverviewCard"; -import { ArticleTextOnlyCard } from "@/ui/components/content/article/ArticleTextOnlyCard"; -import { Text } from "@/ui/components/typography"; - -const { width: screenWidth } = Dimensions.get("window"); - -const HorizontalSeparator = () => ; -const VerticalSeparator = () => ; - -const LoadingIndicator = () => ( - <> - - - - -); - -export type ArticleListDisplayMode = "card" | "magazine" | "text-only"; - -type ArticleListProps = Omit, "renderItem"> & { - data: ArticleOverview[]; - horizontal?: boolean; - infiniteScroll?: boolean; - displayMode?: ArticleListDisplayMode; - hasNextPage?: boolean; - isFetchingNextPage?: boolean; - fetchNextPage?: () => void; -}; - -type ArticleListComponent = React.FC & { - HorizontalSeparator: typeof HorizontalSeparator; - VerticalSeparator: typeof VerticalSeparator; - LoadingIndicator: typeof LoadingIndicator; -}; - -const keyExtractor = (item: ArticleOverview) => item.id; - -const selectDisplayComponent = (mode: ArticleListDisplayMode) => { - switch (mode) { - case "card": - return ArticleOverviewCard; - case "magazine": - return ArticleMagazineCard; - case "text-only": - return ArticleTextOnlyCard; - default: - throw new Error(`Unknown display mode: ${mode}`); - } -}; - -const ArticleList: ArticleListComponent = (props: ArticleListProps) => { - const { - data, - displayMode = "magazine", - horizontal = false, - infiniteScroll = false, - hasNextPage, - isFetchingNextPage, - fetchNextPage, - refreshing, - ...rest - } = props; - - const renderItem = useCallback( - ({ item }: { item: ArticleOverview }) => { - const itemWidth = horizontal ? screenWidth * 0.7 : undefined; - const DisplayComponent = selectDisplayComponent(displayMode); - - return ( - - - - ); - }, - [horizontal, displayMode], - ); - - const handleOnEndReached = useCallback(async () => { - if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) { - fetchNextPage(); - } - }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]); - - return ( - Pas d’articles disponibles pour le moment.} - ListFooterComponent={infiniteScroll ? LoadingIndicator : undefined} - onEndReached={handleOnEndReached} - onEndReachedThreshold={0.5} - refreshing={refreshing} - removeClippedSubviews={true} - renderItem={renderItem} - showsHorizontalScrollIndicator={false} - /> - ); -}; - -ArticleList.HorizontalSeparator = HorizontalSeparator; -ArticleList.VerticalSeparator = VerticalSeparator; -ArticleList.LoadingIndicator = LoadingIndicator; - -export { ArticleList }; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx deleted file mode 100644 index 34f4d78..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Link } from "expo-router"; -import { Card, XStack, YStack } from "tamagui"; - -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { useRelativeTime } from "@/hooks/use-relative-time"; -import { ArticleCoverImage } from "@/ui/components/content/article/ArticleCoverImage"; -import { SourceReferencePill } from "@/ui/components/content/source/SourceReferencePill"; -import { Caption, Text } from "@/ui/components/typography"; - -type ArticleMagazineCardProps = { - data: ArticleOverview; -}; - -export const ArticleMagazineCard = (props: ArticleMagazineCardProps) => { - const { data } = props; - const relativeTime = useRelativeTime(data.publishedAt); - - return ( - - - - - - {data.title} - - - {data.excerpt} - - - - {data.image && } - - - - - - - {relativeTime} - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx deleted file mode 100644 index 4d84a22..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Link } from "expo-router"; -import { Card, XStack, YStack } from "tamagui"; - -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { useRelativeTime } from "@/hooks/use-relative-time"; -import { ArticleCoverImage } from "@/ui/components/content/article/ArticleCoverImage"; -import { SourceReferencePill } from "@/ui/components/content/source/SourceReferencePill"; -import { Caption, Text } from "@/ui/components/typography"; - -type ArticleOverviewCardProps = { - data: ArticleOverview; -}; - -export const ArticleOverviewCard = (props: ArticleOverviewCardProps) => { - const { data } = props; - const relativeTime = useRelativeTime(data.publishedAt); - - return ( - - - {data.image && } - - - {data.title} - - - {data.excerpt} - - - - - - - - {relativeTime} - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx deleted file mode 100644 index 85da530..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { useCallback } from "react"; -import ContentLoader, { Circle, Rect } from "react-content-loader/native"; -import { Dimensions, FlatList } from "react-native"; -import { View } from "tamagui"; - -import { ArticleList, ArticleListDisplayMode } from "@/ui/components/content/article/ArticleList"; - -const { width: screenWidth } = Dimensions.get("window"); -const data: number[] = new Array(5).fill(0); - -type ArticleSkeletonListProps = { - horizontal?: boolean; - displayMode?: ArticleListDisplayMode; -}; - -const OverviewCardSkeleton = (props: any) => ( - - - - - - - - - - - - -); - -const MagazineCardSkeleton = (props: any) => ( - - - - - - - - - - - - - -); - -const TextOnlyCardSkeleton = (props: any) => ( - - - - - - - - - - - -); - -const keyExtractor = (_: number, index: number) => index.toString(); - -const selectSkeletonComponent = (displayMode: ArticleListDisplayMode) => { - switch (displayMode) { - case "magazine": - return MagazineCardSkeleton; - case "text-only": - return TextOnlyCardSkeleton; - default: - return OverviewCardSkeleton; - } -}; - -export const ArticleSkeletonList = (props: ArticleSkeletonListProps) => { - const { horizontal = false, displayMode = "magazine" } = props; - - const ItemSeparator = horizontal - ? ArticleList.HorizontalSeparator - : ArticleList.VerticalSeparator; - - const renderItem = useCallback(() => { - const itemWidth = horizontal ? screenWidth * 0.7 : screenWidth; - const SkeletonComponent = selectSkeletonComponent(displayMode); - - return ( - - - - ); - }, [horizontal, displayMode]); - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx deleted file mode 100644 index 57db9fc..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Link } from "expo-router"; -import { Card, XStack, YStack } from "tamagui"; - -import { ArticleOverview } from "@/api/schema/feed-management/article"; -import { useRelativeTime } from "@/hooks/use-relative-time"; -import { SourceReferencePill } from "@/ui/components/content/source/SourceReferencePill"; -import { Caption, Text } from "@/ui/components/typography"; - -type ArticleTextOnlyCardProps = { - data: ArticleOverview; -}; - -export const ArticleTextOnlyCard = (props: ArticleTextOnlyCardProps) => { - const { data } = props; - const relativeTime = useRelativeTime(data.publishedAt); - - return ( - - - - - - {data.title} - - - {data.excerpt} - - - - - - - - - {relativeTime} - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/article/index.tsx b/apps/mobile-legacy/src/ui/components/content/article/index.tsx deleted file mode 100644 index a3a93ec..0000000 --- a/apps/mobile-legacy/src/ui/components/content/article/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export { ArticleCategoryPill } from "@/ui/components/content/article/ArticleCategoryPill"; -export { ArticleCoverImage } from "@/ui/components/content/article/ArticleCoverImage"; -export { ArticleList } from "@/ui/components/content/article/ArticleList"; -export { ArticleMagazineCard } from "@/ui/components/content/article/ArticleMagazineCard"; -export { ArticleOverviewCard } from "@/ui/components/content/article/ArticleOverviewCard"; -export { ArticleSkeletonList } from "@/ui/components/content/article/ArticleSkeleton"; -export { ArticleTextOnlyCard } from "@/ui/components/content/article/ArticleTextOnlyCard"; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx deleted file mode 100644 index 7c7a74a..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Link } from "expo-router"; -import { Card, XStack, YStack } from "tamagui"; - -import { Bookmark } from "@/api/schema/feed-management/bookmark"; -import { useRelativeTime } from "@/hooks/use-relative-time"; -import { Caption, Text } from "@/ui/components/typography"; - -type BookmarkCardProps = { - data: Bookmark; -}; - -export const BookmarkCard = (props: BookmarkCardProps) => { - const { data } = props; - const relativeTime = useRelativeTime(data.createdAt); - - return ( - - - - - - - - {data.name} - - {data.description && ( - - {data.description} - - )} - - - - - - - {data.isPublic} - {data.articlesCount} articles - {relativeTime} - - - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx deleted file mode 100644 index 49e9466..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { YStack } from "tamagui"; - -import BookmarkIllustration from "@/assets/illustrations/BookmarkIllustration"; -import { CreateBookmarkSheet } from "@/ui/components/content/bookmark/CreateBookmarkSheet"; -import { Heading, Text } from "@/ui/components/typography"; - -export const BookmarkEmptyState = () => { - return ( - - - Empty Bookmarks - - Create a bookmark to save your favorite articles and access them later. - - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx deleted file mode 100644 index 9691fab..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { useCallback } from "react"; -import { ActivityIndicator, FlatList, FlatListProps } from "react-native"; -import { YStack } from "tamagui"; - -import { Bookmark } from "@/api/schema/feed-management/bookmark"; -import { BookmarkCard } from "@/ui/components/content/bookmark/BookmarkCard"; -import { BookmarkEmptyState } from "@/ui/components/content/bookmark/BookmarkEmptyState"; - -const VerticalSeparator = () => ; - -const LoadingIndicator = () => ( - <> - - - - -); - -type BookmarkListProps = Omit, "renderItem"> & { - data: Bookmark[]; - infiniteScroll?: boolean; - hasNextPage?: boolean; - isFetchingNextPage?: boolean; - fetchNextPage?: () => void; -}; - -type BookmarkListComponent = React.FC & { - VerticalSeparator: typeof VerticalSeparator; - LoadingIndicator: typeof LoadingIndicator; -}; - -const keyExtractor = (item: Bookmark) => item.id; - -const renderItem = ({ item }: { item: Bookmark }) => { - return ; -}; - -const BookmarkList: BookmarkListComponent = (props: BookmarkListProps) => { - const { - data, - infiniteScroll = false, - hasNextPage, - isFetchingNextPage, - fetchNextPage, - refreshing, - ...rest - } = props; - - const handleOnEndReached = useCallback(async () => { - if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) { - fetchNextPage(); - } - }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]); - - return ( - } - ListFooterComponent={infiniteScroll && refreshing ? LoadingIndicator : undefined} - onEndReached={handleOnEndReached} - onEndReachedThreshold={0.5} - refreshing={refreshing} - removeClippedSubviews={true} - renderItem={renderItem} - showsHorizontalScrollIndicator={false} - /> - ); -}; - -BookmarkList.VerticalSeparator = VerticalSeparator; -BookmarkList.LoadingIndicator = LoadingIndicator; - -export { BookmarkList }; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx deleted file mode 100644 index 6137d7f..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { joiResolver } from "@hookform/resolvers/joi"; -import { Sheet } from "@tamagui/sheet"; -import { useState } from "react"; -import { useForm } from "react-hook-form"; -import Toast from "react-native-toast-message"; -import { Button, YStack } from "tamagui"; - -import { useCreateBookmark } from "@/api/request/feed-management/bookmark"; -import { BookmarkPayload, BookmarkPayloadSchema } from "@/api/schema/feed-management/bookmark"; -import { ErrorResponse, safeMessage } from "@/api/shared"; -import { FormSwitch, FormTextArea, FormTextInput } from "@/ui/components/controls/forms"; -import { SubmitButton } from "@/ui/components/controls/SubmitButton"; - -export const CreateBookmarkSheet = () => { - const { mutate, isPending } = useCreateBookmark(); - const [open, setOpen] = useState(false); - - const { control, handleSubmit, formState } = useForm({ - resolver: joiResolver(BookmarkPayloadSchema), - }); - - const onSubmit = (data: BookmarkPayload) => { - mutate(data, { - onError: (error: ErrorResponse) => { - Toast.show({ - text1: "Erreur", - text2: safeMessage(error), - type: "error", - }); - }, - onSuccess: () => { - Toast.show({ - text1: "Félicitations !", - text2: "Votre signet a été créé avec succès.", - type: "success", - }); - setOpen(false); - }, - }); - }; - - return ( - - - - - - - - - - - - - - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx deleted file mode 100644 index 7b3bafe..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { joiResolver } from "@hookform/resolvers/joi"; -import { Sheet } from "@tamagui/sheet"; -import { useEffect, useState } from "react"; -import { useForm } from "react-hook-form"; -import Toast from "react-native-toast-message"; -import { Button, YStack } from "tamagui"; - -import { useUpdateBookmark } from "@/api/request/feed-management/bookmark"; -import { - Bookmark, - BookmarkPayload, - BookmarkPayloadSchema, -} from "@/api/schema/feed-management/bookmark"; -import { ErrorResponse, safeMessage } from "@/api/shared"; -import { FormSwitch } from "@/ui/components/controls/forms/Switch"; -import { FormTextArea } from "@/ui/components/controls/forms/TextArea"; -import { FormTextInput } from "@/ui/components/controls/forms/TextInput"; -import { SubmitButton } from "@/ui/components/controls/SubmitButton"; - -type UpdateBookmarkSheetProps = { - data: Bookmark; -}; - -export const UpdateBookmarkSheet = (props: UpdateBookmarkSheetProps) => { - const { data } = props; - const { mutate, isPending } = useUpdateBookmark(data.id); - const [open, setOpen] = useState(false); - - const { control, handleSubmit, formState, reset } = useForm({ - resolver: joiResolver(BookmarkPayloadSchema), - }); - - useEffect(() => { - reset({ ...data }); - }, [data, reset]); - - const onSubmit = (data: BookmarkPayload) => { - mutate(data, { - onError: (error: ErrorResponse) => { - Toast.show({ - text1: "Erreur", - text2: safeMessage(error), - type: "error", - }); - }, - onSuccess: () => { - Toast.show({ - text1: "Félicitations !", - text2: "Votre signet a été modifié avec succès.", - type: "success", - }); - setOpen(false); - }, - }); - }; - - return ( - - - - - - - - - - - - - - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/index.ts b/apps/mobile-legacy/src/ui/components/content/bookmark/index.ts deleted file mode 100644 index 21225e3..0000000 --- a/apps/mobile-legacy/src/ui/components/content/bookmark/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { BookmarkCard } from "@/ui/components/content/bookmark/BookmarkCard"; -export { BookmarkEmptyState } from "@/ui/components/content/bookmark/BookmarkEmptyState"; -export { BookmarkList } from "@/ui/components/content/bookmark/BookmarkList"; -export { CreateBookmarkSheet } from "@/ui/components/content/bookmark/CreateBookmarkSheet"; -export { UpdateBookmarkSheet } from "@/ui/components/content/bookmark/UpdateBookmarkSheet"; diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx deleted file mode 100644 index b65a758..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useCallback, useState } from "react"; -import { ActivityIndicator, Alert } from "react-native"; -import { Button, GetProps } from "tamagui"; - -import { useFollowSource, useUnfollowSource } from "@/api/request/feed-management/source"; - -type SourceFollowButtonProps = GetProps & { - id: string; - name: string; - followed: boolean; -}; - -export const SourceFollowButton = (props: SourceFollowButtonProps) => { - const { id, followed, name, ...rest } = props; - const [isFollowed, setIsFollowed] = useState(followed); - const { mutate: follow, isPending: following } = useFollowSource(id); - const { mutate: unfollow, isPending: unfollowing } = useUnfollowSource(id); - const loading = following || unfollowing; - - const handlePress = useCallback(() => { - if (isFollowed) { - Alert.alert( - "Confirmation", - `Êtes-vous sûr de vouloir ne plus suivre ${name} ?`, - [ - { - style: "cancel", - text: "Annuler", - }, - { - onPress: () => { - unfollow(); - setIsFollowed((prev) => !prev); - }, - style: "destructive", - text: "Ne plus suivre", - }, - ], - { cancelable: false }, - ); - } else { - follow(); - setIsFollowed((prev) => !prev); - } - }, [isFollowed, name, unfollow, follow]); - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx deleted file mode 100644 index 6ab067e..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useCallback } from "react"; -import { FlatList, FlatListProps } from "react-native"; -import { Paragraph, XStack, YStack } from "tamagui"; - -import { SourceOverview } from "@/api/schema/feed-management/source"; -import { SourceOverviewCard } from "@/ui/components/content/source/SourceOverviewCard"; - -const HorizontalSeparator = () => ; -const VerticalSeparator = () => ; - -type SourceOverviewListProps = Omit, "renderItem"> & { - data: SourceOverview[]; - horizontal?: boolean; - infiniteScroll?: boolean; -}; - -type SourceOverviewListComponent = React.FC & { - HorizontalSeparator: typeof HorizontalSeparator; - VerticalSeparator: typeof VerticalSeparator; -}; - -const keyExtractor = (item: SourceOverview) => item.name; - -const SourceList: SourceOverviewListComponent = (props: SourceOverviewListProps) => { - const { data, horizontal = false, ...rest } = props; - - const renderItem = useCallback( - ({ item }: { item: SourceOverview }) => { - return ; - }, - [horizontal], - ); - - return ( - Pas de sources disponibles pour le moment.} - onEndReachedThreshold={0.5} - removeClippedSubviews={true} - renderItem={renderItem} - showsHorizontalScrollIndicator={false} - /> - ); -}; - -SourceList.HorizontalSeparator = HorizontalSeparator; -SourceList.VerticalSeparator = VerticalSeparator; - -export { SourceList }; diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx deleted file mode 100644 index be0c03a..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Link } from "expo-router"; -import { GetProps, XStack, YStack, styled } from "tamagui"; - -import { SourceOverview } from "@/api/schema/feed-management/source"; -import { SourceFollowButton } from "@/ui/components/content/source/SourceFollowButton"; -import { SourceProfileImage } from "@/ui/components/content/source/SourceProfileImage"; -import { Text } from "@/ui/components/typography"; - -const SourceCardFrame = styled(YStack, { - alignItems: "center", - borderRadius: "$4", - gap: "$2", - - variants: { - horizontal: { - false: { - flexDirection: "row", - gap: "$4", - justifyContent: "space-between", - paddingVertical: "$2", - width: "100%", - }, - true: { - flexShrink: 0, - maxWidth: 100, - }, - }, - }, -} as const); - -type SourceCardProps = GetProps & { - data: SourceOverview; - horizontal?: boolean; -}; - -export const SourceOverviewCard = (props: SourceCardProps) => { - const { data, horizontal = true, ...rest } = props; - - const nameFontSize = horizontal ? "$3" : "$4"; - - return ( - - - - - - - {horizontal ? ( - - {data.displayName ?? data.name} - - ) : ( - - - - {data.displayName ?? data.name} - - - - - {data.url} - - - )} - - - - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx deleted file mode 100644 index 5014123..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { GetProps, Image, styled } from "tamagui"; - -const StyledImage = styled(Image, { - backgroundColor: "white", - borderRadius: "$12", -}); - -type SourceAvatarProps = GetProps & { - image: string; - name: string; - size?: number; -}; - -export const SourceProfileImage = (props: SourceAvatarProps) => { - const { image, name, size = 50, ...rest } = props; - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx deleted file mode 100644 index e082a0b..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Link } from "expo-router"; -import { Avatar, GetProps, XStack } from "tamagui"; - -import { SourceReference } from "@/api/schema/feed-management/source"; -import { Text } from "@/ui/components/typography"; - -type SourceReferencePillProps = GetProps & { - data: SourceReference; -}; - -export function SourceReferencePill(props: SourceReferencePillProps) { - const { data, ...rest } = props; - - return ( - - - - - - - - {data.displayName ?? data.name} - - - - ); -} diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx deleted file mode 100644 index 04d60db..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { useCallback } from "react"; -import ContentLoader, { Circle, Rect } from "react-content-loader/native"; -import { FlatList } from "react-native"; -import { YStack } from "tamagui"; - -import { SourceList } from "@/ui/components/content/source/SourceList"; - -const data: number[] = new Array(5).fill(0); - -type SourceSkeletonListProps = { - horizontal?: boolean; -}; - -const VerticalSkeleton = (props: any) => ( - - - - - - -); - -const HorizontalSkeleton = (props: any) => ( - - - - - -); - -const keyExtractor = (_: number, index: number) => index.toString(); - -const selectSkeletonComponent = (horizontal: boolean) => { - return horizontal ? ( - - ) : ( - - - - ); -}; - -export const SourceSkeletonList = (props: SourceSkeletonListProps) => { - const { horizontal = false } = props; - - const ItemSeparator = horizontal ? SourceList.HorizontalSeparator : SourceList.VerticalSeparator; - - const renderItem = useCallback(() => { - return selectSkeletonComponent(horizontal); - }, [horizontal]); - - return ( - - ); -}; diff --git a/apps/mobile-legacy/src/ui/components/content/source/index.ts b/apps/mobile-legacy/src/ui/components/content/source/index.ts deleted file mode 100644 index 4128321..0000000 --- a/apps/mobile-legacy/src/ui/components/content/source/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { SourceFollowButton } from "@/ui/components/content/source/SourceFollowButton"; -export { SourceList } from "@/ui/components/content/source/SourceList"; -export { SourceOverviewCard } from "@/ui/components/content/source/SourceOverviewCard"; -export { SourceProfileImage } from "@/ui/components/content/source/SourceProfileImage"; -export { SourceReferencePill } from "@/ui/components/content/source/SourceReferencePill"; -export { SourceSkeletonList } from "@/ui/components/content/source/SourceSkeleton"; diff --git a/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx b/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx deleted file mode 100644 index 809d3ea..0000000 --- a/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { ArrowLeft } from "@tamagui/lucide-icons"; -import { Button, ButtonProps } from "tamagui"; - -type BackButtonProps = { - onPress: () => void; -}; - -export const BackButton = (props: BackButtonProps & ButtonProps) => { - const { onPress, ...rest } = props; - - return ( -