From 1d0d3f956aa0eb6795d4e987d52a5612d6976214 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 13:02:11 +0700 Subject: [PATCH 01/21] fix: make `FileRepository` implement `ResetInterface` (#135) --- CHANGELOG.md | 4 ++++ composer.json | 2 +- packages/file-bundle/config/file.php | 11 ++++++++--- packages/file/composer.json | 3 ++- packages/file/src/Repository/FileRepository.php | 9 ++++++++- tests/src/Tests/Architecture/Architecture.php | 1 + 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a7ecc8..928d106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 2.0.1 + +* fix: make `FileRepository` implement `ResetInterface` + ## 2.0.0 * chore: clean up `FileAssociationManager` diff --git a/composer.json b/composer.json index da0c953..84b02aa 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ "symfony/http-foundation": "^6.2 || ^7.0", "symfony/http-kernel": "^6.2 || ^7.0", "symfony/options-resolver": "^6.2 || ^7.0", - "symfony/service-contracts": "^3.3", + "symfony/service-contracts": "^3.1", "symfony/stimulus-bundle": "^2.12", "symfony/translation-contracts": "^3.0", "symfony/validator": "^6.3 || ^7.1", diff --git a/packages/file-bundle/config/file.php b/packages/file-bundle/config/file.php index 08edd02..6d0fbe3 100644 --- a/packages/file-bundle/config/file.php +++ b/packages/file-bundle/config/file.php @@ -21,11 +21,16 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); - $services->set(FileFactory::class); + $services + ->set(FileFactory::class); - $services->set(FileRepositoryInterface::class, FileRepository::class) + $services + ->set(FileRepositoryInterface::class) + ->class(FileRepository::class) ->factory([ service(FileFactory::class), 'getFileRepository', - ]); + ]) + ->tag('kernel.reset', ['method' => 'reset']) + ; }; diff --git a/packages/file/composer.json b/packages/file/composer.json index c5db733..2379bda 100644 --- a/packages/file/composer.json +++ b/packages/file/composer.json @@ -35,7 +35,8 @@ "league/mime-type-detection": "^1.0.0", "rekalogika/file-contracts": "^2.0", "rekalogika/file-metadata": "^2.0", - "symfony/deprecation-contracts": "^3.1" + "symfony/deprecation-contracts": "^3.1", + "symfony/service-contracts": "^3.1" }, "require-dev": { "nyholm/psr7": "^1.8" diff --git a/packages/file/src/Repository/FileRepository.php b/packages/file/src/Repository/FileRepository.php index 90d8c65..9050fcd 100644 --- a/packages/file/src/Repository/FileRepository.php +++ b/packages/file/src/Repository/FileRepository.php @@ -30,8 +30,9 @@ use Rekalogika\File\MetadataGenerator\MetadataGeneratorInterface; use Rekalogika\File\RawMetadata; use Rekalogika\File\TemporaryFile; +use Symfony\Contracts\Service\ResetInterface; -final class FileRepository implements FileRepositoryInterface +final class FileRepository implements FileRepositoryInterface, ResetInterface { /** * @var array @@ -45,6 +46,12 @@ public function __construct( private readonly ?string $defaultFilesystemIdForTemporaryFile = null, ) {} + #[\Override] + public function reset() + { + $this->fileCache = []; + } + #[\Override] public function clear(): void { diff --git a/tests/src/Tests/Architecture/Architecture.php b/tests/src/Tests/Architecture/Architecture.php index d6a17b7..79a3a10 100644 --- a/tests/src/Tests/Architecture/Architecture.php +++ b/tests/src/Tests/Architecture/Architecture.php @@ -150,6 +150,7 @@ public function testFile(): Rule Selector::inNamespace('League\Flysystem'), Selector::inNamespace('League\MimeTypeDetection'), Selector::inNamespace('Psr\Http\Message'), + Selector::inNamespace('Symfony\Contracts\Service'), // dependencies on optional packages $this->getFileSymfonyBridge(), From abac58e3ac4cf78fe51349fc25e99654a50b6d15 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 13:08:51 +0700 Subject: [PATCH 02/21] style: improve profiler UI (#136) --- CHANGELOG.md | 1 + .../templates/data_collector.html.twig | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 928d106..bb42dca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.0.1 * fix: make `FileRepository` implement `ResetInterface` +* style: improve profiler UI ## 2.0.0 diff --git a/packages/file-bundle/templates/data_collector.html.twig b/packages/file-bundle/templates/data_collector.html.twig index 3d42cb1..e0f42f5 100644 --- a/packages/file-bundle/templates/data_collector.html.twig +++ b/packages/file-bundle/templates/data_collector.html.twig @@ -35,6 +35,9 @@ {{ source("@RekalogikaFile/file.svg") }} File + + {{ collector.objectCount }} + {% endblock %} @@ -85,9 +88,15 @@ - - - + + + + + + + + + @@ -101,7 +110,7 @@ {% endblock %} {% block object_result %} - + - + From c1c35fc5eae8edbd53a41a1ed423b68e400d587d Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 14:23:17 +0700 Subject: [PATCH 03/21] refactor: make internal services use non-class service names (#137) * refactor: make internal services use non-class service names * file-bundle file-image * the rest * fix --- CHANGELOG.md | 1 + composer.json | 2 +- .../LoggingFilePropertyManager.php | 6 +- .../config/file-association-debug.php | 17 ++- .../file-bundle/config/file-association.php | 138 ++++++++++++------ packages/file-bundle/config/file-bundle.php | 16 +- packages/file-bundle/config/file-image.php | 15 +- packages/file-bundle/config/file-server.php | 4 +- packages/file-bundle/config/file-zip.php | 22 ++- packages/file-bundle/config/file.php | 6 +- .../RekalogikaFileExtension.php | 4 +- packages/file-filepond/composer.json | 2 +- packages/file-server/composer.json | 2 +- packages/file-zip/composer.json | 2 +- .../FileAssociation/ObjectManagerTest.php | 9 +- 15 files changed, 158 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb42dca..264272e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * fix: make `FileRepository` implement `ResetInterface` * style: improve profiler UI +* refactor: make internal services use non-class service names ## 2.0.0 diff --git a/composer.json b/composer.json index 84b02aa..5ff8abb 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "psr/log": "^2 || ^3", "rekalogika/doctrine-collections-decorator": "^2.0", "rekalogika/reconstitutor": "^2.0.2", - "rekalogika/temporary-url-bundle": "^1.7", + "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", diff --git a/packages/file-association/src/FilePropertyManager/LoggingFilePropertyManager.php b/packages/file-association/src/FilePropertyManager/LoggingFilePropertyManager.php index e763564..e55d843 100644 --- a/packages/file-association/src/FilePropertyManager/LoggingFilePropertyManager.php +++ b/packages/file-association/src/FilePropertyManager/LoggingFilePropertyManager.php @@ -19,11 +19,11 @@ use Rekalogika\File\Association\Model\PropertyOperationAction; use Rekalogika\File\Association\Model\PropertyOperationResult; -final class LoggingFilePropertyManager implements FilePropertyManagerInterface +final readonly class LoggingFilePropertyManager implements FilePropertyManagerInterface { public function __construct( - private readonly FilePropertyManagerInterface $decorated, - private readonly ?LoggerInterface $logger, + private FilePropertyManagerInterface $decorated, + private ?LoggerInterface $logger, ) {} #[\Override] diff --git a/packages/file-bundle/config/file-association-debug.php b/packages/file-bundle/config/file-association-debug.php index b7d2b9c..bc00a30 100644 --- a/packages/file-bundle/config/file-association-debug.php +++ b/packages/file-bundle/config/file-association-debug.php @@ -11,8 +11,6 @@ * that was distributed with this source code. */ -use Rekalogika\File\Association\Contracts\FilePropertyManagerInterface; -use Rekalogika\File\Association\Contracts\ObjectManagerInterface; use Rekalogika\File\Bundle\Debug\FileDataCollector; use Rekalogika\File\Bundle\Debug\TraceableFilePropertyManager; use Rekalogika\File\Bundle\Debug\TraceableObjectManager; @@ -24,7 +22,8 @@ $services = $containerConfigurator->services(); $services - ->set(FileDataCollector::class) + ->set('rekalogika.file.association.debug.data_collector') + ->class(FileDataCollector::class) ->tag('data_collector', [ 'id' => 'rekalogika_file', ]) @@ -32,18 +31,20 @@ ; $services - ->set(TraceableObjectManager::class) - ->decorate(ObjectManagerInterface::class) + ->set('rekalogika.file.association.debug.traceable_object_manager') + ->class(TraceableObjectManager::class) + ->decorate('rekalogika.file.association.object_manager') ->args([ service('.inner'), service('debug.stopwatch'), - service(FileDataCollector::class), + service('rekalogika.file.association.debug.data_collector'), ]) ; $services - ->set(TraceableFilePropertyManager::class) - ->decorate(FilePropertyManagerInterface::class) + ->set('rekalogika.file.association.debug.traceable_file_property_manager') + ->class(TraceableFilePropertyManager::class) + ->decorate('rekalogika.file.association.file_property_manager') ->args([ service('.inner'), service('debug.stopwatch'), diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index fe61c02..6039ae2 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -21,12 +21,8 @@ use Rekalogika\File\Association\ClassSignatureResolver\ChainClassSignatureResolver; use Rekalogika\File\Association\ClassSignatureResolver\DefaultClassSignatureResolver; use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; -use Rekalogika\File\Association\Contracts\ClassMetadataFactoryInterface; use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; -use Rekalogika\File\Association\Contracts\FilePropertyManagerInterface; use Rekalogika\File\Association\Contracts\ObjectIdResolverInterface; -use Rekalogika\File\Association\Contracts\ObjectManagerInterface; -use Rekalogika\File\Association\Contracts\PropertyListerInterface; use Rekalogika\File\Association\FilePropertyManager\DefaultFilePropertyManager; use Rekalogika\File\Association\FilePropertyManager\LoggingFilePropertyManager; use Rekalogika\File\Association\ObjectIdResolver\ChainedObjectIdResolver; @@ -50,16 +46,20 @@ // reconstitutors // - $services->set(InterfaceReconstitutor::class) + $services + ->set('rekalogika.file.association.reconstitutor.interface') + ->class(InterfaceReconstitutor::class) ->args([ - service(ObjectManagerInterface::class), + service('rekalogika.file.association.object_manager'), ]) ->tag('rekalogika.reconstitutor.class') ; - $services->set(AttributeReconstitutor::class) + $services + ->set('rekalogika.file.association.reconstitutor.attribute') + ->class(AttributeReconstitutor::class) ->args([ - service(ObjectManagerInterface::class), + service('rekalogika.file.association.object_manager'), ]) ->tag('rekalogika.reconstitutor.attribute') ; @@ -69,20 +69,21 @@ // $services - ->set(ObjectManagerInterface::class) + ->set('rekalogika.file.association.object_manager') ->class(DefaultObjectManager::class) ->args([ - '$classMetadataFactory' => service(ClassMetadataFactoryInterface::class), + '$classMetadataFactory' => service('rekalogika.file.association.class_metadata_factory'), '$objectIdResolver' => service(ObjectIdResolverInterface::class), - '$filePropertyManager' => service(FilePropertyManagerInterface::class), - ]); + '$filePropertyManager' => service('rekalogika.file.association.file_property_manager'), + ]) + ; // // property manager // $services - ->set(FilePropertyManagerInterface::class) + ->set('rekalogika.file.association.file_property_manager') ->class(DefaultFilePropertyManager::class) ->args([ '$fileRepository' => service(FileRepositoryInterface::class), @@ -91,8 +92,9 @@ ; $services - ->set(LoggingFilePropertyManager::class) - ->decorate(FilePropertyManagerInterface::class) + ->set('rekalogika.file.association.file_property_manager.logging') + ->class(LoggingFilePropertyManager::class) + ->decorate('rekalogika.file.association.file_property_manager') ->args([ service('.inner'), service('logger')->nullOnInvalid(), @@ -106,111 +108,153 @@ $services->alias( ObjectIdResolverInterface::class, - ChainedObjectIdResolver::class, + 'rekalogika.file.association.object_id_resolver.chained', ); - $services->set(ChainedObjectIdResolver::class) + $services + ->set('rekalogika.file.association.object_id_resolver.chained') + ->class(ChainedObjectIdResolver::class) ->args([ tagged_iterator('rekalogika.file.association.object_id_resolver'), - ]); + ]) + ; - $services->set(DefaultObjectIdResolver::class) + $services + ->set('rekalogika.file.association.object_id_resolver.default') + ->class(DefaultObjectIdResolver::class) ->tag('rekalogika.file.association.object_id_resolver', [ 'priority' => -1000, - ]); + ]) + ; if (interface_exists(ManagerRegistry::class)) { - $services->set(DoctrineObjectIdResolver::class) + $services + ->set(DoctrineObjectIdResolver::class) ->args([ service(ManagerRegistry::class), ]) ->tag('rekalogika.file.association.object_id_resolver', [ 'priority' => -999, - ]); + ]) + ; } // // class-based file location resolver // + $services->alias( + ClassBasedFileLocationResolverInterface::class, + 'rekalogika.file.association.class_based_file_location_resolver.chained', + ); + $services - ->set(ClassBasedFileLocationResolverInterface::class) + ->set('rekalogika.file.association.class_based_file_location_resolver.chained') ->class(ChainedClassBasedFileLocationResolver::class) ->args([ tagged_iterator('rekalogika.file.association.class_based_file_location_resolver'), - ]); + ]) + ; $services - ->set(DefaultClassBasedFileLocationResolver::class) + ->set('rekalogika.file.association.class_based_file_location_resolver.default') + ->class(DefaultClassBasedFileLocationResolver::class) ->args([ - service(ClassMetadataFactoryInterface::class), + service('rekalogika.file.association.class_metadata_factory'), ]) ->tag('rekalogika.file.association.class_based_file_location_resolver', [ 'priority' => -1000, - ]); + ]) + ; // // class signature resolver // + $services->alias( + ClassSignatureResolverInterface::class, + 'rekalogika.file.association.class_signature_resolver.chained', + ); + $services - ->set(ClassSignatureResolverInterface::class) + ->set('rekalogika.file.association.class_signature_resolver.chained') ->class(ChainClassSignatureResolver::class) ->args([ tagged_iterator('rekalogika.file.association.class_signature_resolver'), - ]); + ]) + ; $services - ->set(DefaultClassSignatureResolver::class) + ->set('rekalogika.file.association.class_signature_resolver.default') + ->class(DefaultClassSignatureResolver::class) ->tag('rekalogika.file.association.class_signature_resolver', [ 'priority' => -1000, - ]); + ]) + ; $services - ->set(AttributeClassSignatureResolver::class) + ->set('rekalogika.file.association.class_signature_resolver.attribute') + ->class(AttributeClassSignatureResolver::class) ->tag('rekalogika.file.association.class_signature_resolver', [ 'priority' => -999, - ]); + ]) + ; // // property lister // - $services->alias(PropertyListerInterface::class, ChainPropertyLister::class); + $services->alias( + 'rekalogika.file.association.property_lister', + 'rekalogika.file.association.property_lister.chain', + ); - $services->set(ChainPropertyLister::class) + $services + ->set('rekalogika.file.association.property_lister.chain') + ->class(ChainPropertyLister::class) ->args([ tagged_iterator('rekalogika.file.association.property_lister'), - ]); + ]) + ; - $services->set(FileAssociationInterfacePropertyLister::class) - ->tag('rekalogika.file.association.property_lister'); + $services + ->set('rekalogika.file.association.property_lister.file_association_interface') + ->class(FileAssociationInterfacePropertyLister::class) + ->tag('rekalogika.file.association.property_lister') + ; - $services->set(AttributesPropertyLister::class) - ->tag('rekalogika.file.association.property_lister'); + $services + ->set('rekalogika.file.association.property_lister.attributes') + ->class(AttributesPropertyLister::class) + ->tag('rekalogika.file.association.property_lister') + ; // // class metadata factory // $services - ->set(ClassMetadataFactoryInterface::class) + ->set('rekalogika.file.association.class_metadata_factory') ->class(DefaultClassMetadataFactory::class) ->args([ - service(PropertyListerInterface::class), + service('rekalogika.file.association.property_lister'), service(ClassSignatureResolverInterface::class), - ]); + ]) + ; $services ->set('rekalogika.file.association.class_metadata_factory.cache') ->parent('cache.system') - ->tag('cache.pool'); + ->tag('cache.pool') + ; $services - ->set(CachingClassMetadataFactory::class) - ->decorate(ClassMetadataFactoryInterface::class) + ->set('rekalogika.file.association.class_metadata_factory.caching') + ->class(CachingClassMetadataFactory::class) + ->decorate('rekalogika.file.association.class_metadata_factory') ->args([ service('.inner'), service('rekalogika.file.association.class_metadata_factory.cache'), - ]); + ]) + ; }; diff --git a/packages/file-bundle/config/file-bundle.php b/packages/file-bundle/config/file-bundle.php index 09fb5ff..f7bfe96 100644 --- a/packages/file-bundle/config/file-bundle.php +++ b/packages/file-bundle/config/file-bundle.php @@ -27,23 +27,29 @@ // $services - ->set(DefaultFilesystemFactory::class); + ->set(DefaultFilesystemFactory::class) + ; $services - ->set('rekalogika.file.default_filesystem', FilesystemOperator::class) + ->set('rekalogika.file.default_filesystem') + ->class(FilesystemOperator::class) ->factory([ service(DefaultFilesystemFactory::class), 'getDefaultFilesystem', - ]); + ]) + ; // // commands // - $services->set(FileLocationResolverCommand::class) + $services + ->set('rekalogika.file.command.file_location_resolver') + ->class(FileLocationResolverCommand::class) ->args([ '$fileLocationResolver' => service(ClassBasedFileLocationResolverInterface::class), ]) - ->tag('console.command'); + ->tag('console.command') + ; }; diff --git a/packages/file-bundle/config/file-image.php b/packages/file-bundle/config/file-image.php index 19246ed..6323a79 100644 --- a/packages/file-bundle/config/file-image.php +++ b/packages/file-bundle/config/file-image.php @@ -23,20 +23,25 @@ $services ->set(ImageResizer::class) - ->tag('rekalogika.file.derivation.filter'); + ->tag('rekalogika.file.derivation.filter') + ; $services - ->set(ImageTwigExtension::class) + ->set('rekalogika.file.image.twig_extension') + ->class(ImageTwigExtension::class) ->tag('twig.extension', [ 'priority' => 1000000, - ]); + ]) + ; $services - ->set(ImageTwigRuntime::class) + ->set('rekalogika.file.image.twig_runtime') + ->class(ImageTwigRuntime::class) ->args([ service(ImageResizer::class), ]) ->tag('twig.runtime', [ 'priority' => 1000000, - ]); + ]) + ; }; diff --git a/packages/file-bundle/config/file-server.php b/packages/file-bundle/config/file-server.php index 182a488..7efcc31 100644 --- a/packages/file-bundle/config/file-server.php +++ b/packages/file-bundle/config/file-server.php @@ -20,7 +20,9 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); - $services->set(FileInterfaceResourceServer::class) + $services + ->set('rekalogika.file.server.file_interface_resource_server') + ->class(FileInterfaceResourceServer::class) ->tag('rekalogika.temporary_url.resource_server', [ 'method' => 'respond', ]) diff --git a/packages/file-bundle/config/file-zip.php b/packages/file-bundle/config/file-zip.php index 72e1bf8..859c634 100644 --- a/packages/file-bundle/config/file-zip.php +++ b/packages/file-bundle/config/file-zip.php @@ -23,19 +23,26 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); - $services->set(FileZip::class) + $services + ->set(FileZip::class) ->args([ - service(ZipDirectory::class), + service('rekalogika.file.zip.zip_directory'), service(TranslatorInterface::class), - ]); + ]) + ; - $services->set(ZipDirectory::class) + $services + ->set('rekalogika.file.zip.zip_directory') + ->class(ZipDirectory::class) ->args([ service(FileRepositoryInterface::class), service(TranslatorInterface::class)->nullOnInvalid(), - ]); + ]) + ; - $services->set(DirectoryResourceServer::class) + $services + ->set('rekalogika.file.zip.directory_resource_server') + ->class(DirectoryResourceServer::class) ->args([ service(FileZip::class), service(TranslatorInterface::class), @@ -45,5 +52,6 @@ ]) ->tag('rekalogika.temporary_url.resource_transformer', [ 'method' => 'transform', - ]); + ]) + ; }; diff --git a/packages/file-bundle/config/file.php b/packages/file-bundle/config/file.php index 6d0fbe3..efe46a2 100644 --- a/packages/file-bundle/config/file.php +++ b/packages/file-bundle/config/file.php @@ -22,13 +22,15 @@ $services = $containerConfigurator->services(); $services - ->set(FileFactory::class); + ->set('rekalogika.file.factory') + ->class(FileFactory::class) + ; $services ->set(FileRepositoryInterface::class) ->class(FileRepository::class) ->factory([ - service(FileFactory::class), + service('rekalogika.file.factory'), 'getFileRepository', ]) ->tag('kernel.reset', ['method' => 'reset']) diff --git a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php index 1259842..c9e5336 100644 --- a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php +++ b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php @@ -105,11 +105,13 @@ public function load(array $configs, ContainerBuilder $container): void } $newFilesystems = []; + foreach ($filesystems as $name => $serviceId) { $newFilesystems[$name] = new Reference($serviceId); } - $container->getDefinition(FileFactory::class) + $container + ->getDefinition('rekalogika.file.factory') ->setArgument('$filesystems', $newFilesystems); // diff --git a/packages/file-filepond/composer.json b/packages/file-filepond/composer.json index 43bfce8..abd8d3f 100644 --- a/packages/file-filepond/composer.json +++ b/packages/file-filepond/composer.json @@ -33,7 +33,7 @@ "rekalogika/file-image": "^2.0", "rekalogika/file-server": "^2.0", "rekalogika/file-symfony-bridge": "^2.0", - "rekalogika/temporary-url-bundle": "^1.7", + "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/dependency-injection": "^6.2 || ^7.0", "symfony/form": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", diff --git a/packages/file-server/composer.json b/packages/file-server/composer.json index d054276..80b7e31 100644 --- a/packages/file-server/composer.json +++ b/packages/file-server/composer.json @@ -26,7 +26,7 @@ "php": "^8.2", "rekalogika/file-contracts": "^2.0", "rekalogika/file-symfony-bridge": "^2.0", - "rekalogika/temporary-url-bundle": "^1.7", + "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/http-foundation": "^6.2 || ^7.0" }, "extra": { diff --git a/packages/file-zip/composer.json b/packages/file-zip/composer.json index bd3076b..2d6f933 100644 --- a/packages/file-zip/composer.json +++ b/packages/file-zip/composer.json @@ -30,7 +30,7 @@ "psr/http-message": "^1.0 || ^2.0", "rekalogika/file-contracts": "^2.0", "rekalogika/file-metadata": "^2.0", - "rekalogika/temporary-url-bundle": "^1.7", + "rekalogika/temporary-url-bundle": "^1.7.2", "maennchen/zipstream-php": "^3.1", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/translation-contracts": "^3.0" diff --git a/tests/src/Tests/FileAssociation/ObjectManagerTest.php b/tests/src/Tests/FileAssociation/ObjectManagerTest.php index 8e27f4f..752aed7 100644 --- a/tests/src/Tests/FileAssociation/ObjectManagerTest.php +++ b/tests/src/Tests/FileAssociation/ObjectManagerTest.php @@ -39,16 +39,15 @@ final class ObjectManagerTest extends KernelTestCase protected function setUp(): void { - $fileAssociationManager = static::getContainer() - ->get(ObjectManagerInterface::class); + $objectManager = static::getContainer() + ->get('rekalogika.file.association.object_manager'); - // @phpstan-ignore method.alreadyNarrowedType $this->assertInstanceOf( ObjectManagerInterface::class, - $fileAssociationManager, + $objectManager, ); - $this->objectManager = $fileAssociationManager; + $this->objectManager = $objectManager; $fileRepository = static::getContainer() ->get(FileRepositoryInterface::class); From cd84b40ce4c5463f922121c184f5e0bb4835a0f7 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 15:11:21 +0700 Subject: [PATCH 04/21] fix: make `ClassMetadataFactoryInterface` autowireable (#138) --- CHANGELOG.md | 1 + packages/file-bundle/config/file-association.php | 9 +++++---- .../src/DependencyInjection/RekalogikaFileExtension.php | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 264272e..eaf9a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * fix: make `FileRepository` implement `ResetInterface` * style: improve profiler UI * refactor: make internal services use non-class service names +* fix: make `ClassMetadataFactoryInterface` autowireable ## 2.0.0 diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index 6039ae2..43a7fff 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -21,6 +21,7 @@ use Rekalogika\File\Association\ClassSignatureResolver\ChainClassSignatureResolver; use Rekalogika\File\Association\ClassSignatureResolver\DefaultClassSignatureResolver; use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; +use Rekalogika\File\Association\Contracts\ClassMetadataFactoryInterface; use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Contracts\ObjectIdResolverInterface; use Rekalogika\File\Association\FilePropertyManager\DefaultFilePropertyManager; @@ -72,7 +73,7 @@ ->set('rekalogika.file.association.object_manager') ->class(DefaultObjectManager::class) ->args([ - '$classMetadataFactory' => service('rekalogika.file.association.class_metadata_factory'), + '$classMetadataFactory' => service(ClassMetadataFactoryInterface::class), '$objectIdResolver' => service(ObjectIdResolverInterface::class), '$filePropertyManager' => service('rekalogika.file.association.file_property_manager'), ]) @@ -160,7 +161,7 @@ ->set('rekalogika.file.association.class_based_file_location_resolver.default') ->class(DefaultClassBasedFileLocationResolver::class) ->args([ - service('rekalogika.file.association.class_metadata_factory'), + service(ClassMetadataFactoryInterface::class), ]) ->tag('rekalogika.file.association.class_based_file_location_resolver', [ 'priority' => -1000, @@ -234,7 +235,7 @@ // $services - ->set('rekalogika.file.association.class_metadata_factory') + ->set(ClassMetadataFactoryInterface::class) ->class(DefaultClassMetadataFactory::class) ->args([ service('rekalogika.file.association.property_lister'), @@ -251,7 +252,7 @@ $services ->set('rekalogika.file.association.class_metadata_factory.caching') ->class(CachingClassMetadataFactory::class) - ->decorate('rekalogika.file.association.class_metadata_factory') + ->decorate(ClassMetadataFactoryInterface::class) ->args([ service('.inner'), service('rekalogika.file.association.class_metadata_factory.cache'), diff --git a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php index c9e5336..d979f1f 100644 --- a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php +++ b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php @@ -21,7 +21,6 @@ use Rekalogika\File\Association\Contracts\PropertyListerInterface; use Rekalogika\File\Bundle\DefaultFilesystemFactory; use Rekalogika\File\Derivation\Filter\FileFilterInterface; -use Rekalogika\File\FileFactory; use Rekalogika\File\Image\ImageResizer; use Rekalogika\File\Server\FileInterfaceResourceServer; use Rekalogika\File\Tests\TestKernel; From 7b860e43a4e3fca8900059a1a355fe341bdd5cb5 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 15:28:08 +0700 Subject: [PATCH 05/21] Revert "fix: make `ClassMetadataFactoryInterface` autowireable (#138)" (#142) This reverts commit cd84b40ce4c5463f922121c184f5e0bb4835a0f7. --- CHANGELOG.md | 1 - packages/file-bundle/config/file-association.php | 9 ++++----- .../src/DependencyInjection/RekalogikaFileExtension.php | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eaf9a4d..264272e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ * fix: make `FileRepository` implement `ResetInterface` * style: improve profiler UI * refactor: make internal services use non-class service names -* fix: make `ClassMetadataFactoryInterface` autowireable ## 2.0.0 diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index 43a7fff..6039ae2 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -21,7 +21,6 @@ use Rekalogika\File\Association\ClassSignatureResolver\ChainClassSignatureResolver; use Rekalogika\File\Association\ClassSignatureResolver\DefaultClassSignatureResolver; use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; -use Rekalogika\File\Association\Contracts\ClassMetadataFactoryInterface; use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Contracts\ObjectIdResolverInterface; use Rekalogika\File\Association\FilePropertyManager\DefaultFilePropertyManager; @@ -73,7 +72,7 @@ ->set('rekalogika.file.association.object_manager') ->class(DefaultObjectManager::class) ->args([ - '$classMetadataFactory' => service(ClassMetadataFactoryInterface::class), + '$classMetadataFactory' => service('rekalogika.file.association.class_metadata_factory'), '$objectIdResolver' => service(ObjectIdResolverInterface::class), '$filePropertyManager' => service('rekalogika.file.association.file_property_manager'), ]) @@ -161,7 +160,7 @@ ->set('rekalogika.file.association.class_based_file_location_resolver.default') ->class(DefaultClassBasedFileLocationResolver::class) ->args([ - service(ClassMetadataFactoryInterface::class), + service('rekalogika.file.association.class_metadata_factory'), ]) ->tag('rekalogika.file.association.class_based_file_location_resolver', [ 'priority' => -1000, @@ -235,7 +234,7 @@ // $services - ->set(ClassMetadataFactoryInterface::class) + ->set('rekalogika.file.association.class_metadata_factory') ->class(DefaultClassMetadataFactory::class) ->args([ service('rekalogika.file.association.property_lister'), @@ -252,7 +251,7 @@ $services ->set('rekalogika.file.association.class_metadata_factory.caching') ->class(CachingClassMetadataFactory::class) - ->decorate(ClassMetadataFactoryInterface::class) + ->decorate('rekalogika.file.association.class_metadata_factory') ->args([ service('.inner'), service('rekalogika.file.association.class_metadata_factory.cache'), diff --git a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php index d979f1f..c9e5336 100644 --- a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php +++ b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php @@ -21,6 +21,7 @@ use Rekalogika\File\Association\Contracts\PropertyListerInterface; use Rekalogika\File\Bundle\DefaultFilesystemFactory; use Rekalogika\File\Derivation\Filter\FileFilterInterface; +use Rekalogika\File\FileFactory; use Rekalogika\File\Image\ImageResizer; use Rekalogika\File\Server\FileInterfaceResourceServer; use Rekalogika\File\Tests\TestKernel; From abbf33da654e11fbb2d5f5491691cccee10e49b9 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 15:32:16 +0700 Subject: [PATCH 06/21] refactor: make user-facing `ClassSignatureResolverInterface` gets the result from metadata (#141) --- CHANGELOG.md | 2 ++ .../DefaultClassBasedFileLocationResolver.php | 13 ++++--- .../MetadataClassSignatureResolver.php | 35 +++++++++++++++++++ .../file-bundle/config/file-association.php | 23 ++++++++---- .../RekalogikaFileExtension.php | 1 - .../DefaultFileLocationResolverTest.php | 11 ++---- 6 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 packages/file-association/src/ClassSignatureResolver/MetadataClassSignatureResolver.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 264272e..432e936 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * fix: make `FileRepository` implement `ResetInterface` * style: improve profiler UI * refactor: make internal services use non-class service names +* refactor: make user-facing `ClassSignatureResolverInterface` gets the result + from metadata ## 2.0.0 diff --git a/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php b/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php index 4ef408f..77a4074 100644 --- a/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php +++ b/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php @@ -15,13 +15,13 @@ use Rekalogika\Contracts\File\FilePointerInterface; use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; -use Rekalogika\File\Association\Contracts\ClassMetadataFactoryInterface; +use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Model\FilePointer; final readonly class DefaultClassBasedFileLocationResolver implements ClassBasedFileLocationResolverInterface { public function __construct( - private ClassMetadataFactoryInterface $classMetadataFactory, + private ClassSignatureResolverInterface $classSignatureResolver, private string $filesystemIdentifier = 'default', private string $prefix = 'entity', private int $hashLevel = 4, @@ -36,9 +36,12 @@ public function getFileLocation( $splittedHash = str_split(sha1($id), 2); $hash = implode('/', \array_slice($splittedHash, 0, $this->hashLevel)); - $classSignature = $this->classMetadataFactory - ->getClassMetadata($class) - ->getSignature(); + $classSignature = $this->classSignatureResolver + ->getClassSignature($class) + ?? throw new \LogicException(\sprintf( + 'Class signature resolver not found for class "%s"', + $class, + )); $key = \sprintf( '%s/%s/%s/%s/%s', diff --git a/packages/file-association/src/ClassSignatureResolver/MetadataClassSignatureResolver.php b/packages/file-association/src/ClassSignatureResolver/MetadataClassSignatureResolver.php new file mode 100644 index 0000000..44f8c05 --- /dev/null +++ b/packages/file-association/src/ClassSignatureResolver/MetadataClassSignatureResolver.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Association\ClassSignatureResolver; + +use Rekalogika\File\Association\Contracts\ClassMetadataFactoryInterface; +use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; + +/** + * Gets the class signature already saved in the metadata + */ +final readonly class MetadataClassSignatureResolver implements ClassSignatureResolverInterface +{ + public function __construct( + private ClassMetadataFactoryInterface $classMetadataFactory, + ) {} + + #[\Override] + public function getClassSignature(string $class): string + { + return $this->classMetadataFactory + ->getClassMetadata($class) + ->getSignature(); + } +} diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index 6039ae2..2377dc7 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -12,6 +12,7 @@ */ use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Metadata\Metadata; use Rekalogika\Contracts\File\FileRepositoryInterface; use Rekalogika\File\Association\ClassBasedFileLocationResolver\ChainedClassBasedFileLocationResolver; use Rekalogika\File\Association\ClassBasedFileLocationResolver\DefaultClassBasedFileLocationResolver; @@ -20,6 +21,7 @@ use Rekalogika\File\Association\ClassSignatureResolver\AttributeClassSignatureResolver; use Rekalogika\File\Association\ClassSignatureResolver\ChainClassSignatureResolver; use Rekalogika\File\Association\ClassSignatureResolver\DefaultClassSignatureResolver; +use Rekalogika\File\Association\ClassSignatureResolver\MetadataClassSignatureResolver; use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Contracts\ObjectIdResolverInterface; @@ -160,7 +162,7 @@ ->set('rekalogika.file.association.class_based_file_location_resolver.default') ->class(DefaultClassBasedFileLocationResolver::class) ->args([ - service('rekalogika.file.association.class_metadata_factory'), + service(ClassSignatureResolverInterface::class), ]) ->tag('rekalogika.file.association.class_based_file_location_resolver', [ 'priority' => -1000, @@ -168,13 +170,20 @@ ; // - // class signature resolver + // class signature resolver, user-facing // - $services->alias( - ClassSignatureResolverInterface::class, - 'rekalogika.file.association.class_signature_resolver.chained', - ); + $services + ->set(ClassSignatureResolverInterface::class) + ->class(MetadataClassSignatureResolver::class) + ->args([ + service('rekalogika.file.association.class_metadata_factory'), + ]) + ; + + // + // class signature resolver, backend + // $services ->set('rekalogika.file.association.class_signature_resolver.chained') @@ -238,7 +247,7 @@ ->class(DefaultClassMetadataFactory::class) ->args([ service('rekalogika.file.association.property_lister'), - service(ClassSignatureResolverInterface::class), + service('rekalogika.file.association.class_signature_resolver.chained'), ]) ; diff --git a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php index c9e5336..d979f1f 100644 --- a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php +++ b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php @@ -21,7 +21,6 @@ use Rekalogika\File\Association\Contracts\PropertyListerInterface; use Rekalogika\File\Bundle\DefaultFilesystemFactory; use Rekalogika\File\Derivation\Filter\FileFilterInterface; -use Rekalogika\File\FileFactory; use Rekalogika\File\Image\ImageResizer; use Rekalogika\File\Server\FileInterfaceResourceServer; use Rekalogika\File\Tests\TestKernel; diff --git a/tests/src/Tests/FileAssociation/DefaultFileLocationResolverTest.php b/tests/src/Tests/FileAssociation/DefaultFileLocationResolverTest.php index e924b38..4dd80e5 100644 --- a/tests/src/Tests/FileAssociation/DefaultFileLocationResolverTest.php +++ b/tests/src/Tests/FileAssociation/DefaultFileLocationResolverTest.php @@ -15,10 +15,8 @@ use PHPUnit\Framework\TestCase; use Rekalogika\File\Association\ClassBasedFileLocationResolver\DefaultClassBasedFileLocationResolver; -use Rekalogika\File\Association\ClassMetadataFactory\DefaultClassMetadataFactory; use Rekalogika\File\Association\ClassSignatureResolver\DefaultClassSignatureResolver; use Rekalogika\File\Association\ObjectIdResolver\DefaultObjectIdResolver; -use Rekalogika\File\Association\PropertyLister\AttributesPropertyLister; use Rekalogika\File\Association\Util\ProxyUtil; use Rekalogika\File\Tests\Tests\Model\Entity; @@ -26,14 +24,11 @@ final class DefaultFileLocationResolverTest extends TestCase { public function testDefaultLocationResolver(): void { - $classMetadataFactory = new DefaultClassMetadataFactory( - propertyLister: new AttributesPropertyLister(), - classSignatureResolver: new DefaultClassSignatureResolver(), - ); - $objectIdResolver = new DefaultObjectIdResolver(); - $locationResolver = new DefaultClassBasedFileLocationResolver($classMetadataFactory); + $locationResolver = new DefaultClassBasedFileLocationResolver( + new DefaultClassSignatureResolver(), + ); $object = new Entity('entity_id'); From 764713ca4f8d1699a81c3fb5699aac355f47f8e4 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 5 May 2025 19:16:30 +0700 Subject: [PATCH 07/21] refactor: refactor directory hashing code to a separate class for reusability (#144) --- CHANGELOG.md | 1 + .../DefaultClassBasedFileLocationResolver.php | 7 ++-- .../src/Util/FileLocationUtil.php | 33 +++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 packages/file-association/src/Util/FileLocationUtil.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 432e936..ade8a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * refactor: make internal services use non-class service names * refactor: make user-facing `ClassSignatureResolverInterface` gets the result from metadata +* refactor: refactor directory hashing code to a separate class for reusability ## 2.0.0 diff --git a/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php b/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php index 77a4074..5430cd6 100644 --- a/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php +++ b/packages/file-association/src/ClassBasedFileLocationResolver/DefaultClassBasedFileLocationResolver.php @@ -17,6 +17,7 @@ use Rekalogika\File\Association\Contracts\ClassBasedFileLocationResolverInterface; use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Model\FilePointer; +use Rekalogika\File\Association\Util\FileLocationUtil; final readonly class DefaultClassBasedFileLocationResolver implements ClassBasedFileLocationResolverInterface { @@ -33,8 +34,7 @@ public function getFileLocation( string $id, string $propertyName, ): FilePointerInterface { - $splittedHash = str_split(sha1($id), 2); - $hash = implode('/', \array_slice($splittedHash, 0, $this->hashLevel)); + $hash = FileLocationUtil::createHashedDirectory($id, $this->hashLevel); $classSignature = $this->classSignatureResolver ->getClassSignature($class) @@ -52,9 +52,6 @@ public function getFileLocation( $id, ); - $key = preg_replace('/\/+/', '/', $key); - \assert(\is_string($key)); - return new FilePointer($this->filesystemIdentifier, $key); } } diff --git a/packages/file-association/src/Util/FileLocationUtil.php b/packages/file-association/src/Util/FileLocationUtil.php new file mode 100644 index 0000000..0250fb3 --- /dev/null +++ b/packages/file-association/src/Util/FileLocationUtil.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Association\Util; + +final readonly class FileLocationUtil +{ + private function __construct() {} + + public static function createHashedDirectory( + string $id, + int $hashLevel, + ): string { + return implode( + '/', + \array_slice( + str_split(sha1($id), 2), + 0, + $hashLevel, + ), + ); + } +} From 58f4f78773c260280d8c5a8b090f741615e3e0fd Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Tue, 6 May 2025 15:39:34 +0700 Subject: [PATCH 08/21] fix: disable `PropertyLister` autoconfiguration (#145) --- CHANGELOG.md | 1 + .../src/DependencyInjection/RekalogikaFileExtension.php | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ade8a52..2949275 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * refactor: make user-facing `ClassSignatureResolverInterface` gets the result from metadata * refactor: refactor directory hashing code to a separate class for reusability +* fix: disable `PropertyLister` autoconfiguration ## 2.0.0 diff --git a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php index d979f1f..4c677fb 100644 --- a/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php +++ b/packages/file-bundle/src/DependencyInjection/RekalogikaFileExtension.php @@ -18,7 +18,6 @@ use Rekalogika\File\Association\Contracts\ClassSignatureResolverInterface; use Rekalogika\File\Association\Contracts\ObjectIdResolverInterface; use Rekalogika\File\Association\Contracts\ObjectManagerInterface; -use Rekalogika\File\Association\Contracts\PropertyListerInterface; use Rekalogika\File\Bundle\DefaultFilesystemFactory; use Rekalogika\File\Derivation\Filter\FileFilterInterface; use Rekalogika\File\Image\ImageResizer; @@ -123,10 +122,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('rekalogika.file.derivation.filter'); } - $container - ->registerForAutoconfiguration(PropertyListerInterface::class) - ->addTag('rekalogika.file.association.property_lister'); - $container ->registerForAutoconfiguration(ClassBasedFileLocationResolverInterface::class) ->addTag('rekalogika.file.association.class_based_file_location_resolver'); From 7ab9876a73af916bcd9aca36923e19f2be010c5d Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Tue, 6 May 2025 20:18:08 +0700 Subject: [PATCH 09/21] fix: compatibility with reconstitutor 2.1 (#147) * fix: compatibility with reconstitutor 2.1 * fix * fix --- CHANGELOG.md | 1 + composer.json | 2 +- packages/file-association/composer.json | 2 +- .../src/Reconstitutor/AttributeReconstitutor.php | 3 +++ .../src/Reconstitutor/InterfaceReconstitutor.php | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2949275..d1e3b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ from metadata * refactor: refactor directory hashing code to a separate class for reusability * fix: disable `PropertyLister` autoconfiguration +* fix: compatibility with reconstitutor 2.1 ## 2.0.0 diff --git a/composer.json b/composer.json index 5ff8abb..86dae56 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "psr/http-message": "^1.0 || ^2.0", "psr/log": "^2 || ^3", "rekalogika/doctrine-collections-decorator": "^2.0", - "rekalogika/reconstitutor": "^2.0.2", + "rekalogika/reconstitutor": "^2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index f7f83e1..7dfe4ec 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -33,7 +33,7 @@ "rekalogika/file-association-contracts": "^2.0", "rekalogika/file-contracts": "^2.0", "rekalogika/file-null": "^2.0", - "rekalogika/reconstitutor": "^2.0.2", + "rekalogika/reconstitutor": "^2.1", "symfony/deprecation-contracts": "^3.1" }, "extra": { diff --git a/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php b/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php index 5c08945..755524e 100644 --- a/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php +++ b/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php @@ -52,4 +52,7 @@ public function onLoad(object $object): void #[\Override] public function onCreate(object $object): void {} + + #[\Override] + public function onClear(object $object): void {} } diff --git a/packages/file-association/src/Reconstitutor/InterfaceReconstitutor.php b/packages/file-association/src/Reconstitutor/InterfaceReconstitutor.php index d2cf327..4723f18 100644 --- a/packages/file-association/src/Reconstitutor/InterfaceReconstitutor.php +++ b/packages/file-association/src/Reconstitutor/InterfaceReconstitutor.php @@ -54,4 +54,7 @@ public function onLoad(object $object): void #[\Override] public function onCreate(object $object): void {} + + #[\Override] + public function onClear(object $object): void {} } From 2204abc7640b9a100fafd1354497b3de0e623047 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Tue, 6 May 2025 20:20:54 +0700 Subject: [PATCH 10/21] release: 2.1.0 (#148) --- composer.json | 40 +++++++++---------- .../file-association-contracts/composer.json | 2 +- .../file-association-entity/composer.json | 8 ++-- packages/file-association/composer.json | 8 ++-- packages/file-bundle/composer.json | 10 ++--- packages/file-contracts/composer.json | 2 +- packages/file-derivation/composer.json | 6 +-- packages/file-filepond/composer.json | 16 ++++---- packages/file-image/composer.json | 6 +-- .../file-metadata-contracts/composer.json | 2 +- packages/file-metadata/composer.json | 6 +-- packages/file-null/composer.json | 4 +- .../file-oneup-uploader-bridge/composer.json | 6 +-- packages/file-server/composer.json | 6 +-- packages/file-symfony-bridge/composer.json | 10 ++--- packages/file-zip/composer.json | 6 +-- packages/file/composer.json | 6 +-- 17 files changed, 72 insertions(+), 72 deletions(-) diff --git a/composer.json b/composer.json index 86dae56..2d21481 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,15 @@ { "name": "rekalogika/file-src", "description": "Monorepo for rekalogika/file and related packages", + "homepage": "https://rekalogika.dev/file", "license": "MIT", - "type": "project", "authors": [ { "name": "Priyadi Iman Nurcahyo", "email": "priyadi@rekalogika.com" } ], - "homepage": "https://rekalogika.dev/file", + "type": "project", "require": { "cardinalby/content-disposition": "^1.1", "doctrine/collections": "^2.0", @@ -89,24 +89,6 @@ "twig/extra-bundle": "^2.12|^3.0", "vimeo/psalm": "^6.0" }, - "replace": { - "rekalogika/file": "2.0.0", - "rekalogika/file-association": "2.0.0", - "rekalogika/file-association-contracts": "2.0.0", - "rekalogika/file-association-entity": "2.0.0", - "rekalogika/file-bundle": "2.0.0", - "rekalogika/file-contracts": "2.0.0", - "rekalogika/file-derivation": "2.0.0", - "rekalogika/file-filepond": "2.0.0", - "rekalogika/file-image": "2.0.0", - "rekalogika/file-metadata": "2.0.0", - "rekalogika/file-metadata-contracts": "2.0.0", - "rekalogika/file-null": "2.0.0", - "rekalogika/file-oneup-uploader-bridge": "2.0.0", - "rekalogika/file-server": "2.0.0", - "rekalogika/file-symfony-bridge": "2.0.0", - "rekalogika/file-zip": "2.0.0" - }, "autoload": { "psr-4": { "Rekalogika\\Contracts\\File\\": "packages/file-contracts/src/", @@ -138,5 +120,23 @@ "php-http/discovery": true, "symfony/runtime": true } + }, + "replace": { + "rekalogika/file": "2.1.0", + "rekalogika/file-association": "2.1.0", + "rekalogika/file-association-contracts": "2.1.0", + "rekalogika/file-association-entity": "2.1.0", + "rekalogika/file-bundle": "2.1.0", + "rekalogika/file-contracts": "2.1.0", + "rekalogika/file-derivation": "2.1.0", + "rekalogika/file-filepond": "2.1.0", + "rekalogika/file-image": "2.1.0", + "rekalogika/file-metadata": "2.1.0", + "rekalogika/file-metadata-contracts": "2.1.0", + "rekalogika/file-null": "2.1.0", + "rekalogika/file-oneup-uploader-bridge": "2.1.0", + "rekalogika/file-server": "2.1.0", + "rekalogika/file-symfony-bridge": "2.1.0", + "rekalogika/file-zip": "2.1.0" } } diff --git a/packages/file-association-contracts/composer.json b/packages/file-association-contracts/composer.json index c543ffb..2fe16c7 100644 --- a/packages/file-association-contracts/composer.json +++ b/packages/file-association-contracts/composer.json @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-association-entity/composer.json b/packages/file-association-entity/composer.json index c1b5cf0..bd4c079 100644 --- a/packages/file-association-entity/composer.json +++ b/packages/file-association-entity/composer.json @@ -29,15 +29,15 @@ "php": "^8.2", "doctrine/collections": "^2.0", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-metadata": "^2.0", - "rekalogika/file-null": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-metadata": "^2.1", + "rekalogika/file-null": "^2.1", "rekalogika/doctrine-collections-decorator": "^2.0", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index 7dfe4ec..311bec1 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -30,15 +30,15 @@ "psr/cache": "^2 || ^3", "psr/log": "^2 || ^3", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-association-contracts": "^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-null": "^2.0", + "rekalogika/file-association-contracts": "^2.1", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-null": "^2.1", "rekalogika/reconstitutor": "^2.1", "symfony/deprecation-contracts": "^3.1" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-bundle/composer.json b/packages/file-bundle/composer.json index 61ffc53..8134681 100644 --- a/packages/file-bundle/composer.json +++ b/packages/file-bundle/composer.json @@ -28,10 +28,10 @@ "php": "^8.2", "league/flysystem": "^3.16", "league/flysystem-local": "^3.16", - "rekalogika/file": "^2.0", - "rekalogika/file-association-contracts": "^2.0", - "rekalogika/file-association-entity": "^2.0", - "rekalogika/file-contracts": "^2.0", + "rekalogika/file": "^2.1", + "rekalogika/file-association-contracts": "^2.1", + "rekalogika/file-association-entity": "^2.1", + "rekalogika/file-contracts": "^2.1", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", @@ -53,7 +53,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-contracts/composer.json b/packages/file-contracts/composer.json index 888d5db..2faa4c9 100644 --- a/packages/file-contracts/composer.json +++ b/packages/file-contracts/composer.json @@ -33,7 +33,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-derivation/composer.json b/packages/file-derivation/composer.json index 75a011b..d3825f9 100644 --- a/packages/file-derivation/composer.json +++ b/packages/file-derivation/composer.json @@ -22,12 +22,12 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file": "^2.0" + "rekalogika/file-contracts": "^2.1", + "rekalogika/file": "^2.1" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-filepond/composer.json b/packages/file-filepond/composer.json index abd8d3f..04582f0 100644 --- a/packages/file-filepond/composer.json +++ b/packages/file-filepond/composer.json @@ -26,13 +26,13 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.0", - "rekalogika/file-association-entity": "^2.0", - "rekalogika/file-bundle": "^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-image": "^2.0", - "rekalogika/file-server": "^2.0", - "rekalogika/file-symfony-bridge": "^2.0", + "rekalogika/file": "^2.1", + "rekalogika/file-association-entity": "^2.1", + "rekalogika/file-bundle": "^2.1", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-image": "^2.1", + "rekalogika/file-server": "^2.1", + "rekalogika/file-symfony-bridge": "^2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/dependency-injection": "^6.2 || ^7.0", "symfony/form": "^6.2 || ^7.0", @@ -43,7 +43,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-image/composer.json b/packages/file-image/composer.json index 2ac624d..d544c96 100644 --- a/packages/file-image/composer.json +++ b/packages/file-image/composer.json @@ -29,13 +29,13 @@ "php": "^8.2", "intervention/image": "^3.3", "psr/log": "^2 || ^3", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-derivation": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-derivation": "^2.1", "twig/twig": "^3.9" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-metadata-contracts/composer.json b/packages/file-metadata-contracts/composer.json index 972c603..8bd180c 100644 --- a/packages/file-metadata-contracts/composer.json +++ b/packages/file-metadata-contracts/composer.json @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-metadata/composer.json b/packages/file-metadata/composer.json index 444e51e..2258c26 100644 --- a/packages/file-metadata/composer.json +++ b/packages/file-metadata/composer.json @@ -26,13 +26,13 @@ "php": "^8.2", "cardinalby/content-disposition": "^1.1", "fileeye/mimemap": "^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-metadata-contracts": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-metadata-contracts": "^2.1", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-null/composer.json b/packages/file-null/composer.json index 17bfdb9..02a1656 100644 --- a/packages/file-null/composer.json +++ b/packages/file-null/composer.json @@ -26,12 +26,12 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.0", + "rekalogika/file-contracts": "^2.1", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-oneup-uploader-bridge/composer.json b/packages/file-oneup-uploader-bridge/composer.json index d9e1cfc..e128c6f 100644 --- a/packages/file-oneup-uploader-bridge/composer.json +++ b/packages/file-oneup-uploader-bridge/composer.json @@ -25,12 +25,12 @@ "require": { "php": "^8.2", "oneup/uploader-bundle": "^5.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file": "^2.0" + "rekalogika/file-contracts": "^2.1", + "rekalogika/file": "^2.1" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-server/composer.json b/packages/file-server/composer.json index 80b7e31..c7c7582 100644 --- a/packages/file-server/composer.json +++ b/packages/file-server/composer.json @@ -24,14 +24,14 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-symfony-bridge": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-symfony-bridge": "^2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/http-foundation": "^6.2 || ^7.0" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-symfony-bridge/composer.json b/packages/file-symfony-bridge/composer.json index a73e11c..3d3d6d7 100644 --- a/packages/file-symfony-bridge/composer.json +++ b/packages/file-symfony-bridge/composer.json @@ -27,17 +27,17 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-metadata-contracts": "^2.0", - "rekalogika/file-metadata": "^2.0", + "rekalogika/file": "^2.1", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-metadata-contracts": "^2.1", + "rekalogika/file-metadata": "^2.1", "symfony/form": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/validator": "^6.3 || ^7.1" }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file-zip/composer.json b/packages/file-zip/composer.json index 2d6f933..a37817a 100644 --- a/packages/file-zip/composer.json +++ b/packages/file-zip/composer.json @@ -28,8 +28,8 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-metadata": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-metadata": "^2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "maennchen/zipstream-php": "^3.1", "symfony/http-foundation": "^6.2 || ^7.0", @@ -37,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } diff --git a/packages/file/composer.json b/packages/file/composer.json index 2379bda..adfa41d 100644 --- a/packages/file/composer.json +++ b/packages/file/composer.json @@ -33,8 +33,8 @@ "psr/http-factory-implementation": "^1.0", "league/flysystem": "^3.16", "league/mime-type-detection": "^1.0.0", - "rekalogika/file-contracts": "^2.0", - "rekalogika/file-metadata": "^2.0", + "rekalogika/file-contracts": "^2.1", + "rekalogika/file-metadata": "^2.1", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" }, @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.2-dev" } } } From 714f053e6a52e27e00eff4f19f17838a48acb03c Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Tue, 6 May 2025 20:51:25 +0700 Subject: [PATCH 11/21] fix(AtributesPropertyLister): throw exception if there are two properties with the same name in the same class hierarchy (#146) * fix(AtributesPropertyLister): throw exception if there are two properties with the same name in the same class hierarchy * fix * fix * fix --- CHANGELOG.md | 9 ++++- .../DuplicatePropertyNameException.php | 40 +++++++++++++++++++ .../InvalidClassSignatureException.php | 2 +- .../src/Exception/LogicException.php | 16 ++++++++ .../AttributesPropertyLister.php | 22 +++++++++- ...FileAssociationInterfacePropertyLister.php | 23 +++++++++-- .../FileAssociation/PropertyListerTest.php | 14 +++++-- 7 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 packages/file-association/src/Exception/DuplicatePropertyNameException.php create mode 100644 packages/file-association/src/Exception/LogicException.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d1e3b1f..64b774e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # CHANGELOG -## 2.0.1 +## 2.2.0 + +* fix: throw exception if there are two properties with the same name in the + same class hierarchy + +## 2.1.0 * fix: make `FileRepository` implement `ResetInterface` * style: improve profiler UI @@ -10,6 +15,8 @@ * refactor: refactor directory hashing code to a separate class for reusability * fix: disable `PropertyLister` autoconfiguration * fix: compatibility with reconstitutor 2.1 +* fix(AtributesPropertyLister): throw exception if there are two properties with + the same name in the same class hierarchy ## 2.0.0 diff --git a/packages/file-association/src/Exception/DuplicatePropertyNameException.php b/packages/file-association/src/Exception/DuplicatePropertyNameException.php new file mode 100644 index 0000000..774cfc1 --- /dev/null +++ b/packages/file-association/src/Exception/DuplicatePropertyNameException.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Association\Exception; + +final class DuplicatePropertyNameException extends LogicException +{ + /** + * @param string $propertyName + * @param class-string $class1 + * @param class-string $class2 + * @param string $leafClass + */ + public function __construct( + string $propertyName, + string $class1, + string $class2, + string $leafClass, + ) { + parent::__construct( + \sprintf( + 'Invalid class signature for property "%s" in class "%s" and "%s". Leaf class: "%s"', + $propertyName, + $class1, + $class2, + $leafClass, + ), + ); + } +} diff --git a/packages/file-association/src/Exception/InvalidClassSignatureException.php b/packages/file-association/src/Exception/InvalidClassSignatureException.php index cfc93fe..03e7adb 100644 --- a/packages/file-association/src/Exception/InvalidClassSignatureException.php +++ b/packages/file-association/src/Exception/InvalidClassSignatureException.php @@ -13,4 +13,4 @@ namespace Rekalogika\File\Association\Exception; -final class InvalidClassSignatureException extends \LogicException implements FileAssociationException {} +final class InvalidClassSignatureException extends LogicException {} diff --git a/packages/file-association/src/Exception/LogicException.php b/packages/file-association/src/Exception/LogicException.php new file mode 100644 index 0000000..93b50a0 --- /dev/null +++ b/packages/file-association/src/Exception/LogicException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Association\Exception; + +class LogicException extends \LogicException implements FileAssociationException {} diff --git a/packages/file-association/src/PropertyLister/AttributesPropertyLister.php b/packages/file-association/src/PropertyLister/AttributesPropertyLister.php index c2eef39..c151084 100644 --- a/packages/file-association/src/PropertyLister/AttributesPropertyLister.php +++ b/packages/file-association/src/PropertyLister/AttributesPropertyLister.php @@ -15,6 +15,7 @@ use Rekalogika\File\Association\Attribute\AsFileAssociation; use Rekalogika\File\Association\Contracts\PropertyListerInterface; +use Rekalogika\File\Association\Exception\DuplicatePropertyNameException; use Rekalogika\File\Association\Model\Property; use Rekalogika\File\Association\Util\ClassUtil; @@ -32,11 +33,28 @@ class: $class, attribute: AsFileAssociation::class, ); + $result = []; + foreach ($reflectionProperties as $reflectionProperty) { - yield new Property( + $name = $reflectionProperty->getName(); + + if (isset($result[$name])) { + $previous = $result[$name]; + + throw new DuplicatePropertyNameException( + propertyName: $name, + class1: $previous->getClass(), + class2: $reflectionProperty->getDeclaringClass()->getName(), + leafClass: $class, + ); + } + + $result[$name] = new Property( class: $reflectionProperty->getDeclaringClass()->getName(), - name: $reflectionProperty->getName(), + name: $name, ); } + + return array_values($result); } } diff --git a/packages/file-association/src/PropertyLister/FileAssociationInterfacePropertyLister.php b/packages/file-association/src/PropertyLister/FileAssociationInterfacePropertyLister.php index 6481e06..34c9edf 100644 --- a/packages/file-association/src/PropertyLister/FileAssociationInterfacePropertyLister.php +++ b/packages/file-association/src/PropertyLister/FileAssociationInterfacePropertyLister.php @@ -15,6 +15,7 @@ use Rekalogika\Contracts\File\Association\FileAssociationInterface; use Rekalogika\File\Association\Contracts\PropertyListerInterface; +use Rekalogika\File\Association\Exception\DuplicatePropertyNameException; use Rekalogika\File\Association\Model\Property; use Rekalogika\File\Association\Util\ClassUtil; @@ -33,16 +34,32 @@ public function getFileProperties(string $class): iterable $propertyNames = $class::getFileAssociationPropertyList(); $properties = ClassUtil::getReflectionProperties($class); + $result = []; foreach ($properties as $reflectionProperty) { - if (!\in_array($reflectionProperty->getName(), $propertyNames, true)) { + $name = $reflectionProperty->getName(); + + if (!\in_array($name, $propertyNames, true)) { continue; } - yield new Property( + if (isset($result[$name])) { + $previous = $result[$name]; + + throw new DuplicatePropertyNameException( + propertyName: $name, + class1: $previous->getClass(), + class2: $reflectionProperty->getDeclaringClass()->getName(), + leafClass: $class, + ); + } + + $result[$name] = new Property( class: $reflectionProperty->getDeclaringClass()->getName(), - name: $reflectionProperty->getName(), + name: $name, ); } + + return array_values($result); } } diff --git a/tests/src/Tests/FileAssociation/PropertyListerTest.php b/tests/src/Tests/FileAssociation/PropertyListerTest.php index 16ff42c..63efbe7 100644 --- a/tests/src/Tests/FileAssociation/PropertyListerTest.php +++ b/tests/src/Tests/FileAssociation/PropertyListerTest.php @@ -34,21 +34,23 @@ public function testPropertyLister( PropertyListerInterface $lister, string $class, array $expectedProperties, + bool $invalid, ): void { + if ($invalid) { + $this->expectException(\LogicException::class); + } + $properties = $lister->getFileProperties($class); $properties = $properties instanceof \Traversable ? iterator_to_array($properties) : $properties; - // dump($expectedProperties); - // dump($properties); - $this->assertEqualsCanonicalizing($expectedProperties, $properties); } /** - * @return iterable}> + * @return iterable,bool}> */ public static function propertyListerProvider(): iterable { @@ -65,6 +67,7 @@ class: EntityWithAttribute::class, name: 'protectedFile', ), ], + false, ]; yield [ @@ -88,6 +91,7 @@ class: SubclassOfEntityWithAttribute::class, name: 'protectedFile', ), ], + true, ]; yield [ @@ -103,6 +107,7 @@ class: EntityImplementingFileAssociation::class, name: 'protectedFile', ), ], + false, ]; yield [ @@ -126,6 +131,7 @@ class: SubclassOfEntityImplementingFileAssociation::class, name: 'protectedFile', ), ], + true, ]; } } From 3b2cfbf116a23f77c61b3d80c7537c3158252c2e Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Tue, 6 May 2025 21:31:36 +0700 Subject: [PATCH 12/21] feat: record initial value for avoid some file requests (#149) --- CHANGELOG.md | 1 + .../DefaultFilePropertyManager.php | 59 ++++++++++++++-- .../InitialPropertyRecorder.php | 67 +++++++++++++++++++ .../file-bundle/config/file-association.php | 3 + tests/src/Tests/Architecture/Architecture.php | 1 + 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b774e..6537cbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * fix: throw exception if there are two properties with the same name in the same class hierarchy +* feat: record initial value for avoid some file requests ## 2.1.0 diff --git a/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php b/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php index b2cae46..06b705c 100644 --- a/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php +++ b/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php @@ -26,17 +26,29 @@ use Rekalogika\File\Association\Model\PropertyOperationAction; use Rekalogika\File\Association\Model\PropertyOperationResult; use Rekalogika\File\Association\PropertyReaderWriter\DefaultPropertyReaderWriter; +use Symfony\Contracts\Service\ResetInterface; -final readonly class DefaultFilePropertyManager implements FilePropertyManagerInterface +final readonly class DefaultFilePropertyManager implements + FilePropertyManagerInterface, + ResetInterface { private PropertyReaderInterface $reader; private PropertyWriterInterface $writer; + private InitialPropertyRecorder $initialPropertyRecorder; + public function __construct( private FileRepositoryInterface $fileRepository, private ClassBasedFileLocationResolverInterface $fileLocationResolver, ) { $this->reader = $this->writer = new DefaultPropertyReaderWriter(); + $this->initialPropertyRecorder = new InitialPropertyRecorder(); + } + + #[\Override] + public function reset(): void + { + $this->initialPropertyRecorder->reset(); } /** @@ -51,9 +63,6 @@ public function flushProperty( $propertyName = $propertyMetadata->getName(); $class = $propertyMetadata->getClass(); - /** @psalm-suppress MixedAssignment */ - $currentFile = $this->reader->read($object, $propertyMetadata); - // determine the file location $filePointer = $this->fileLocationResolver->getFileLocation( class: $class, @@ -61,12 +70,41 @@ class: $class, propertyName: $propertyName, ); + /** @psalm-suppress MixedAssignment */ + $initialProperty = $this->initialPropertyRecorder->getInitialProperty( + object: $object, + propertyName: $propertyName, + ); + + /** @psalm-suppress MixedAssignment */ + $currentFile = $this->reader->read($object, $propertyMetadata); + + if ($initialProperty === $currentFile) { + return new PropertyOperationResult( + type: ObjectOperationType::Flush, + action: PropertyOperationAction::Nothing, + class: $propertyMetadata->getClass(), + scopeClass: $propertyMetadata->getScopeClass(), + property: $propertyName, + objectId: $id, + filePointer: $filePointer, + ); + } + // if the file is null, we need to remove the file from storage, then // we are done if (null === $currentFile) { $this->fileRepository->delete($filePointer); + // record the initial property + + $this->initialPropertyRecorder->recordInitialProperty( + object: $object, + propertyName: $propertyName, + value: null, + ); + return new PropertyOperationResult( type: ObjectOperationType::Flush, action: PropertyOperationAction::Removed, @@ -102,6 +140,13 @@ class: $propertyMetadata->getClass(), // inject the file to the object $this->writer->write($object, $propertyMetadata, $file); + // record the initial property + $this->initialPropertyRecorder->recordInitialProperty( + object: $object, + propertyName: $propertyName, + value: $file, + ); + return new PropertyOperationResult( type: ObjectOperationType::Flush, action: PropertyOperationAction::Saved, @@ -225,6 +270,12 @@ class: $propertyMetadata->getClass(), $this->writer->write($object, $propertyMetadata, $file); + $this->initialPropertyRecorder->recordInitialProperty( + object: $object, + propertyName: $propertyName, + value: $file, + ); + return $result; } } diff --git a/packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php b/packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php new file mode 100644 index 0000000..c08d9d6 --- /dev/null +++ b/packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Association\FilePropertyManager; + +use Symfony\Contracts\Service\ResetInterface; + +final class InitialPropertyRecorder implements ResetInterface +{ + /** + * @var \WeakMap> + */ + private \WeakMap $properties; + + public function __construct() + { + $this->init(); + } + + #[\Override] + public function reset(): void + { + $this->init(); + } + + private function init(): void + { + /** @var \WeakMap> */ + $properties = new \WeakMap(); + $this->properties = $properties; + } + + public function recordInitialProperty( + object $object, + string $propertyName, + mixed $value, + ): void { + if (!isset($this->properties[$object])) { + $this->properties[$object] = []; + } + + /** @psalm-suppress MixedArgument */ + $this->properties[$object][$propertyName] = $value; + } + + public function getInitialProperty( + object $object, + string $propertyName, + ): mixed { + if (!isset($this->properties[$object])) { + return null; + } + + /** @psalm-suppress PossiblyNullArrayAccess */ + return $this->properties[$object][$propertyName] ?? null; + } +} diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index 2377dc7..74e7b06 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -91,6 +91,9 @@ '$fileRepository' => service(FileRepositoryInterface::class), '$fileLocationResolver' => service(ClassBasedFileLocationResolverInterface::class), ]) + ->tag('kernel.reset', [ + 'method' => 'reset', + ]) ; $services diff --git a/tests/src/Tests/Architecture/Architecture.php b/tests/src/Tests/Architecture/Architecture.php index 79a3a10..715ffe8 100644 --- a/tests/src/Tests/Architecture/Architecture.php +++ b/tests/src/Tests/Architecture/Architecture.php @@ -194,6 +194,7 @@ public function testFileAssociation(): Rule Selector::inNamespace('Psr\Log'), Selector::inNamespace('Psr\Cache'), Selector::inNamespace('Rekalogika\Reconstitutor\Contract'), + Selector::inNamespace('Symfony\Contracts\Service'), // dependencies on optional packages Selector::classname(ManagerRegistry::class), From cd75af81853d7f6c5f89de233f5f627ae2090a14 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 00:17:40 +0700 Subject: [PATCH 13/21] perf: avoid removing file if we know the file does not exist (#150) * perf: avoid removing file if we know the file does not exist * fix * phpstan --- CHANGELOG.md | 3 +- composer.json | 2 +- packages/file-association/composer.json | 2 +- .../DefaultFilePropertyManager.php | 51 +++++++-- .../PropertyRecorder.php} | 30 +++++- phpstan.neon.dist | 6 ++ .../FileAssociation/DoctrineTestCase.php | 61 +++++++++++ .../src/Tests/FileAssociation/EntityTest.php | 100 ++++++++++++++++-- 8 files changed, 229 insertions(+), 26 deletions(-) rename packages/file-association/src/{FilePropertyManager/InitialPropertyRecorder.php => PropertyRecorder/PropertyRecorder.php} (64%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6537cbc..6264022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ * fix: throw exception if there are two properties with the same name in the same class hierarchy -* feat: record initial value for avoid some file requests +* perf: record initial value for avoid some file requests +* perf: avoid removing file if we know the file does not exist ## 2.1.0 diff --git a/composer.json b/composer.json index 2d21481..cd2a976 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "psr/http-message": "^1.0 || ^2.0", "psr/log": "^2 || ^3", "rekalogika/doctrine-collections-decorator": "^2.0", - "rekalogika/reconstitutor": "^2.1", + "rekalogika/reconstitutor": "^2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index 311bec1..0fc8b21 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -33,7 +33,7 @@ "rekalogika/file-association-contracts": "^2.1", "rekalogika/file-contracts": "^2.1", "rekalogika/file-null": "^2.1", - "rekalogika/reconstitutor": "^2.1", + "rekalogika/reconstitutor": "^2.2", "symfony/deprecation-contracts": "^3.1" }, "extra": { diff --git a/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php b/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php index 06b705c..b3aa171 100644 --- a/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php +++ b/packages/file-association/src/FilePropertyManager/DefaultFilePropertyManager.php @@ -26,6 +26,7 @@ use Rekalogika\File\Association\Model\PropertyOperationAction; use Rekalogika\File\Association\Model\PropertyOperationResult; use Rekalogika\File\Association\PropertyReaderWriter\DefaultPropertyReaderWriter; +use Rekalogika\File\Association\PropertyRecorder\PropertyRecorder; use Symfony\Contracts\Service\ResetInterface; final readonly class DefaultFilePropertyManager implements @@ -35,20 +36,20 @@ private PropertyReaderInterface $reader; private PropertyWriterInterface $writer; - private InitialPropertyRecorder $initialPropertyRecorder; + private PropertyRecorder $propertyRecorder; public function __construct( private FileRepositoryInterface $fileRepository, private ClassBasedFileLocationResolverInterface $fileLocationResolver, ) { $this->reader = $this->writer = new DefaultPropertyReaderWriter(); - $this->initialPropertyRecorder = new InitialPropertyRecorder(); + $this->propertyRecorder = new PropertyRecorder(); } #[\Override] public function reset(): void { - $this->initialPropertyRecorder->reset(); + $this->propertyRecorder->reset(); } /** @@ -71,7 +72,7 @@ class: $class, ); /** @psalm-suppress MixedAssignment */ - $initialProperty = $this->initialPropertyRecorder->getInitialProperty( + $initialProperty = $this->propertyRecorder->getInitialProperty( object: $object, propertyName: $propertyName, ); @@ -79,6 +80,8 @@ class: $class, /** @psalm-suppress MixedAssignment */ $currentFile = $this->reader->read($object, $propertyMetadata); + // if property is unchanged, we don't need to do anything + if ($initialProperty === $currentFile) { return new PropertyOperationResult( type: ObjectOperationType::Flush, @@ -99,7 +102,7 @@ class: $propertyMetadata->getClass(), // record the initial property - $this->initialPropertyRecorder->recordInitialProperty( + $this->propertyRecorder->saveInitialProperty( object: $object, propertyName: $propertyName, value: null, @@ -117,7 +120,8 @@ class: $propertyMetadata->getClass(), } // if the file location of the current file is the same as the - // file location of the property, we don't need to do anything + // file location of the property, we don't need to do anything. + // possibly not necessary. if ($currentFile->isEqualTo($filePointer)) { return new PropertyOperationResult( @@ -137,11 +141,11 @@ class: $propertyMetadata->getClass(), // get reference of the file from storage $file = $this->fileRepository->getReference($filePointer); - // inject the file to the object + // inject the reference to the object $this->writer->write($object, $propertyMetadata, $file); // record the initial property - $this->initialPropertyRecorder->recordInitialProperty( + $this->propertyRecorder->saveInitialProperty( object: $object, propertyName: $propertyName, value: $file, @@ -159,7 +163,7 @@ class: $propertyMetadata->getClass(), } /** - * Process a file removal on an attribute + * Process a file removal on a property */ #[\Override] public function removeProperty( @@ -176,6 +180,31 @@ class: $class, propertyName: $propertyName, ); + /** @psalm-suppress MixedAssignment */ + $initialProperty = $this->propertyRecorder->getInitialProperty( + object: $object, + propertyName: $propertyName, + ); + + // remove the initial property + $this->propertyRecorder->removeInitialProperty( + object: $object, + propertyName: $propertyName, + ); + + // if the initial property is null, we don't need to do anything + if ($initialProperty === null) { + return new PropertyOperationResult( + type: ObjectOperationType::Remove, + action: PropertyOperationAction::Nothing, + class: $propertyMetadata->getClass(), + scopeClass: $propertyMetadata->getScopeClass(), + property: $propertyName, + objectId: $id, + filePointer: $filePointer, + ); + } + $this->fileRepository->delete($filePointer); return new PropertyOperationResult( @@ -190,7 +219,7 @@ class: $propertyMetadata->getClass(), } /** - * Process an attribute on an object loading + * Process an property on an object loading */ #[\Override] public function loadProperty( @@ -270,7 +299,7 @@ class: $propertyMetadata->getClass(), $this->writer->write($object, $propertyMetadata, $file); - $this->initialPropertyRecorder->recordInitialProperty( + $this->propertyRecorder->saveInitialProperty( object: $object, propertyName: $propertyName, value: $file, diff --git a/packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php b/packages/file-association/src/PropertyRecorder/PropertyRecorder.php similarity index 64% rename from packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php rename to packages/file-association/src/PropertyRecorder/PropertyRecorder.php index c08d9d6..0395398 100644 --- a/packages/file-association/src/FilePropertyManager/InitialPropertyRecorder.php +++ b/packages/file-association/src/PropertyRecorder/PropertyRecorder.php @@ -11,11 +11,11 @@ * that was distributed with this source code. */ -namespace Rekalogika\File\Association\FilePropertyManager; +namespace Rekalogika\File\Association\PropertyRecorder; use Symfony\Contracts\Service\ResetInterface; -final class InitialPropertyRecorder implements ResetInterface +final class PropertyRecorder implements ResetInterface { /** * @var \WeakMap> @@ -40,7 +40,7 @@ private function init(): void $this->properties = $properties; } - public function recordInitialProperty( + public function saveInitialProperty( object $object, string $propertyName, mixed $value, @@ -64,4 +64,28 @@ public function getInitialProperty( /** @psalm-suppress PossiblyNullArrayAccess */ return $this->properties[$object][$propertyName] ?? null; } + + public function hasInitialProperty( + object $object, + string $propertyName, + ): bool { + if (!isset($this->properties[$object])) { + return false; + } + + /** @psalm-suppress PossiblyNullArrayAccess */ + return isset($this->properties[$object][$propertyName]); + } + + public function removeInitialProperty( + object $object, + string $propertyName, + ): void { + if (!isset($this->properties[$object])) { + return; + } + + /** @psalm-suppress PossiblyNullArrayAccess */ + unset($this->properties[$object][$propertyName]); + } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index ca9ee64..30fdaeb 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,6 +18,12 @@ parameters: - identifier: return.unusedType path: packages/file-symfony-bridge/src/HttpFoundation/ToHttpFoundationFileAdapter.php + - + message: '#Call to an undefined method ReflectionClass<.*>::isUninitializedLazyObject#' + reportUnmatched: false + - + message: '#Call to an undefined method ReflectionClass<.*>::initializeLazyObject#' + reportUnmatched: false includes: - vendor/phpstan/phpstan-phpunit/extension.neon diff --git a/tests/src/Tests/FileAssociation/DoctrineTestCase.php b/tests/src/Tests/FileAssociation/DoctrineTestCase.php index 5a55aa7..0cc0692 100644 --- a/tests/src/Tests/FileAssociation/DoctrineTestCase.php +++ b/tests/src/Tests/FileAssociation/DoctrineTestCase.php @@ -15,10 +15,15 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; +use Doctrine\Persistence\Proxy; +use Rekalogika\Contracts\File\FileRepositoryInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; abstract class DoctrineTestCase extends KernelTestCase { + protected EntityManagerInterface $entityManager; + protected FileRepositoryInterface $fileRepository; + #[\Override] protected function setUp(): void { @@ -28,10 +33,66 @@ protected function setUp(): void $entityManager = static::getContainer()->get('doctrine.orm.entity_manager'); $this->assertInstanceOf(EntityManagerInterface::class, $entityManager); + $this->entityManager = $entityManager; // create schema $schemaTool = new SchemaTool($entityManager); $schemaTool->createSchema($entityManager->getMetadataFactory()->getAllMetadata()); + + // save file repository to class property + + $fileRepository = static::getContainer()->get(FileRepositoryInterface::class); + // @phpstan-ignore method.alreadyNarrowedType + $this->assertInstanceOf(FileRepositoryInterface::class, $fileRepository); + $this->fileRepository = $fileRepository; + } + + + // + // assertions + // + + protected function assertIsProxy(mixed $object): void + { + $this->assertIsObject($object, 'Expected an object'); + + if (\PHP_VERSION_ID >= 80400) { + $reflection = new \ReflectionClass($object); + /** + * @psalm-suppress UndefinedMethod + * @psalm-suppress MixedAssignment + */ + $isProxy = $reflection->isUninitializedLazyObject($object); + + if ($isProxy) { + return; + } + } + + $this->assertInstanceOf(Proxy::class, $object, 'Object is not a proxy'); + $this->assertFalse($object->__isInitialized(), 'Object is not an uninitialized proxy'); + } + + protected function assertNotProxy(mixed $object): void + { + $this->assertIsObject($object, 'Expected an object'); + + if ($object instanceof Proxy) { + $this->assertTrue($object->__isInitialized(), 'Object is a proxy, but should not be'); + + return; + } + + if (\PHP_VERSION_ID >= 80400) { + $reflection = new \ReflectionClass($object); + + /** + * @psalm-suppress UndefinedMethod + */ + if ($reflection->isUninitializedLazyObject($object)) { + static::fail('Object is a proxy, but should not be'); + } + } } } diff --git a/tests/src/Tests/FileAssociation/EntityTest.php b/tests/src/Tests/FileAssociation/EntityTest.php index 2953e37..1c20a69 100644 --- a/tests/src/Tests/FileAssociation/EntityTest.php +++ b/tests/src/Tests/FileAssociation/EntityTest.php @@ -13,28 +13,110 @@ namespace Rekalogika\File\Tests\Tests\FileAssociation; -use Doctrine\ORM\EntityManagerInterface; +use Rekalogika\Contracts\File\Exception\File\FileNotFoundException; use Rekalogika\File\File; use Rekalogika\File\Tests\App\Entity\User; final class EntityTest extends DoctrineTestCase { - public function testProxy(): void + private function createUserWithImage(): User { - $entityManager = static::getContainer()->get('doctrine.orm.entity_manager'); - $this->assertInstanceOf(EntityManagerInterface::class, $entityManager); - $image = new File(__DIR__ . '/../Resources/smiley.png'); $user = new User('foo'); $user->setImage($image); - $entityManager->persist($user); - $entityManager->flush(); + return $user; + } + + public function testCreate(): void + { + $user = $this->createUserWithImage(); + $image = $user->getImage(); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $this->assertInstanceOf(File::class, $user->getImage()); + $this->assertNotSame($image, $user->getImage()); + } + + public function testCreateLoad(): void + { + $user = $this->createUserWithImage(); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + $image = $user->getImage(); + + $this->entityManager->clear(); + + $user = $this->entityManager->find(User::class, $user->getId()); + $this->assertInstanceOf(User::class, $user); + $this->assertInstanceOf(File::class, $user->getImage()); + $this->assertEquals($image, $user->getImage()); + } + + public function testProxy(): void + { + $user = $this->createUserWithImage(); + + $this->entityManager->persist($user); + $this->entityManager->flush(); - $entityManager->clear(); + $this->entityManager->clear(); - $user = $entityManager->getReference(User::class, $user->getId()); + $user = $this->entityManager->getReference(User::class, $user->getId()); + $this->assertIsProxy($user); $this->assertInstanceOf(User::class, $user); $this->assertInstanceOf(File::class, $user->getImage()); } + + public function testRemove(): void + { + $user = $this->createUserWithImage(); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $image = $user->getImage(); + $this->assertInstanceOf(File::class, $image); + $pointer = $image->getPointer(); + + $this->entityManager->clear(); + + $user = $this->entityManager->find(User::class, $user->getId()); + $this->assertInstanceOf(User::class, $user); + + $this->entityManager->remove($user); + $this->entityManager->flush(); + + $this->expectException(FileNotFoundException::class); + $newFile = $this->fileRepository->get($pointer); + } + + public function testRemoveProxy(): void + { + $user = $this->createUserWithImage(); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $image = $user->getImage(); + $this->assertInstanceOf(File::class, $image); + $pointer = $image->getPointer(); + + $this->entityManager->clear(); + + $user = $this->entityManager->getReference(User::class, $user->getId()); + $this->assertInstanceOf(User::class, $user); + $this->assertIsProxy($user); + + $this->entityManager->remove($user); + $this->assertNotProxy($user); + $this->entityManager->flush(); + $this->assertNotProxy($user); + + $this->expectException(FileNotFoundException::class); + $newFile = $this->fileRepository->get($pointer); + } } From 43659fe5337b0786f19eca0839159b16bc4ea91c Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 00:21:20 +0700 Subject: [PATCH 14/21] release: 2.2.0 (#151) --- composer.json | 32 +++++++++---------- .../file-association-contracts/composer.json | 2 +- .../file-association-entity/composer.json | 8 ++--- packages/file-association/composer.json | 8 ++--- packages/file-bundle/composer.json | 10 +++--- packages/file-contracts/composer.json | 2 +- packages/file-derivation/composer.json | 6 ++-- packages/file-filepond/composer.json | 16 +++++----- packages/file-image/composer.json | 6 ++-- .../file-metadata-contracts/composer.json | 2 +- packages/file-metadata/composer.json | 6 ++-- packages/file-null/composer.json | 4 +-- .../file-oneup-uploader-bridge/composer.json | 6 ++-- packages/file-server/composer.json | 6 ++-- packages/file-symfony-bridge/composer.json | 10 +++--- packages/file-zip/composer.json | 6 ++-- packages/file/composer.json | 6 ++-- 17 files changed, 68 insertions(+), 68 deletions(-) diff --git a/composer.json b/composer.json index cd2a976..8472206 100644 --- a/composer.json +++ b/composer.json @@ -122,21 +122,21 @@ } }, "replace": { - "rekalogika/file": "2.1.0", - "rekalogika/file-association": "2.1.0", - "rekalogika/file-association-contracts": "2.1.0", - "rekalogika/file-association-entity": "2.1.0", - "rekalogika/file-bundle": "2.1.0", - "rekalogika/file-contracts": "2.1.0", - "rekalogika/file-derivation": "2.1.0", - "rekalogika/file-filepond": "2.1.0", - "rekalogika/file-image": "2.1.0", - "rekalogika/file-metadata": "2.1.0", - "rekalogika/file-metadata-contracts": "2.1.0", - "rekalogika/file-null": "2.1.0", - "rekalogika/file-oneup-uploader-bridge": "2.1.0", - "rekalogika/file-server": "2.1.0", - "rekalogika/file-symfony-bridge": "2.1.0", - "rekalogika/file-zip": "2.1.0" + "rekalogika/file": "2.2.0", + "rekalogika/file-association": "2.2.0", + "rekalogika/file-association-contracts": "2.2.0", + "rekalogika/file-association-entity": "2.2.0", + "rekalogika/file-bundle": "2.2.0", + "rekalogika/file-contracts": "2.2.0", + "rekalogika/file-derivation": "2.2.0", + "rekalogika/file-filepond": "2.2.0", + "rekalogika/file-image": "2.2.0", + "rekalogika/file-metadata": "2.2.0", + "rekalogika/file-metadata-contracts": "2.2.0", + "rekalogika/file-null": "2.2.0", + "rekalogika/file-oneup-uploader-bridge": "2.2.0", + "rekalogika/file-server": "2.2.0", + "rekalogika/file-symfony-bridge": "2.2.0", + "rekalogika/file-zip": "2.2.0" } } diff --git a/packages/file-association-contracts/composer.json b/packages/file-association-contracts/composer.json index 2fe16c7..d5258ad 100644 --- a/packages/file-association-contracts/composer.json +++ b/packages/file-association-contracts/composer.json @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-association-entity/composer.json b/packages/file-association-entity/composer.json index bd4c079..34eeef6 100644 --- a/packages/file-association-entity/composer.json +++ b/packages/file-association-entity/composer.json @@ -29,15 +29,15 @@ "php": "^8.2", "doctrine/collections": "^2.0", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-metadata": "^2.1", - "rekalogika/file-null": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-metadata": "^2.2", + "rekalogika/file-null": "^2.2", "rekalogika/doctrine-collections-decorator": "^2.0", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index 0fc8b21..c14e048 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -30,15 +30,15 @@ "psr/cache": "^2 || ^3", "psr/log": "^2 || ^3", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-association-contracts": "^2.1", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-null": "^2.1", + "rekalogika/file-association-contracts": "^2.2", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-null": "^2.2", "rekalogika/reconstitutor": "^2.2", "symfony/deprecation-contracts": "^3.1" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-bundle/composer.json b/packages/file-bundle/composer.json index 8134681..2393ea8 100644 --- a/packages/file-bundle/composer.json +++ b/packages/file-bundle/composer.json @@ -28,10 +28,10 @@ "php": "^8.2", "league/flysystem": "^3.16", "league/flysystem-local": "^3.16", - "rekalogika/file": "^2.1", - "rekalogika/file-association-contracts": "^2.1", - "rekalogika/file-association-entity": "^2.1", - "rekalogika/file-contracts": "^2.1", + "rekalogika/file": "^2.2", + "rekalogika/file-association-contracts": "^2.2", + "rekalogika/file-association-entity": "^2.2", + "rekalogika/file-contracts": "^2.2", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", @@ -53,7 +53,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-contracts/composer.json b/packages/file-contracts/composer.json index 2faa4c9..bd71370 100644 --- a/packages/file-contracts/composer.json +++ b/packages/file-contracts/composer.json @@ -33,7 +33,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-derivation/composer.json b/packages/file-derivation/composer.json index d3825f9..f80d419 100644 --- a/packages/file-derivation/composer.json +++ b/packages/file-derivation/composer.json @@ -22,12 +22,12 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file": "^2.1" + "rekalogika/file-contracts": "^2.2", + "rekalogika/file": "^2.2" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-filepond/composer.json b/packages/file-filepond/composer.json index 04582f0..0d644e3 100644 --- a/packages/file-filepond/composer.json +++ b/packages/file-filepond/composer.json @@ -26,13 +26,13 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.1", - "rekalogika/file-association-entity": "^2.1", - "rekalogika/file-bundle": "^2.1", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-image": "^2.1", - "rekalogika/file-server": "^2.1", - "rekalogika/file-symfony-bridge": "^2.1", + "rekalogika/file": "^2.2", + "rekalogika/file-association-entity": "^2.2", + "rekalogika/file-bundle": "^2.2", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-image": "^2.2", + "rekalogika/file-server": "^2.2", + "rekalogika/file-symfony-bridge": "^2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/dependency-injection": "^6.2 || ^7.0", "symfony/form": "^6.2 || ^7.0", @@ -43,7 +43,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-image/composer.json b/packages/file-image/composer.json index d544c96..ecf838b 100644 --- a/packages/file-image/composer.json +++ b/packages/file-image/composer.json @@ -29,13 +29,13 @@ "php": "^8.2", "intervention/image": "^3.3", "psr/log": "^2 || ^3", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-derivation": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-derivation": "^2.2", "twig/twig": "^3.9" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-metadata-contracts/composer.json b/packages/file-metadata-contracts/composer.json index 8bd180c..2468237 100644 --- a/packages/file-metadata-contracts/composer.json +++ b/packages/file-metadata-contracts/composer.json @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-metadata/composer.json b/packages/file-metadata/composer.json index 2258c26..3869a19 100644 --- a/packages/file-metadata/composer.json +++ b/packages/file-metadata/composer.json @@ -26,13 +26,13 @@ "php": "^8.2", "cardinalby/content-disposition": "^1.1", "fileeye/mimemap": "^2.0", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-metadata-contracts": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-metadata-contracts": "^2.2", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-null/composer.json b/packages/file-null/composer.json index 02a1656..97cc177 100644 --- a/packages/file-null/composer.json +++ b/packages/file-null/composer.json @@ -26,12 +26,12 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.1", + "rekalogika/file-contracts": "^2.2", "symfony/translation-contracts": "^3.0" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-oneup-uploader-bridge/composer.json b/packages/file-oneup-uploader-bridge/composer.json index e128c6f..25831c2 100644 --- a/packages/file-oneup-uploader-bridge/composer.json +++ b/packages/file-oneup-uploader-bridge/composer.json @@ -25,12 +25,12 @@ "require": { "php": "^8.2", "oneup/uploader-bundle": "^5.0", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file": "^2.1" + "rekalogika/file-contracts": "^2.2", + "rekalogika/file": "^2.2" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-server/composer.json b/packages/file-server/composer.json index c7c7582..65ded5a 100644 --- a/packages/file-server/composer.json +++ b/packages/file-server/composer.json @@ -24,14 +24,14 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-symfony-bridge": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-symfony-bridge": "^2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/http-foundation": "^6.2 || ^7.0" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-symfony-bridge/composer.json b/packages/file-symfony-bridge/composer.json index 3d3d6d7..10b8f32 100644 --- a/packages/file-symfony-bridge/composer.json +++ b/packages/file-symfony-bridge/composer.json @@ -27,17 +27,17 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.1", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-metadata-contracts": "^2.1", - "rekalogika/file-metadata": "^2.1", + "rekalogika/file": "^2.2", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-metadata-contracts": "^2.2", + "rekalogika/file-metadata": "^2.2", "symfony/form": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/validator": "^6.3 || ^7.1" }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file-zip/composer.json b/packages/file-zip/composer.json index a37817a..514352b 100644 --- a/packages/file-zip/composer.json +++ b/packages/file-zip/composer.json @@ -28,8 +28,8 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-metadata": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-metadata": "^2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "maennchen/zipstream-php": "^3.1", "symfony/http-foundation": "^6.2 || ^7.0", @@ -37,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } diff --git a/packages/file/composer.json b/packages/file/composer.json index adfa41d..9d9e3ef 100644 --- a/packages/file/composer.json +++ b/packages/file/composer.json @@ -33,8 +33,8 @@ "psr/http-factory-implementation": "^1.0", "league/flysystem": "^3.16", "league/mime-type-detection": "^1.0.0", - "rekalogika/file-contracts": "^2.1", - "rekalogika/file-metadata": "^2.1", + "rekalogika/file-contracts": "^2.2", + "rekalogika/file-metadata": "^2.2", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" }, @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.2-dev" + "dev-main": "2.3-dev" } } } From d5db782346562c17972a920d80c506bdf54c9e87 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 22:20:29 +0700 Subject: [PATCH 15/21] fix: fix bug that `kernel.reset` is applied to outer decorators (#152) --- CHANGELOG.md | 4 ++ composer.json | 40 +++++++++---------- packages/file-association/composer.json | 3 +- packages/file-bundle/composer.json | 1 + .../file-bundle/config/file-association.php | 21 ++++++++-- tests/src/Tests/Architecture/Architecture.php | 1 + 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6264022..d889800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 2.2.1 + +* fix: fix bug that `kernel.reset` is applied to outer decorators + ## 2.2.0 * fix: throw exception if there are two properties with the same name in the diff --git a/composer.json b/composer.json index 8472206..aff96ee 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,15 @@ { "name": "rekalogika/file-src", "description": "Monorepo for rekalogika/file and related packages", - "homepage": "https://rekalogika.dev/file", "license": "MIT", + "type": "project", "authors": [ { "name": "Priyadi Iman Nurcahyo", "email": "priyadi@rekalogika.com" } ], - "type": "project", + "homepage": "https://rekalogika.dev/file", "require": { "cardinalby/content-disposition": "^1.1", "doctrine/collections": "^2.0", @@ -89,6 +89,24 @@ "twig/extra-bundle": "^2.12|^3.0", "vimeo/psalm": "^6.0" }, + "replace": { + "rekalogika/file": "2.2.0", + "rekalogika/file-association": "2.2.0", + "rekalogika/file-association-contracts": "2.2.0", + "rekalogika/file-association-entity": "2.2.0", + "rekalogika/file-bundle": "2.2.0", + "rekalogika/file-contracts": "2.2.0", + "rekalogika/file-derivation": "2.2.0", + "rekalogika/file-filepond": "2.2.0", + "rekalogika/file-image": "2.2.0", + "rekalogika/file-metadata": "2.2.0", + "rekalogika/file-metadata-contracts": "2.2.0", + "rekalogika/file-null": "2.2.0", + "rekalogika/file-oneup-uploader-bridge": "2.2.0", + "rekalogika/file-server": "2.2.0", + "rekalogika/file-symfony-bridge": "2.2.0", + "rekalogika/file-zip": "2.2.0" + }, "autoload": { "psr-4": { "Rekalogika\\Contracts\\File\\": "packages/file-contracts/src/", @@ -120,23 +138,5 @@ "php-http/discovery": true, "symfony/runtime": true } - }, - "replace": { - "rekalogika/file": "2.2.0", - "rekalogika/file-association": "2.2.0", - "rekalogika/file-association-contracts": "2.2.0", - "rekalogika/file-association-entity": "2.2.0", - "rekalogika/file-bundle": "2.2.0", - "rekalogika/file-contracts": "2.2.0", - "rekalogika/file-derivation": "2.2.0", - "rekalogika/file-filepond": "2.2.0", - "rekalogika/file-image": "2.2.0", - "rekalogika/file-metadata": "2.2.0", - "rekalogika/file-metadata-contracts": "2.2.0", - "rekalogika/file-null": "2.2.0", - "rekalogika/file-oneup-uploader-bridge": "2.2.0", - "rekalogika/file-server": "2.2.0", - "rekalogika/file-symfony-bridge": "2.2.0", - "rekalogika/file-zip": "2.2.0" } } diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index c14e048..7e1c0af 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -34,7 +34,8 @@ "rekalogika/file-contracts": "^2.2", "rekalogika/file-null": "^2.2", "rekalogika/reconstitutor": "^2.2", - "symfony/deprecation-contracts": "^3.1" + "symfony/deprecation-contracts": "^3.1", + "symfony/service-contracts": "^3.1" }, "extra": { "branch-alias": { diff --git a/packages/file-bundle/composer.json b/packages/file-bundle/composer.json index 2393ea8..798c55c 100644 --- a/packages/file-bundle/composer.json +++ b/packages/file-bundle/composer.json @@ -39,6 +39,7 @@ "symfony/framework-bundle": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/http-kernel": "^6.2 || ^7.0", + "symfony/service-contracts": "^3.1", "twig/twig": "^3.9" }, "require-dev": { diff --git a/packages/file-bundle/config/file-association.php b/packages/file-bundle/config/file-association.php index 74e7b06..af515cf 100644 --- a/packages/file-bundle/config/file-association.php +++ b/packages/file-bundle/config/file-association.php @@ -70,8 +70,13 @@ // object manager // + $services->alias( + 'rekalogika.file.association.object_manager', + 'rekalogika.file.association.object_manager.default', + ); + $services - ->set('rekalogika.file.association.object_manager') + ->set('rekalogika.file.association.object_manager.default') ->class(DefaultObjectManager::class) ->args([ '$classMetadataFactory' => service('rekalogika.file.association.class_metadata_factory'), @@ -84,8 +89,13 @@ // property manager // + $services->alias( + 'rekalogika.file.association.file_property_manager', + 'rekalogika.file.association.file_property_manager.default', + ); + $services - ->set('rekalogika.file.association.file_property_manager') + ->set('rekalogika.file.association.file_property_manager.default') ->class(DefaultFilePropertyManager::class) ->args([ '$fileRepository' => service(FileRepositoryInterface::class), @@ -245,8 +255,13 @@ // class metadata factory // + $services->alias( + 'rekalogika.file.association.class_metadata_factory', + 'rekalogika.file.association.class_metadata_factory.default', + ); + $services - ->set('rekalogika.file.association.class_metadata_factory') + ->set('rekalogika.file.association.class_metadata_factory.default') ->class(DefaultClassMetadataFactory::class) ->args([ service('rekalogika.file.association.property_lister'), diff --git a/tests/src/Tests/Architecture/Architecture.php b/tests/src/Tests/Architecture/Architecture.php index 715ffe8..8d9407a 100644 --- a/tests/src/Tests/Architecture/Architecture.php +++ b/tests/src/Tests/Architecture/Architecture.php @@ -308,6 +308,7 @@ public function testFileBundle(): Rule Selector::inNamespace('Symfony\Component\HttpFoundation'), Selector::inNamespace('Symfony\Component\HttpKernel'), Selector::inNamespace('Symfony\Component\Stopwatch'), + Selector::inNamespace('Symfony\Contracts\Service'), // soft dependencies (attributes) Selector::classname(\Override::class), From 339c6fba118204286d22415f6334412907aae6fb Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 22:22:24 +0700 Subject: [PATCH 16/21] deps: bump js dependencies (#153) --- CHANGELOG.md | 1 + .../file-filepond/assets/package-lock.json | 991 +++++++++--------- 2 files changed, 483 insertions(+), 509 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d889800..854b9fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.2.1 * fix: fix bug that `kernel.reset` is applied to outer decorators +* deps: bump js dependencies ## 2.2.0 diff --git a/packages/file-filepond/assets/package-lock.json b/packages/file-filepond/assets/package-lock.json index c4b5ab7..439da3a 100644 --- a/packages/file-filepond/assets/package-lock.json +++ b/packages/file-filepond/assets/package-lock.json @@ -48,9 +48,9 @@ } }, "node_modules/@babel/cli": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.27.0.tgz", - "integrity": "sha512-bZfxn8DRxwiVzDO5CEeV+7IqXeCkzI4yYnrQbpwjT76CUyossQc6RYE7n+xfm0/2k40lPaCpW0FhxYs7EBAetw==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.27.2.tgz", + "integrity": "sha512-cfd7DnGlhH6OIyuPSSj3vcfIdnbXukhAyKY8NaZrFadC7pXyL9mOL5WgjcptiEJLi5k3j8aYvLIVCzezrWTaiA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -77,44 +77,44 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -130,13 +130,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", "dev": true, "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -146,25 +146,25 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", + "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", "dev": true, "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -174,17 +174,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", - "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", + "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.27.0", + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.27.1", "semver": "^6.3.1" }, "engines": { @@ -195,12 +195,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", - "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-annotate-as-pure": "^7.27.1", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, @@ -228,40 +228,40 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -271,35 +271,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dev": true, "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -309,14 +309,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -326,79 +326,79 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", + "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", "dev": true, "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "dev": true, "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -408,13 +408,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", + "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -424,12 +424,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -439,12 +439,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -454,14 +454,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -471,13 +471,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", + "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -516,12 +516,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -531,12 +531,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -562,12 +562,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -577,14 +577,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", - "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", + "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.26.8" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -594,14 +594,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -611,12 +611,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", - "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -626,12 +626,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", - "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", + "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -641,13 +641,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -657,13 +657,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", + "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -673,16 +673,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", + "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.27.1", "globals": "^11.1.0" }, "engines": { @@ -693,13 +693,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -709,12 +709,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", + "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -724,13 +724,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -740,12 +740,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -755,13 +755,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -771,12 +771,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -786,12 +786,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", + "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -801,12 +801,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -816,13 +816,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", - "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -832,14 +832,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -849,12 +849,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -864,12 +864,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -879,12 +879,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", + "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -894,12 +894,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -909,13 +909,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -925,13 +925,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -941,15 +941,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", + "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -959,13 +959,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -975,13 +975,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -991,12 +991,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1006,12 +1006,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.26.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", - "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1021,12 +1021,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1036,14 +1036,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", + "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1053,13 +1054,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1069,12 +1070,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1084,13 +1085,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", + "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1100,12 +1101,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", + "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1115,13 +1116,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1131,14 +1132,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1148,12 +1149,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1163,13 +1164,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", - "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", + "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "regenerator-transform": "^0.15.2" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1179,13 +1179,13 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1195,12 +1195,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1210,12 +1210,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1225,13 +1225,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1241,12 +1241,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1256,12 +1256,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", - "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1271,12 +1271,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", - "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1286,12 +1286,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1301,13 +1301,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1317,13 +1317,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1333,13 +1333,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1349,74 +1349,74 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", - "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", + "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.26.8", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.26.5", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.26.3", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.26.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.26.3", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.26.8", - "@babel/plugin-transform-typeof-symbol": "^7.26.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.27.1", + "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.11.0", @@ -1445,43 +1445,31 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1490,13 +1478,13 @@ } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1659,9 +1647,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dev": true, "funding": [ { @@ -1678,10 +1666,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -1691,9 +1679,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001715", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", - "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", + "version": "1.0.30001717", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", + "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", "dev": true, "funding": [ { @@ -1757,9 +1745,9 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", - "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", + "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", "dev": true, "dependencies": { "browserslist": "^4.24.4" @@ -1787,9 +1775,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.143", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.143.tgz", - "integrity": "sha512-QqklJMOFBMqe46k8iIOwA9l2hz57V2OKMmP5eSWcUvwx+mASAsbU+wkF1pHjn9ZVSBPrsYWr4/W/95y5SwYg2g==", + "version": "1.5.150", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.150.tgz", + "integrity": "sha512-rOOkP2ZUMx1yL4fCxXQKDHQ8ZXwisb2OycOQVKHgvB3ZI4CvehOd4y2tfnnLDieJ3Zs1RL1Dlp3cMkyIn7nnXA==", "dev": true }, "node_modules/escalade": { @@ -2285,21 +2273,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", From b96fff18af3889d6f15f736e2ff661f43630f3f3 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 22:26:25 +0700 Subject: [PATCH 17/21] ci: add lint container (#154) --- .github/workflows/php.yml | 3 +++ CHANGELOG.md | 1 + 2 files changed, 4 insertions(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index b87217b..f060027 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -56,6 +56,9 @@ jobs: env: SYMFONY_REQUIRE: ${{ matrix.symfony }} + - name: Lint container + run: tests/bin/console lint:container + - name: Run psalm run: vendor/bin/psalm if: matrix.dep == 'highest' diff --git a/CHANGELOG.md b/CHANGELOG.md index 854b9fc..ff87e35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * fix: fix bug that `kernel.reset` is applied to outer decorators * deps: bump js dependencies +* ci: add lint container ## 2.2.0 From 168c861e2888e1b17baf77b13c3fa836c2e487e3 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 22:29:50 +0700 Subject: [PATCH 18/21] release: 2.2.1 (#155) --- composer.json | 40 +++++++++---------- .../file-association-entity/composer.json | 6 +-- packages/file-association/composer.json | 6 +-- packages/file-bundle/composer.json | 8 ++-- packages/file-derivation/composer.json | 4 +- packages/file-filepond/composer.json | 14 +++---- packages/file-image/composer.json | 4 +- packages/file-metadata/composer.json | 4 +- packages/file-null/composer.json | 2 +- .../file-oneup-uploader-bridge/composer.json | 4 +- packages/file-server/composer.json | 4 +- packages/file-symfony-bridge/composer.json | 8 ++-- packages/file-zip/composer.json | 4 +- packages/file/composer.json | 4 +- 14 files changed, 56 insertions(+), 56 deletions(-) diff --git a/composer.json b/composer.json index aff96ee..0608672 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,15 @@ { "name": "rekalogika/file-src", "description": "Monorepo for rekalogika/file and related packages", + "homepage": "https://rekalogika.dev/file", "license": "MIT", - "type": "project", "authors": [ { "name": "Priyadi Iman Nurcahyo", "email": "priyadi@rekalogika.com" } ], - "homepage": "https://rekalogika.dev/file", + "type": "project", "require": { "cardinalby/content-disposition": "^1.1", "doctrine/collections": "^2.0", @@ -89,24 +89,6 @@ "twig/extra-bundle": "^2.12|^3.0", "vimeo/psalm": "^6.0" }, - "replace": { - "rekalogika/file": "2.2.0", - "rekalogika/file-association": "2.2.0", - "rekalogika/file-association-contracts": "2.2.0", - "rekalogika/file-association-entity": "2.2.0", - "rekalogika/file-bundle": "2.2.0", - "rekalogika/file-contracts": "2.2.0", - "rekalogika/file-derivation": "2.2.0", - "rekalogika/file-filepond": "2.2.0", - "rekalogika/file-image": "2.2.0", - "rekalogika/file-metadata": "2.2.0", - "rekalogika/file-metadata-contracts": "2.2.0", - "rekalogika/file-null": "2.2.0", - "rekalogika/file-oneup-uploader-bridge": "2.2.0", - "rekalogika/file-server": "2.2.0", - "rekalogika/file-symfony-bridge": "2.2.0", - "rekalogika/file-zip": "2.2.0" - }, "autoload": { "psr-4": { "Rekalogika\\Contracts\\File\\": "packages/file-contracts/src/", @@ -138,5 +120,23 @@ "php-http/discovery": true, "symfony/runtime": true } + }, + "replace": { + "rekalogika/file": "2.2.1", + "rekalogika/file-association": "2.2.1", + "rekalogika/file-association-contracts": "2.2.1", + "rekalogika/file-association-entity": "2.2.1", + "rekalogika/file-bundle": "2.2.1", + "rekalogika/file-contracts": "2.2.1", + "rekalogika/file-derivation": "2.2.1", + "rekalogika/file-filepond": "2.2.1", + "rekalogika/file-image": "2.2.1", + "rekalogika/file-metadata": "2.2.1", + "rekalogika/file-metadata-contracts": "2.2.1", + "rekalogika/file-null": "2.2.1", + "rekalogika/file-oneup-uploader-bridge": "2.2.1", + "rekalogika/file-server": "2.2.1", + "rekalogika/file-symfony-bridge": "2.2.1", + "rekalogika/file-zip": "2.2.1" } } diff --git a/packages/file-association-entity/composer.json b/packages/file-association-entity/composer.json index 34eeef6..1f8fc33 100644 --- a/packages/file-association-entity/composer.json +++ b/packages/file-association-entity/composer.json @@ -29,9 +29,9 @@ "php": "^8.2", "doctrine/collections": "^2.0", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-metadata": "^2.2", - "rekalogika/file-null": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-metadata": "^2.2.1", + "rekalogika/file-null": "^2.2.1", "rekalogika/doctrine-collections-decorator": "^2.0", "symfony/translation-contracts": "^3.0" }, diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index 7e1c0af..21d00b8 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -30,9 +30,9 @@ "psr/cache": "^2 || ^3", "psr/log": "^2 || ^3", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-association-contracts": "^2.2", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-null": "^2.2", + "rekalogika/file-association-contracts": "^2.2.1", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-null": "^2.2.1", "rekalogika/reconstitutor": "^2.2", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" diff --git a/packages/file-bundle/composer.json b/packages/file-bundle/composer.json index 798c55c..4f71d7e 100644 --- a/packages/file-bundle/composer.json +++ b/packages/file-bundle/composer.json @@ -28,10 +28,10 @@ "php": "^8.2", "league/flysystem": "^3.16", "league/flysystem-local": "^3.16", - "rekalogika/file": "^2.2", - "rekalogika/file-association-contracts": "^2.2", - "rekalogika/file-association-entity": "^2.2", - "rekalogika/file-contracts": "^2.2", + "rekalogika/file": "^2.2.1", + "rekalogika/file-association-contracts": "^2.2.1", + "rekalogika/file-association-entity": "^2.2.1", + "rekalogika/file-contracts": "^2.2.1", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", diff --git a/packages/file-derivation/composer.json b/packages/file-derivation/composer.json index f80d419..043bb16 100644 --- a/packages/file-derivation/composer.json +++ b/packages/file-derivation/composer.json @@ -22,8 +22,8 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file": "^2.2" + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file": "^2.2.1" }, "extra": { "branch-alias": { diff --git a/packages/file-filepond/composer.json b/packages/file-filepond/composer.json index 0d644e3..086fd61 100644 --- a/packages/file-filepond/composer.json +++ b/packages/file-filepond/composer.json @@ -26,13 +26,13 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.2", - "rekalogika/file-association-entity": "^2.2", - "rekalogika/file-bundle": "^2.2", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-image": "^2.2", - "rekalogika/file-server": "^2.2", - "rekalogika/file-symfony-bridge": "^2.2", + "rekalogika/file": "^2.2.1", + "rekalogika/file-association-entity": "^2.2.1", + "rekalogika/file-bundle": "^2.2.1", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-image": "^2.2.1", + "rekalogika/file-server": "^2.2.1", + "rekalogika/file-symfony-bridge": "^2.2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/dependency-injection": "^6.2 || ^7.0", "symfony/form": "^6.2 || ^7.0", diff --git a/packages/file-image/composer.json b/packages/file-image/composer.json index ecf838b..eac7cdd 100644 --- a/packages/file-image/composer.json +++ b/packages/file-image/composer.json @@ -29,8 +29,8 @@ "php": "^8.2", "intervention/image": "^3.3", "psr/log": "^2 || ^3", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-derivation": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-derivation": "^2.2.1", "twig/twig": "^3.9" }, "extra": { diff --git a/packages/file-metadata/composer.json b/packages/file-metadata/composer.json index 3869a19..74a2301 100644 --- a/packages/file-metadata/composer.json +++ b/packages/file-metadata/composer.json @@ -26,8 +26,8 @@ "php": "^8.2", "cardinalby/content-disposition": "^1.1", "fileeye/mimemap": "^2.0", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-metadata-contracts": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-metadata-contracts": "^2.2.1", "symfony/translation-contracts": "^3.0" }, "extra": { diff --git a/packages/file-null/composer.json b/packages/file-null/composer.json index 97cc177..30c9a4d 100644 --- a/packages/file-null/composer.json +++ b/packages/file-null/composer.json @@ -26,7 +26,7 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2", + "rekalogika/file-contracts": "^2.2.1", "symfony/translation-contracts": "^3.0" }, "extra": { diff --git a/packages/file-oneup-uploader-bridge/composer.json b/packages/file-oneup-uploader-bridge/composer.json index 25831c2..c282ec2 100644 --- a/packages/file-oneup-uploader-bridge/composer.json +++ b/packages/file-oneup-uploader-bridge/composer.json @@ -25,8 +25,8 @@ "require": { "php": "^8.2", "oneup/uploader-bundle": "^5.0", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file": "^2.2" + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file": "^2.2.1" }, "extra": { "branch-alias": { diff --git a/packages/file-server/composer.json b/packages/file-server/composer.json index 65ded5a..1364365 100644 --- a/packages/file-server/composer.json +++ b/packages/file-server/composer.json @@ -24,8 +24,8 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-symfony-bridge": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-symfony-bridge": "^2.2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/http-foundation": "^6.2 || ^7.0" }, diff --git a/packages/file-symfony-bridge/composer.json b/packages/file-symfony-bridge/composer.json index 10b8f32..7289c37 100644 --- a/packages/file-symfony-bridge/composer.json +++ b/packages/file-symfony-bridge/composer.json @@ -27,10 +27,10 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.2", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-metadata-contracts": "^2.2", - "rekalogika/file-metadata": "^2.2", + "rekalogika/file": "^2.2.1", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-metadata-contracts": "^2.2.1", + "rekalogika/file-metadata": "^2.2.1", "symfony/form": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/validator": "^6.3 || ^7.1" diff --git a/packages/file-zip/composer.json b/packages/file-zip/composer.json index 514352b..74cf45a 100644 --- a/packages/file-zip/composer.json +++ b/packages/file-zip/composer.json @@ -28,8 +28,8 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-metadata": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-metadata": "^2.2.1", "rekalogika/temporary-url-bundle": "^1.7.2", "maennchen/zipstream-php": "^3.1", "symfony/http-foundation": "^6.2 || ^7.0", diff --git a/packages/file/composer.json b/packages/file/composer.json index 9d9e3ef..51c56f0 100644 --- a/packages/file/composer.json +++ b/packages/file/composer.json @@ -33,8 +33,8 @@ "psr/http-factory-implementation": "^1.0", "league/flysystem": "^3.16", "league/mime-type-detection": "^1.0.0", - "rekalogika/file-contracts": "^2.2", - "rekalogika/file-metadata": "^2.2", + "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-metadata": "^2.2.1", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" }, From 213f7800aa53d7e308b22534bba30ceb211e2495 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Wed, 7 May 2025 23:58:41 +0700 Subject: [PATCH 19/21] fix: fix generics on `AttributeReconstitutor` (#156) --- CHANGELOG.md | 4 ++++ .../src/Reconstitutor/AttributeReconstitutor.php | 2 ++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff87e35..3f197f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 2.2.2 + +* fix: fix generics on `AttributeReconstitutor` + ## 2.2.1 * fix: fix bug that `kernel.reset` is applied to outer decorators diff --git a/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php b/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php index 755524e..749bfc4 100644 --- a/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php +++ b/packages/file-association/src/Reconstitutor/AttributeReconstitutor.php @@ -19,6 +19,8 @@ /** * Reconstitutes objects with WithFileAssociation attribute + * + * @implements AttributeReconstitutorInterface */ final readonly class AttributeReconstitutor implements AttributeReconstitutorInterface { From c14a2d7ceaa27fe81b642fc51048c64e6123b9ab Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Fri, 9 May 2025 18:15:21 +0700 Subject: [PATCH 20/21] fix: `WeakMap` indirect modification bug (#157) --- CHANGELOG.md | 1 + .../src/PropertyRecorder/PropertyRecorder.php | 30 ++++--- psalm.xml | 5 ++ tests/src/Tests/Architecture/Architecture.php | 1 + .../FileAssociation/PropertyRecorderTest.php | 90 +++++++++++++++++++ 5 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 tests/src/Tests/FileAssociation/PropertyRecorderTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f197f5..e607d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.2.2 * fix: fix generics on `AttributeReconstitutor` +* fix: `WeakMap` indirect modification bug ## 2.2.1 diff --git a/packages/file-association/src/PropertyRecorder/PropertyRecorder.php b/packages/file-association/src/PropertyRecorder/PropertyRecorder.php index 0395398..5ac087a 100644 --- a/packages/file-association/src/PropertyRecorder/PropertyRecorder.php +++ b/packages/file-association/src/PropertyRecorder/PropertyRecorder.php @@ -18,7 +18,7 @@ final class PropertyRecorder implements ResetInterface { /** - * @var \WeakMap> + * @var \WeakMap> */ private \WeakMap $properties; @@ -35,8 +35,9 @@ public function reset(): void private function init(): void { - /** @var \WeakMap> */ + /** @var \WeakMap> */ $properties = new \WeakMap(); + $this->properties = $properties; } @@ -46,11 +47,15 @@ public function saveInitialProperty( mixed $value, ): void { if (!isset($this->properties[$object])) { - $this->properties[$object] = []; + /** @var \ArrayObject */ + $arrayObject = new \ArrayObject(); + + $this->properties->offsetSet($object, $arrayObject); } - /** @psalm-suppress MixedArgument */ - $this->properties[$object][$propertyName] = $value; + $this->properties + ->offsetGet($object) + ->offsetSet($propertyName, $value); } public function getInitialProperty( @@ -61,8 +66,9 @@ public function getInitialProperty( return null; } - /** @psalm-suppress PossiblyNullArrayAccess */ - return $this->properties[$object][$propertyName] ?? null; + return $this->properties + ->offsetGet($object) + ->offsetGet($propertyName); } public function hasInitialProperty( @@ -73,8 +79,9 @@ public function hasInitialProperty( return false; } - /** @psalm-suppress PossiblyNullArrayAccess */ - return isset($this->properties[$object][$propertyName]); + return $this->properties + ->offsetGet($object) + ->offsetExists($propertyName); } public function removeInitialProperty( @@ -85,7 +92,8 @@ public function removeInitialProperty( return; } - /** @psalm-suppress PossiblyNullArrayAccess */ - unset($this->properties[$object][$propertyName]); + $this->properties + ->offsetGet($object) + ->offsetUnset($propertyName); } } diff --git a/psalm.xml b/psalm.xml index e9a5c35..61f1e8f 100644 --- a/psalm.xml +++ b/psalm.xml @@ -66,6 +66,11 @@ + + + + + diff --git a/tests/src/Tests/Architecture/Architecture.php b/tests/src/Tests/Architecture/Architecture.php index 8d9407a..7b694b8 100644 --- a/tests/src/Tests/Architecture/Architecture.php +++ b/tests/src/Tests/Architecture/Architecture.php @@ -208,6 +208,7 @@ public function testFileAssociation(): Rule Selector::classname(\DateTimeInterface::class), Selector::classname(\DateTimeImmutable::class), Selector::classname(\WeakMap::class), + Selector::classname(\ArrayObject::class), Selector::classname(\UnitEnum::class), // reflection diff --git a/tests/src/Tests/FileAssociation/PropertyRecorderTest.php b/tests/src/Tests/FileAssociation/PropertyRecorderTest.php new file mode 100644 index 0000000..66c7131 --- /dev/null +++ b/tests/src/Tests/FileAssociation/PropertyRecorderTest.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Tests\Tests\FileAssociation; + +use PHPUnit\Framework\TestCase; +use Rekalogika\File\Association\PropertyRecorder\PropertyRecorder; + +final class PropertyRecorderTest extends TestCase +{ + private PropertyRecorder $propertyRecorder; + + #[\Override] + protected function setUp(): void + { + $this->propertyRecorder = new PropertyRecorder(); + } + + public function testSaveInitialProperty(): void + { + $object = new \stdClass(); + $propertyName = 'testProperty'; + $value = 'testValue'; + + $this->propertyRecorder->saveInitialProperty($object, $propertyName, $value); + + $this->assertTrue($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + $this->assertSame($value, $this->propertyRecorder->getInitialProperty($object, $propertyName)); + } + + public function testGetInitialProperty(): void + { + $object = new \stdClass(); + $propertyName = 'testProperty'; + $value = 'testValue'; + + $this->propertyRecorder->saveInitialProperty($object, $propertyName, $value); + + $this->assertSame($value, $this->propertyRecorder->getInitialProperty($object, $propertyName)); + $this->assertNull($this->propertyRecorder->getInitialProperty(new \stdClass(), 'nonExistentProperty')); + } + + public function testHasInitialProperty(): void + { + $object = new \stdClass(); + $propertyName = 'testProperty'; + + $this->assertFalse($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + + $this->propertyRecorder->saveInitialProperty($object, $propertyName, 'testValue'); + + $this->assertTrue($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + } + + public function testRemoveInitialProperty(): void + { + $object = new \stdClass(); + $propertyName = 'testProperty'; + $value = 'testValue'; + + $this->propertyRecorder->saveInitialProperty($object, $propertyName, $value); + $this->assertTrue($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + + $this->propertyRecorder->removeInitialProperty($object, $propertyName); + $this->assertFalse($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + } + + public function testReset(): void + { + $object = new \stdClass(); + $propertyName = 'testProperty'; + $value = 'testValue'; + + $this->propertyRecorder->saveInitialProperty($object, $propertyName, $value); + $this->assertTrue($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + + $this->propertyRecorder->reset(); + $this->assertFalse($this->propertyRecorder->hasInitialProperty($object, $propertyName)); + } +} From 3df82ce6f74bd005e401daafda385c207de6dd8c Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Fri, 9 May 2025 18:16:25 +0700 Subject: [PATCH 21/21] release: 2.2.2 (#158) --- composer.json | 32 +++++++++---------- .../file-association-entity/composer.json | 6 ++-- packages/file-association/composer.json | 6 ++-- packages/file-bundle/composer.json | 8 ++--- packages/file-derivation/composer.json | 4 +-- packages/file-filepond/composer.json | 14 ++++---- packages/file-image/composer.json | 4 +-- packages/file-metadata/composer.json | 4 +-- packages/file-null/composer.json | 2 +- .../file-oneup-uploader-bridge/composer.json | 4 +-- packages/file-server/composer.json | 4 +-- packages/file-symfony-bridge/composer.json | 8 ++--- packages/file-zip/composer.json | 4 +-- packages/file/composer.json | 4 +-- 14 files changed, 52 insertions(+), 52 deletions(-) diff --git a/composer.json b/composer.json index 0608672..ea4abae 100644 --- a/composer.json +++ b/composer.json @@ -122,21 +122,21 @@ } }, "replace": { - "rekalogika/file": "2.2.1", - "rekalogika/file-association": "2.2.1", - "rekalogika/file-association-contracts": "2.2.1", - "rekalogika/file-association-entity": "2.2.1", - "rekalogika/file-bundle": "2.2.1", - "rekalogika/file-contracts": "2.2.1", - "rekalogika/file-derivation": "2.2.1", - "rekalogika/file-filepond": "2.2.1", - "rekalogika/file-image": "2.2.1", - "rekalogika/file-metadata": "2.2.1", - "rekalogika/file-metadata-contracts": "2.2.1", - "rekalogika/file-null": "2.2.1", - "rekalogika/file-oneup-uploader-bridge": "2.2.1", - "rekalogika/file-server": "2.2.1", - "rekalogika/file-symfony-bridge": "2.2.1", - "rekalogika/file-zip": "2.2.1" + "rekalogika/file": "2.2.2", + "rekalogika/file-association": "2.2.2", + "rekalogika/file-association-contracts": "2.2.2", + "rekalogika/file-association-entity": "2.2.2", + "rekalogika/file-bundle": "2.2.2", + "rekalogika/file-contracts": "2.2.2", + "rekalogika/file-derivation": "2.2.2", + "rekalogika/file-filepond": "2.2.2", + "rekalogika/file-image": "2.2.2", + "rekalogika/file-metadata": "2.2.2", + "rekalogika/file-metadata-contracts": "2.2.2", + "rekalogika/file-null": "2.2.2", + "rekalogika/file-oneup-uploader-bridge": "2.2.2", + "rekalogika/file-server": "2.2.2", + "rekalogika/file-symfony-bridge": "2.2.2", + "rekalogika/file-zip": "2.2.2" } } diff --git a/packages/file-association-entity/composer.json b/packages/file-association-entity/composer.json index 1f8fc33..7998a72 100644 --- a/packages/file-association-entity/composer.json +++ b/packages/file-association-entity/composer.json @@ -29,9 +29,9 @@ "php": "^8.2", "doctrine/collections": "^2.0", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-metadata": "^2.2.1", - "rekalogika/file-null": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-metadata": "^2.2.2", + "rekalogika/file-null": "^2.2.2", "rekalogika/doctrine-collections-decorator": "^2.0", "symfony/translation-contracts": "^3.0" }, diff --git a/packages/file-association/composer.json b/packages/file-association/composer.json index 21d00b8..ca042e1 100644 --- a/packages/file-association/composer.json +++ b/packages/file-association/composer.json @@ -30,9 +30,9 @@ "psr/cache": "^2 || ^3", "psr/log": "^2 || ^3", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-association-contracts": "^2.2.1", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-null": "^2.2.1", + "rekalogika/file-association-contracts": "^2.2.2", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-null": "^2.2.2", "rekalogika/reconstitutor": "^2.2", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" diff --git a/packages/file-bundle/composer.json b/packages/file-bundle/composer.json index 4f71d7e..9296c25 100644 --- a/packages/file-bundle/composer.json +++ b/packages/file-bundle/composer.json @@ -28,10 +28,10 @@ "php": "^8.2", "league/flysystem": "^3.16", "league/flysystem-local": "^3.16", - "rekalogika/file": "^2.2.1", - "rekalogika/file-association-contracts": "^2.2.1", - "rekalogika/file-association-entity": "^2.2.1", - "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file": "^2.2.2", + "rekalogika/file-association-contracts": "^2.2.2", + "rekalogika/file-association-entity": "^2.2.2", + "rekalogika/file-contracts": "^2.2.2", "symfony/cache": "^6.2 || ^7.0", "symfony/config": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", diff --git a/packages/file-derivation/composer.json b/packages/file-derivation/composer.json index 043bb16..48045a8 100644 --- a/packages/file-derivation/composer.json +++ b/packages/file-derivation/composer.json @@ -22,8 +22,8 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file": "^2.2.1" + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file": "^2.2.2" }, "extra": { "branch-alias": { diff --git a/packages/file-filepond/composer.json b/packages/file-filepond/composer.json index 086fd61..8f93509 100644 --- a/packages/file-filepond/composer.json +++ b/packages/file-filepond/composer.json @@ -26,13 +26,13 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.2.1", - "rekalogika/file-association-entity": "^2.2.1", - "rekalogika/file-bundle": "^2.2.1", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-image": "^2.2.1", - "rekalogika/file-server": "^2.2.1", - "rekalogika/file-symfony-bridge": "^2.2.1", + "rekalogika/file": "^2.2.2", + "rekalogika/file-association-entity": "^2.2.2", + "rekalogika/file-bundle": "^2.2.2", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-image": "^2.2.2", + "rekalogika/file-server": "^2.2.2", + "rekalogika/file-symfony-bridge": "^2.2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/dependency-injection": "^6.2 || ^7.0", "symfony/form": "^6.2 || ^7.0", diff --git a/packages/file-image/composer.json b/packages/file-image/composer.json index eac7cdd..65db3b6 100644 --- a/packages/file-image/composer.json +++ b/packages/file-image/composer.json @@ -29,8 +29,8 @@ "php": "^8.2", "intervention/image": "^3.3", "psr/log": "^2 || ^3", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-derivation": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-derivation": "^2.2.2", "twig/twig": "^3.9" }, "extra": { diff --git a/packages/file-metadata/composer.json b/packages/file-metadata/composer.json index 74a2301..9acb380 100644 --- a/packages/file-metadata/composer.json +++ b/packages/file-metadata/composer.json @@ -26,8 +26,8 @@ "php": "^8.2", "cardinalby/content-disposition": "^1.1", "fileeye/mimemap": "^2.0", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-metadata-contracts": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-metadata-contracts": "^2.2.2", "symfony/translation-contracts": "^3.0" }, "extra": { diff --git a/packages/file-null/composer.json b/packages/file-null/composer.json index 30c9a4d..112c149 100644 --- a/packages/file-null/composer.json +++ b/packages/file-null/composer.json @@ -26,7 +26,7 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", "symfony/translation-contracts": "^3.0" }, "extra": { diff --git a/packages/file-oneup-uploader-bridge/composer.json b/packages/file-oneup-uploader-bridge/composer.json index c282ec2..5dee05d 100644 --- a/packages/file-oneup-uploader-bridge/composer.json +++ b/packages/file-oneup-uploader-bridge/composer.json @@ -25,8 +25,8 @@ "require": { "php": "^8.2", "oneup/uploader-bundle": "^5.0", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file": "^2.2.1" + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file": "^2.2.2" }, "extra": { "branch-alias": { diff --git a/packages/file-server/composer.json b/packages/file-server/composer.json index 1364365..6bb0f70 100644 --- a/packages/file-server/composer.json +++ b/packages/file-server/composer.json @@ -24,8 +24,8 @@ }, "require": { "php": "^8.2", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-symfony-bridge": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-symfony-bridge": "^2.2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "symfony/http-foundation": "^6.2 || ^7.0" }, diff --git a/packages/file-symfony-bridge/composer.json b/packages/file-symfony-bridge/composer.json index 7289c37..805e5a0 100644 --- a/packages/file-symfony-bridge/composer.json +++ b/packages/file-symfony-bridge/composer.json @@ -27,10 +27,10 @@ }, "require": { "php": "^8.2", - "rekalogika/file": "^2.2.1", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-metadata-contracts": "^2.2.1", - "rekalogika/file-metadata": "^2.2.1", + "rekalogika/file": "^2.2.2", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-metadata-contracts": "^2.2.2", + "rekalogika/file-metadata": "^2.2.2", "symfony/form": "^6.2 || ^7.0", "symfony/http-foundation": "^6.2 || ^7.0", "symfony/validator": "^6.3 || ^7.1" diff --git a/packages/file-zip/composer.json b/packages/file-zip/composer.json index 74cf45a..484e591 100644 --- a/packages/file-zip/composer.json +++ b/packages/file-zip/composer.json @@ -28,8 +28,8 @@ "require": { "php": "^8.2", "psr/http-message": "^1.0 || ^2.0", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-metadata": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-metadata": "^2.2.2", "rekalogika/temporary-url-bundle": "^1.7.2", "maennchen/zipstream-php": "^3.1", "symfony/http-foundation": "^6.2 || ^7.0", diff --git a/packages/file/composer.json b/packages/file/composer.json index 51c56f0..fb17b9d 100644 --- a/packages/file/composer.json +++ b/packages/file/composer.json @@ -33,8 +33,8 @@ "psr/http-factory-implementation": "^1.0", "league/flysystem": "^3.16", "league/mime-type-detection": "^1.0.0", - "rekalogika/file-contracts": "^2.2.1", - "rekalogika/file-metadata": "^2.2.1", + "rekalogika/file-contracts": "^2.2.2", + "rekalogika/file-metadata": "^2.2.2", "symfony/deprecation-contracts": "^3.1", "symfony/service-contracts": "^3.1" },
Class/PropertyAction/ResultObjectID/File LocationClassActionObject IDDuration
PropertyResultFilesystem ID — Key Duration
{{ object_result.class|abbr_class }} {{ object_result.type.string }} @@ -117,7 +126,7 @@ {% block property_result %}
└ {{ property_result.property }}{{ property_result.property }} {{ property_result.action.string }}