diff --git a/composer.lock b/composer.lock index 175159715..3c581bb8c 100644 --- a/composer.lock +++ b/composer.lock @@ -71,16 +71,16 @@ "source": { "type": "git", "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "b01a80e20e17c3bf3c5d8a0246289ec465fd0b0f" + "reference": "720f4bf1e1978f837161b12681a42a282a1ad786" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/b01a80e20e17c3bf3c5d8a0246289ec465fd0b0f", - "reference": "b01a80e20e17c3bf3c5d8a0246289ec465fd0b0f", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/720f4bf1e1978f837161b12681a42a282a1ad786", + "reference": "720f4bf1e1978f837161b12681a42a282a1ad786", "shasum": "" }, "require": { - "php": "~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5", + "php": "~8.3 || ~8.4 || ~8.5", "psr/clock": "^1.0", "psr/container": "^2.0.2", "psr/event-dispatcher": "^1.0", @@ -113,7 +113,7 @@ "issues": "https://github.com/nextcloud-deps/ocp/issues", "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "time": "2026-06-04T02:37:15+00:00" + "time": "2026-07-21T01:28:34+00:00" }, { "name": "psr/clock", @@ -1692,15 +1692,15 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "nextcloud/ocp": 20, - "roave/security-advisories": 20 + "roave/security-advisories": 20, + "nextcloud/ocp": 20 }, "prefer-stable": false, "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, + "platform": [], + "platform-dev": [], "platform-overrides": { "php": "8.2" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 77fdebecc..953893791 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -8,7 +8,6 @@ namespace OCA\GroupFolders\AppInfo; -use OCA\Circles\Events\CircleDestroyedEvent; use OCA\DAV\Connector\Sabre\Principal; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent; @@ -26,12 +25,12 @@ use OCA\GroupFolders\Command\ExpireGroup\ExpireGroupVersionsTrash; use OCA\GroupFolders\Folder\FolderManager; use OCA\GroupFolders\Listeners\CacheListener; -use OCA\GroupFolders\Listeners\CircleDestroyedEventListener; use OCA\GroupFolders\Listeners\DeleteListener; use OCA\GroupFolders\Listeners\LoadAdditionalScriptsListener; use OCA\GroupFolders\Listeners\NodeRenamedListener; use OCA\GroupFolders\Mount\FolderStorageManager; use OCA\GroupFolders\Mount\MountProvider; +use OCA\GroupFolders\TeamSpace\TeamSpaceProvider; use OCA\GroupFolders\Trash\TrashBackend; use OCA\GroupFolders\Trash\TrashManager; use OCA\GroupFolders\Versions\GroupVersionsExpireManager; @@ -85,7 +84,7 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalScriptsListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, LoadAdditionalScriptsListener::class); - $context->registerEventListener(CircleDestroyedEvent::class, CircleDestroyedEventListener::class); + $context->registerTeamResourceProvider(TeamSpaceProvider::class); $context->registerEventListener(NodeRenamedEvent::class, NodeRenamedListener::class); $context->registerEventListener(CacheEntryInsertedEvent::class, CacheListener::class, 99999); $context->registerEventListener(CacheEntryUpdatedEvent::class, CacheListener::class, 99999); diff --git a/lib/Command/Delete.php b/lib/Command/Delete.php index e01f03e5b..923f9e8f8 100644 --- a/lib/Command/Delete.php +++ b/lib/Command/Delete.php @@ -31,6 +31,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int return -1; } + if ($folder->isTeamSpace()) { + $output->writeln('This folder belongs to a team and cannot be deleted directly; unlink it from its team first.'); + return 1; + } + /** @var QuestionHelper $helper */ $helper = $this->getHelper('question'); $question = new ConfirmationQuestion('Are you sure you want to delete the Team folder ' . $folder->mountPoint . ' and all files within, this cannot be undone (y/N).', false); diff --git a/lib/Command/Group.php b/lib/Command/Group.php index 8eb3ff847..c3aeea018 100644 --- a/lib/Command/Group.php +++ b/lib/Command/Group.php @@ -71,7 +71,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $this->folderManager->setGroupPermissions($folder->id, $groupString, $permissions); - return 0; } diff --git a/lib/Command/Rename.php b/lib/Command/Rename.php index 0ec5d97a7..dccf76309 100644 --- a/lib/Command/Rename.php +++ b/lib/Command/Rename.php @@ -28,6 +28,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int return -1; } + if ($folder->isTeamSpace()) { + $output->writeln('This folder belongs to a team and cannot be renamed; unlink it from its team first.'); + return 1; + } + /** @var string $name */ $name = $input->getArgument('name'); diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php index 1efff9642..3fa530a4c 100644 --- a/lib/Controller/FolderController.php +++ b/lib/Controller/FolderController.php @@ -53,6 +53,7 @@ * acl_default_no_permission: bool, * manage: list, * sortIndex?: non-negative-int, + * team_circle_id?: ?string, * } */ class FolderController extends OCSController { @@ -110,6 +111,7 @@ private function formatFolder(FolderWithMappingsAndCache $folder): array { 'groups' => array_map(fn (array $group): int => $group['permissions'], $folder->groups), 'group_details' => $folder->groups, 'manage' => $folder->manage, + 'team_circle_id' => $folder->getTeamCircleId(), ]; } @@ -293,6 +295,10 @@ public function addFolder(string $mountpoint, ?string $bucket = null, bool $acl_ public function removeFolder(int $id): DataResponse { $folder = $this->checkedGetFolder($id); + if ($folder->isTeamSpace()) { + throw new OCSForbiddenException('This folder belongs to a team and cannot be deleted directly; unlink it from its team first'); + } + $this->folderStorageManager->deleteStoragesForFolder($folder); $this->manager->removeFolder($id); @@ -344,6 +350,10 @@ public function setMountPoint(int $id, string $mountPoint): DataResponse { public function addGroup(int $id, string $group): DataResponse { $folder = $this->checkedGetFolder($id); + if ($folder->isTeamSpace()) { + throw new OCSForbiddenException('This folder belongs to a team and cannot be shared with other groups; unlink it from its team first'); + } + if (array_key_exists($group, $folder->groups)) { throw new OCSBadRequestException('Group already assigned to this Groupfolder'); } @@ -370,7 +380,13 @@ public function addGroup(int $id, string $group): DataResponse { #[NoAdminRequired] #[FrontpageRoute(verb: 'DELETE', url: '/folders/{id}/groups/{group}', requirements: ['group' => '.+'])] public function removeGroup(int $id, string $group): DataResponse { - $this->checkedGetFolder($id); + $folder = $this->checkedGetFolder($id); + + // The owning team's access cannot be removed independently; the folder + // must be unlinked from its team first. + if ($folder->isTeamSpace() && $folder->getTeamCircleId() === $group) { + throw new OCSForbiddenException('This folder belongs to this team and its access cannot be removed independently; unlink the folder from the team first'); + } $this->manager->removeApplicableGroup($id, $group); @@ -395,7 +411,12 @@ public function removeGroup(int $id, string $group): DataResponse { #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/folders/{id}/groups/{group}', requirements: ['group' => '.+'])] public function setPermissions(int $id, string $group, int $permissions): DataResponse { - $this->checkedGetFolder($id); + $folder = $this->checkedGetFolder($id); + + // The owning team's permissions on a team space are fixed. + if ($folder->isTeamSpace() && $folder->getTeamCircleId() === $group) { + throw new OCSForbiddenException('This team space belongs to this team and its permissions cannot be changed independently; unlink the team space from the team first'); + } $this->manager->setGroupPermissions($id, $group, $permissions); @@ -421,7 +442,11 @@ public function setPermissions(int $id, string $group, int $permissions): DataRe #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/folders/{id}/manageACL')] public function setManageACL(int $id, string $mappingType, string $mappingId, bool $manageAcl): DataResponse { - $this->checkedGetFolder($id); + $folder = $this->checkedGetFolder($id); + + if ($folder->isTeamSpace()) { + throw new OCSForbiddenException('This folder belongs to a team and its ACL management cannot be changed independently; unlink it from its team first'); + } $this->manager->setManageACL($id, $mappingType, $mappingId, $manageAcl); @@ -445,7 +470,7 @@ public function setManageACL(int $id, string $mappingType, string $mappingId, bo #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/folders/{id}/quota')] public function setQuota(int $id, int $quota): DataResponse { - $this->checkedGetFolder($id); + $folder = $this->checkedGetFolder($id); $this->manager->setFolderQuota($id, $quota); @@ -469,7 +494,11 @@ public function setQuota(int $id, int $quota): DataResponse { #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/folders/{id}/acl')] public function setACL(int $id, bool $acl): DataResponse { - $this->checkedGetFolder($id); + $folder = $this->checkedGetFolder($id); + + if ($folder->isTeamSpace()) { + throw new OCSForbiddenException('This folder belongs to a team and its advanced permissions cannot be changed independently; unlink it from its team first'); + } $this->manager->setFolderACL($id, $acl); @@ -496,10 +525,12 @@ public function setACL(int $id, bool $acl): DataResponse { public function renameFolder(int $id, string $mountpoint): DataResponse { $mountpoint = $this->manager->trimMountpoint($mountpoint); - $this->checkedGetFolder($id); - $folder = $this->checkedGetFolder($id); + if ($folder->isTeamSpace()) { + throw new OCSForbiddenException('This folder belongs to a team and cannot be renamed; unlink it from its team first'); + } + if ($folder->mountPoint === $mountpoint) { return new DataResponse(['success' => true, 'folder' => $this->formatFolder($folder)]); } diff --git a/lib/Folder/FolderDefinition.php b/lib/Folder/FolderDefinition.php index 6a821e40e..1104d7462 100644 --- a/lib/Folder/FolderDefinition.php +++ b/lib/Folder/FolderDefinition.php @@ -11,6 +11,7 @@ class FolderDefinition { /** * @param array{separate-storage?: bool} $options + * @param ?string $teamCircleId The circle single id this team space belongs to; null for regular team folders. */ public function __construct( public readonly int $id, @@ -21,10 +22,27 @@ public function __construct( public readonly int $storageId, public readonly int $rootId, public readonly array $options, + public readonly ?string $teamCircleId = null, ) { } public function useSeparateStorage(): bool { return $this->options['separate-storage'] ?? false; } + + /** + * Whether this folder belongs to a team (i.e. is a team space) and + * therefore cannot be deleted or renamed independently of that team. + */ + public function isTeamSpace(): bool { + return $this->teamCircleId !== null; + } + + /** + * The circle single id this team space belongs to, or null for regular + * team folders. + */ + public function getTeamCircleId(): ?string { + return $this->teamCircleId; + } } diff --git a/lib/Folder/FolderDefinitionWithMappings.php b/lib/Folder/FolderDefinitionWithMappings.php index eb08b6a45..d7b584037 100644 --- a/lib/Folder/FolderDefinitionWithMappings.php +++ b/lib/Folder/FolderDefinitionWithMappings.php @@ -18,6 +18,7 @@ class FolderDefinitionWithMappings extends FolderDefinition { /** * @param array $groups * @param list $manage + * @param ?string $teamCircleId */ public function __construct( int $id, @@ -30,8 +31,9 @@ public function __construct( array $options, public readonly array $groups, public readonly array $manage, + ?string $teamCircleId = null, ) { - parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options); + parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options, $teamCircleId); } /** @@ -50,6 +52,7 @@ public static function fromFolder(FolderDefinition $folder, array $groups, array $folder->options, $groups, $manage, + $folder->teamCircleId, ); } diff --git a/lib/Folder/FolderDefinitionWithPermissions.php b/lib/Folder/FolderDefinitionWithPermissions.php index 6327d6311..d44e031ca 100644 --- a/lib/Folder/FolderDefinitionWithPermissions.php +++ b/lib/Folder/FolderDefinitionWithPermissions.php @@ -27,8 +27,9 @@ public function __construct( array $options, public readonly ICacheEntry $rootCacheEntry, public readonly int $permissions, + ?string $teamCircleId = null, ) { - parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options); + parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options, $teamCircleId); } public static function fromFolder(FolderDefinition $folder, ICacheEntry $rootCacheEntry, int $permissions): FolderDefinitionWithPermissions { @@ -43,6 +44,7 @@ public static function fromFolder(FolderDefinition $folder, ICacheEntry $rootCac $folder->options, $rootCacheEntry, $permissions, + $folder->teamCircleId, ); } @@ -85,6 +87,7 @@ public function withAddedPermissions(int $permissions): self { $this->options, $this->rootCacheEntry, $this->permissions | $permissions, + $this->teamCircleId, ); } } diff --git a/lib/Folder/FolderManager.php b/lib/Folder/FolderManager.php index b7e94850d..3752ad89a 100644 --- a/lib/Folder/FolderManager.php +++ b/lib/Folder/FolderManager.php @@ -100,10 +100,10 @@ public function getAllFolders(): array { $query = $this->connection->getQueryBuilder(); - $query->select('folder_id', 'mount_point', 'quota', 'acl', 'acl_default_no_permission', 'storage_id', 'root_id', 'options') + $query->select('folder_id', 'mount_point', 'quota', 'acl', 'acl_default_no_permission', 'storage_id', 'root_id', 'options', 'team_circle_id') ->from('group_folders', 'f'); - /** @var list $rows */ + /** @var list $rows */ $rows = $query->executeQuery()->fetchAll(); $folderMap = []; @@ -134,6 +134,7 @@ private function selectWithFileCache(?IQueryBuilder $query = null): IQueryBuilde 'storage_id', 'root_id', 'options', + 'team_circle_id', 'c.fileid', 'c.storage', 'c.path', @@ -174,7 +175,7 @@ public function getAllFoldersWithSize(int $offset = 0, ?int $limit = null, strin $query->addOrderBy('mount_point', 'ASC'); } - /** @var list $rows */ + /** @var list $rows */ $rows = $query->executeQuery()->fetchAll(); $folderIds = array_map(static fn (array $row): int => (int)$row['folder_id'], $rows); @@ -215,7 +216,7 @@ public function getAllFoldersForUserWithSize(IUser $user): array { ->selectAlias('a.permissions', 'group_permissions') ->where($query->expr()->in('a.group_id', $query->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY))); - /** @var list $rows */ + /** @var list $rows */ $rows = $query->executeQuery()->fetchAll(); $folderIds = array_map(static fn (array $row): int => (int)$row['folder_id'], $rows); @@ -336,7 +337,7 @@ public function getFolder(int $id): ?FolderWithMappingsAndCache { $query->where($query->expr()->eq('f.folder_id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT))); $result = $query->executeQuery(); - /** @var array{folder_id: int|string, mount_point: string, quota: int|string, acl: bool, acl_default_no_permission: bool, storage_id: int|string, root_id: int|string, options: string}|false $row */ + /** @var array{folder_id: int|string, mount_point: string, quota: int|string, acl: bool, acl_default_no_permission: bool, storage_id: int|string, root_id: int|string, options: string, team_circle_id: ?string}|false $row */ $row = $result->fetch(); $result->closeCursor(); if ($row === false) { @@ -662,7 +663,7 @@ private function getFolderOptions(array $row): array { } /** - * @param array{folder_id: int|string, mount_point: string, quota: int|string, acl: bool, acl_default_no_permission: bool, storage_id: int|string, root_id: int|string, options?: string} $row + * @param array{folder_id: int|string, mount_point: string, quota: int|string, acl: bool, acl_default_no_permission: bool, storage_id: int|string, root_id: int|string, options?: string, team_circle_id?: ?string} $row */ private function rowToFolder(array $row): FolderDefinition { return new FolderDefinition( @@ -674,6 +675,7 @@ private function rowToFolder(array $row): FolderDefinition { (int)$row['storage_id'], (int)$row['root_id'], $this->getFolderOptions($row), + $row['team_circle_id'] ?? null, ); } @@ -713,7 +715,7 @@ public function getFoldersForGroups(array $groupIds, ?int $folderId = null, ?arr $query->setParameter('groupIds', $chunk, IQueryBuilder::PARAM_STR_ARRAY); if ($paths === null) { - /** @var list $result */ + /** @var list $result */ $result = array_merge($result, $query->executeQuery()->fetchAll()); continue; } @@ -721,7 +723,7 @@ public function getFoldersForGroups(array $groupIds, ?int $folderId = null, ?arr // When paths are set, we need to chunk these as well foreach (array_chunk($paths, 1000) as $pathChunk) { $query->setParameter('path', $pathChunk, IQueryBuilder::PARAM_STR_ARRAY); - /** @var list $result */ + /** @var list $result */ $result = array_merge($result, $query->executeQuery()->fetchAll()); } } @@ -782,6 +784,32 @@ public function hasFolderForCircle(string $circleId): bool { return ($count) > 0; } + /** + * Return all group folders directly assigned to or owned by a circle. + * + * @return list + * @throws Exception + */ + public function getFoldersForCircle(string $circleId): array { + if ($circleId === '') { + throw new \InvalidArgumentException('circleId cannot be empty'); + } + + $query = $this->connection->getQueryBuilder(); + $query->select('f.folder_id', 'f.mount_point', 'f.quota', 'f.acl', 'f.acl_default_no_permission', 'f.storage_id', 'f.root_id', 'f.options', 'f.team_circle_id') + ->from('group_folders', 'f') + ->leftJoin('f', 'group_folders_groups', 'g', $query->expr()->eq('f.folder_id', 'g.folder_id')) + ->where($query->expr()->orX( + $query->expr()->eq('g.circle_id', $query->createNamedParameter($circleId)), + $query->expr()->eq('f.team_circle_id', $query->createNamedParameter($circleId)), + )); + + /** @var list $rows */ + $rows = $query->executeQuery()->fetchAll(); + + return array_map($this->rowToFolder(...), $rows); + } + /** * @param list $paths * @return list @@ -826,11 +854,11 @@ public function getFoldersFromCircleMemberships(IUser $user, ?int $folderId = nu // When paths are set, we need to chunk these as well foreach (array_chunk($paths, 1000) as $pathChunk) { $query->setParameter('path', $pathChunk, IQueryBuilder::PARAM_STR_ARRAY); - /** @var list $result */ + /** @var list $result */ $result = array_merge($result, $query->executeQuery()->fetchAll()); } } else { - /** @var list $result */ + /** @var list $result */ $result = $query->executeQuery()->fetchAll(); } @@ -883,6 +911,7 @@ public function createFolder(string $mountPoint, array $options = [], bool $aclD 'mount_point' => $query->createNamedParameter($mountPoint), 'quota' => self::SPACE_DEFAULT, 'acl_default_no_permission' => $query->createNamedParameter($aclDefaultNoPermission, IQueryBuilder::PARAM_BOOL), + 'team_circle_id' => $query->createNamedParameter(null, IQueryBuilder::PARAM_NULL), 'options' => $query->createNamedParameter(json_encode([ 'separate-storage' => $seperateStorage, ])) @@ -908,6 +937,8 @@ public function createFolder(string $mountPoint, array $options = [], bool $aclD * @throws Exception */ public function addApplicableGroup(int $folderId, string $groupId): void { + $this->assertNotTeamSpace($folderId, 'sharing'); + $query = $this->connection->getQueryBuilder(); if ($this->isACircle($groupId)) { @@ -931,6 +962,17 @@ public function addApplicableGroup(int $folderId, string $groupId): void { * @throws Exception */ public function removeApplicableGroup(int $folderId, string $groupId): void { + // Removing the owning team's access would orphan the team space from + // its team. Block it; the folder must be unlinked from its team first + // (which clears team_circle_id and then removes the applicable group). + $teamCircleId = $this->getTeamCircleId($folderId); + if ($teamCircleId !== null && $teamCircleId === $groupId) { + throw new Exception( + 'This team space belongs to this team and its access cannot be removed independently; ' + . 'unlink the team space from the team first', + ); + } + $query = $this->connection->getQueryBuilder(); $query->delete('group_folders_groups') @@ -954,6 +996,16 @@ public function removeApplicableGroup(int $folderId, string $groupId): void { * @throws Exception */ public function setGroupPermissions(int $folderId, string $groupId, int $permissions): void { + // The owning team's permissions on a team space are fixed; they must + // not be lowered or removed independently of the team-space link. + $teamCircleId = $this->getTeamCircleId($folderId); + if ($teamCircleId !== null && $teamCircleId === $groupId) { + throw new Exception( + 'This team space belongs to this team and its permissions cannot be changed independently; ' + . 'unlink the team space from the team first', + ); + } + $query = $this->connection->getQueryBuilder(); $query->update('group_folders_groups') @@ -979,6 +1031,8 @@ public function setGroupPermissions(int $folderId, string $groupId, int $permiss * @throws Exception */ public function setManageACL(int $folderId, string $type, string $id, bool $manageAcl): void { + $this->assertNotTeamSpace($folderId, 'ACL management'); + $query = $this->connection->getQueryBuilder(); if ($manageAcl === true) { @@ -1007,6 +1061,14 @@ public function setManageACL(int $folderId, string $type, string $id, bool $mana * @throws Exception */ public function removeFolder(int $folderId): void { + // Prevent deletion of team spaces (folders that belong to a team). + // The owning app is responsible for unlinking the team space from its team + // before deleting it. + $folder = $this->getFolder($folderId); + if ($folder !== null && $folder->isTeamSpace()) { + throw new Exception('This team space belongs to a team and cannot be deleted directly; unlink it from its team first'); + } + $this->connection->beginTransaction(); try { $query = $this->connection->getQueryBuilder(); @@ -1059,10 +1121,33 @@ public function setFolderQuota(int $folderId, int $quota): void { $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The quota for groupfolder with id %d was set to %d bytes', [$folderId, $quota])); } + /** + * Update the JSON-encoded options of a folder. + * + * @param int $folderId + * @param array{separate-storage?: bool} $options + * @throws Exception + */ + public function setFolderOptions(int $folderId, array $options): void { + $query = $this->connection->getQueryBuilder(); + $query->update('group_folders') + ->set('options', $query->createNamedParameter(json_encode($options, JSON_THROW_ON_ERROR))) + ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The options for groupfolder with id %d were updated', [$folderId])); + } + /** * @throws Exception */ public function renameFolder(int $folderId, string $newMountPoint): void { + // Prevent renaming of team spaces (folders that belong to a team). + $folder = $this->getFolder($folderId); + if ($folder !== null && $folder->isTeamSpace()) { + throw new Exception('This team space belongs to a team and cannot be renamed; unlink it from its team first'); + } + $query = $this->connection->getQueryBuilder(); $query->update('group_folders') @@ -1138,10 +1223,126 @@ public function deleteCircle(string $circleId): void { $query->executeStatement(); } + /** + * Look up the team space that belongs to the given team (circle single id) + * via the `team_circle_id` column. + * + * This is the single source of truth for the "folder belongs to team" + * relationship. The legacy `group_folders_groups.circle_id` column tracks + * applicable-group membership (a separate concern) and must not be used to + * determine team ownership. + * + * @return int|null The folder id, or null if no folder belongs to this team. + */ + public function getFolderIdByTeamCircleId(string $circleId): ?int { + if ($circleId === '') { + return null; + } + + $query = $this->connection->getQueryBuilder(); + $query->select('folder_id') + ->from('group_folders') + ->where($query->expr()->eq('team_circle_id', $query->createNamedParameter($circleId))); + $result = $query->executeQuery(); + $row = $result->fetch(); + $result->closeCursor(); + + if ($row === false || !isset($row['folder_id'])) { + return null; + } + + $folderId = $row['folder_id']; + return is_numeric($folderId) ? (int)$folderId : null; + } + + /** + * Mark a team folder as belonging to a team by setting the `team_circle_id` + * column. + */ + public function setTeamCircleId(int $folderId, string $circleId): void { + $existingFolderId = $this->getFolderIdByTeamCircleId($circleId); + if ($existingFolderId !== null && $existingFolderId !== $folderId) { + throw new Exception('This team already has a team space'); + } + + $query = $this->connection->getQueryBuilder(); + $query->update('group_folders') + ->set('team_circle_id', $query->createNamedParameter($circleId)) + ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + } + + /** + * Clear the team ownership of a team space by resetting the + * `team_circle_id` column to null. + */ + public function clearTeamCircleId(int $folderId): void { + $query = $this->connection->getQueryBuilder(); + $query->update('group_folders') + ->set('team_circle_id', $query->createNamedParameter(null, IQueryBuilder::PARAM_NULL)) + ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + } + + /** + * Reject a mutation that would change the sharing, rights, or ownership of + * a folder that belongs to a team. + * + * Team spaces are meant to host the team-specific apps and data of their + * owning team: they must not be shared with other teams/groups, have their + * permissions or ACL management changed, or have their quota altered + * independently of the team-space policy. The owning team's access can + * only be removed by unlinking the folder from its team first (which + * clears `team_circle_id`). + * + * Uses a lightweight query on `team_circle_id` instead of {@see getFolder()} + * so the guard works even when the folder's filecache row is incomplete + * (e.g. during tests or before storage initialization). + * + * @param int $folderId The folder being mutated. + * @param string $operation Human-readable description of the blocked + * operation, used in the exception message. + * @throws Exception When the folder belongs to a team. + */ + private function assertNotTeamSpace(int $folderId, string $operation): void { + if ($this->getTeamCircleId($folderId) !== null) { + throw new Exception( + 'This team space belongs to a team and its ' . $operation + . ' cannot be changed independently; unlink it from its team first', + ); + } + } + + /** + * Read only the `team_circle_id` column for a folder. + * + * Lighter than {@see getFolder()} (no filecache join), used by the + * team-space guards. Returns null if the folder does not exist or has no + * team owner. + */ + private function getTeamCircleId(int $folderId): ?string { + $query = $this->connection->getQueryBuilder(); + $query->select('team_circle_id') + ->from('group_folders') + ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); + $result = $query->executeQuery(); + $row = $result->fetch(); + $result->closeCursor(); + + if ($row === false || !array_key_exists('team_circle_id', $row)) { + return null; + } + + $value = $row['team_circle_id']; + return is_string($value) && $value !== '' ? $value : null; + } + /** * @throws Exception */ public function setFolderACL(int $folderId, bool $acl): void { + $this->assertNotTeamSpace($folderId, 'advanced permissions'); + $query = $this->connection->getQueryBuilder(); $query->update('group_folders') diff --git a/lib/Folder/FolderWithMappingsAndCache.php b/lib/Folder/FolderWithMappingsAndCache.php index b78dbfc4b..020b9707e 100644 --- a/lib/Folder/FolderWithMappingsAndCache.php +++ b/lib/Folder/FolderWithMappingsAndCache.php @@ -19,6 +19,7 @@ class FolderWithMappingsAndCache extends FolderDefinitionWithMappings { /** * @param array $groups * @param list $manage + * @param ?string $teamCircleId */ public function __construct( int $id, @@ -32,8 +33,9 @@ public function __construct( array $groups, array $manage, public readonly ICacheEntry $rootCacheEntry, + ?string $teamCircleId = null, ) { - parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options, $groups, $manage); + parent::__construct($id, $mountPoint, $quota, $acl, $aclDefaultNoPermission, $storageId, $rootId, $options, $groups, $manage, $teamCircleId); } public static function fromFolderWithMapping(FolderDefinitionWithMappings $folder, ICacheEntry $rootCacheEntry): FolderWithMappingsAndCache { @@ -49,6 +51,7 @@ public static function fromFolderWithMapping(FolderDefinitionWithMappings $folde $folder->groups, $folder->manage, $rootCacheEntry, + $folder->teamCircleId, ); } @@ -65,6 +68,7 @@ public static function fromFolderWithMapping(FolderDefinitionWithMappings $folde * groups: array, * manage: list, * options: array{separate-storage?: bool}, + * team_circle_id: ?string, * } */ #[\Override] @@ -81,6 +85,7 @@ public function toArray(): array { 'groups' => $this->groups, 'manage' => $this->manage, 'options' => $this->options, + 'team_circle_id' => $this->getTeamCircleId(), ]; } } diff --git a/lib/Listeners/CircleDestroyedEventListener.php b/lib/Listeners/CircleDestroyedEventListener.php deleted file mode 100644 index 7583c9485..000000000 --- a/lib/Listeners/CircleDestroyedEventListener.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ -class CircleDestroyedEventListener implements IEventListener { - public function __construct( - private readonly FolderManager $folderManager, - ) { - } - - #[\Override] - public function handle(Event $event): void { - /** @phpstan-ignore instanceof.alwaysTrue */ - if (!$event instanceof CircleDestroyedEvent) { - return; - } - - $circle = $event->getCircle(); - $this->folderManager->deleteCircle($circle->getSingleId()); - } -} diff --git a/lib/Migration/Version2300000Date20260720000001.php b/lib/Migration/Version2300000Date20260720000001.php new file mode 100644 index 000000000..4300b4e30 --- /dev/null +++ b/lib/Migration/Version2300000Date20260720000001.php @@ -0,0 +1,53 @@ +getTable('group_folders'); + if (!$table->hasColumn('team_circle_id')) { + $table->addColumn( + 'team_circle_id', Types::STRING, + [ + 'notnull' => false, + 'length' => 31, + 'default' => null, + ] + ); + } + + if (!$table->hasIndex('group_folders_team_circle')) { + $table->addUniqueIndex(['team_circle_id'], 'group_folders_team_circle'); + } + + return $schema; + } +} diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index fdbe579a6..0aaae75f2 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -57,6 +57,7 @@ * acl_default_no_permission: bool, * manage: list, * sortIndex?: non-negative-int, + * team_circle_id?: ?string, * } */ class ResponseDefinitions { diff --git a/lib/TeamSpace/TeamSpaceProvider.php b/lib/TeamSpace/TeamSpaceProvider.php new file mode 100644 index 000000000..f1455cd02 --- /dev/null +++ b/lib/TeamSpace/TeamSpaceProvider.php @@ -0,0 +1,101 @@ +l10n->t('Team spaces'); + } + + #[\Override] + public function getIconSvg(): string { + return ''; + } + + #[\Override] + public function getTeamFolder(string $teamId): ?TeamFolder { + return $this->service->getTeamSpaceForCircle($teamId); + } + + #[\Override] + public function createTeamFolder(Team $team, int $quota = 0): TeamFolder { + $this->service->upgradeTeamSpace($team, $quota); + + $folder = $this->getTeamFolder($team->getId()); + if ($folder === null) { + throw new \RuntimeException('Created team space could not be found'); + } + + return $folder; + } + + #[\Override] + public function unlinkTeamFolder(string $teamId): ?TeamFolder { + $folder = $this->getTeamFolder($teamId); + if ($folder === null) { + return null; + } + + $this->service->unlinkTeamSpace($teamId); + return $folder; + } + + #[\Override] + public function removeTeamFolder(string $teamId): bool { + return $this->service->removeTeamSpace($teamId); + } + + #[\Override] + public function getSharedWith(string $teamId): array { + return array_map(fn (TeamFolder $folder): TeamResource => new TeamResource( + $this, + (string)$folder->getId(), + $folder->getMountPoint(), + $this->urlGenerator->getAbsoluteURL('/apps/files/?dir=/' . rawurlencode($folder->getMountPoint())), + iconSvg: $this->getIconSvg(), + ), $this->service->getGroupFoldersForCircle($teamId)); + } + + #[\Override] + public function isSharedWithTeam(string $teamId, string $resourceId): bool { + foreach ($this->service->getGroupFoldersForCircle($teamId) as $folder) { + if ((string)$folder->getId() === $resourceId) { + return true; + } + } + + return false; + } + + #[\Override] + public function getTeamsForResource(string $resourceId): array { + return []; + } +} diff --git a/lib/TeamSpace/TeamSpaceService.php b/lib/TeamSpace/TeamSpaceService.php new file mode 100644 index 000000000..a277ece6f --- /dev/null +++ b/lib/TeamSpace/TeamSpaceService.php @@ -0,0 +1,288 @@ +folderManager->createFolder($mountPoint); + + try { + if ($quota > 0) { + $this->folderManager->setFolderQuota($folderId, $quota); + } + + $this->folderManager->addApplicableGroup($folderId, $circleId); + $this->folderManager->setManageACL($folderId, 'circle', $circleId, true); + + $this->folderManager->setTeamCircleId($folderId, $circleId); + } catch (\Exception $e) { + $existingFolderId = $this->folderManager->getFolderIdByTeamCircleId($circleId); + $this->logger->error( + 'Failed to configure team space, rolling back creation', + [ + 'circleId' => $circleId, + 'folderId' => $folderId, + 'exception' => $e, + ], + ); + try { + // Clear the team link first so the isTeamSpace guard in + // removeFolder() does not reject the rollback. + $this->folderManager->clearTeamCircleId($folderId); + $this->folderManager->removeFolder($folderId); + } catch (\Exception $rollbackException) { + $this->logger->error( + 'Could not roll back team space creation, manual cleanup required', + [ + 'circleId' => $circleId, + 'folderId' => $folderId, + 'exception' => $rollbackException, + ], + ); + } + + if ($existingFolderId !== null) { + $this->logger->info('Another request created the team space first; using the existing folder', [ + 'circleId' => $circleId, + 'folderId' => $existingFolderId, + ]); + return $existingFolderId; + } + throw $e; + } + + return $folderId; + } + + /** + * Unlink the team space from a team without deleting the folder. + * + * Clears the `team_circle_id` column and removes the applicable-group entry + * so the team no longer has access. The folder and its contents are + * preserved and become a regular team folder that can be managed via the + * groupfolders admin UI. + * + * This is the path used when a team is destroyed: the folder is kept so an + * admin can restore access if needed. It is also the admin escape hatch + * exposed via the circles OCS endpoint. + * + * @param string $circleId The circle single id. + * @return int|null The unlinked folder id, or null if no folder was linked. + */ + public function unlinkTeamSpace(string $circleId): ?int { + $folderId = $this->folderManager->getFolderIdByTeamCircleId($circleId); + if ($folderId === null) { + return null; + } + + $this->folderManager->clearTeamCircleId($folderId); + $this->folderManager->removeApplicableGroup($folderId, $circleId); + $this->logger->info('Unlinked team space from circle', [ + 'circleId' => $circleId, + 'folderId' => $folderId, + ]); + + return $folderId; + } + + /** + * Remove the team space that belongs to a team, deleting its contents. + * + * Clears the `team_circle_id` column first so the `isTeamSpace` guard in + * {@see FolderManager::removeFolder()} does not reject the deletion, then + * deletes the folder. + * + * @param string $circleId The circle single id. + * @return bool Whether a folder was found and removed. + */ + public function removeTeamSpace(string $circleId): bool { + $folderId = $this->folderManager->getFolderIdByTeamCircleId($circleId); + if ($folderId === null) { + return false; + } + + $this->folderManager->clearTeamCircleId($folderId); + $this->folderManager->removeApplicableGroup($folderId, $circleId); + $this->folderManager->removeFolder($folderId); + $this->logger->info('Removed team space for circle', [ + 'circleId' => $circleId, + 'folderId' => $folderId, + ]); + + return true; + } + + /** + * Create a team space for a team that predates the feature (or return the + * existing one if the team already has a folder). + * + * Idempotent: if the team already owns a folder, its id is returned without + * creating a new one. + * + * @param Team $team The team to upgrade. + * @param int $quota Quota in bytes (0 = unlimited). + * @return int The folder id (existing or newly created). + * @throws \Exception on failure. + */ + public function upgradeTeamSpace(Team $team, int $quota = 0): int { + $circleId = $team->getId(); + + $existing = $this->folderManager->getFolderIdByTeamCircleId($circleId); + if ($existing !== null) { + return $existing; + } + + $mountPoint = $this->generateUniqueMountPoint($this->pickBaseName($team)); + + return $this->createTeamSpace($circleId, $mountPoint, $quota); + } + + /** + * Find the team space that belongs to the given team. + * + * @return TeamFolder|null + */ + public function getTeamSpaceForCircle(string $circleId): ?TeamFolder { + $folderId = $this->folderManager->getFolderIdByTeamCircleId($circleId); + if ($folderId === null) { + return null; + } + + $folder = $this->folderManager->getFolder($folderId); + if ($folder === null) { + return null; + } + + return new TeamFolder($folder->id, $folder->mountPoint); + } + + /** + * Return all group folders directly accessible to the given team. + * + * This includes the team's dedicated team space as well as regular group + * folders that have been assigned to the team's circle. + * + * @return list + */ + public function getGroupFoldersForCircle(string $circleId): array { + return array_map( + static fn (FolderDefinition $folder): TeamFolder => new TeamFolder($folder->id, $folder->mountPoint), + $this->folderManager->getFoldersForCircle($circleId), + ); + } + + /** + * Whether the given circle (looked up by single id) owns a team space. + */ + public function hasTeamSpace(string $circleId): bool { + return $this->folderManager->getFolderIdByTeamCircleId($circleId) !== null; + } + + /** + * Pick a non-empty base name for the team space mount point. + * + * Tries the display name first, then the circle name, then the single id. + */ + public function pickBaseName(Team $team): string { + $displayName = trim($team->getDisplayName()); + if ($displayName !== '') { + return $displayName; + } + + $singleId = trim($team->getId()); + if ($singleId !== '') { + return $singleId; + } + + $this->logger->warning('pickBaseName: falling back to generic team-space'); + return 'team-space'; + } + + /** + * Generate a unique mount point based on the given base name. + * + * Falls back to a generic name if the sanitized base name is empty. + */ + public function generateUniqueMountPoint(string $baseName): string { + $mountPoint = $this->sanitizeMountPoint($baseName); + + if ($mountPoint === '') { + $mountPoint = 'team-space'; + } + + if (!$this->folderManager->mountPointExists($mountPoint)) { + return $mountPoint; + } + + $counter = 1; + do { + $candidate = $mountPoint . ' (' . $counter . ')'; + $counter++; + } while ($this->folderManager->mountPointExists($candidate)); + + return $candidate; + } + + /** + * Sanitize a string so it can be used as a team folder mount point. + * + * Strips control characters, path separators and backslashes, and limits + * the length to a safe value for the `mount_point` column. + */ + public function sanitizeMountPoint(string $name): string { + $name = trim($name); + $name = preg_replace('/[\x00-\x1f\/\\\\]+/', '', $name) ?? ''; + $name = trim($name); + + $max = 255; + if (mb_strlen($name) > $max) { + $name = mb_substr($name, 0, $max); + } + + return $name; + } +} diff --git a/openapi.json b/openapi.json index 946065eac..2510c8db4 100644 --- a/openapi.json +++ b/openapi.json @@ -191,6 +191,10 @@ "type": "integer", "format": "int64", "minimum": 0 + }, + "team_circle_id": { + "type": "string", + "nullable": true } } }, diff --git a/package-lock.json b/package-lock.json index c357b9839..fef32523b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -147,6 +147,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -227,7 +228,6 @@ "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -259,7 +259,6 @@ "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", @@ -282,7 +281,6 @@ "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -301,7 +299,6 @@ "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -328,7 +325,6 @@ "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -374,7 +370,6 @@ "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -398,7 +393,6 @@ "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-wrap-function": "^7.25.0", @@ -417,7 +411,6 @@ "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", @@ -436,7 +429,6 @@ "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -451,7 +443,6 @@ "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -494,7 +485,6 @@ "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.0", @@ -539,7 +529,6 @@ "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.3" @@ -557,7 +546,6 @@ "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -574,7 +562,6 @@ "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -591,7 +578,6 @@ "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -610,7 +596,6 @@ "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.0" @@ -628,7 +613,6 @@ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" }, @@ -641,7 +625,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -654,7 +637,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -668,7 +650,6 @@ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -699,7 +680,6 @@ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -713,7 +693,6 @@ "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -730,7 +709,6 @@ "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -746,7 +724,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -759,7 +736,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -788,7 +764,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -801,7 +776,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -814,7 +788,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -827,7 +800,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -840,7 +812,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -853,7 +824,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -867,7 +837,6 @@ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -883,7 +852,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -900,7 +868,6 @@ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -918,7 +885,6 @@ "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -935,7 +901,6 @@ "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-remap-async-to-generator": "^7.25.0", @@ -955,7 +920,6 @@ "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -974,7 +938,6 @@ "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -991,7 +954,6 @@ "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1008,7 +970,6 @@ "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.4", "@babel/helper-plugin-utils": "^7.24.8" @@ -1026,7 +987,6 @@ "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1045,7 +1005,6 @@ "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.25.2", @@ -1067,7 +1026,6 @@ "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -1085,7 +1043,6 @@ "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1102,7 +1059,6 @@ "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1120,7 +1076,6 @@ "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1137,7 +1092,6 @@ "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8" @@ -1155,7 +1109,6 @@ "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1173,7 +1126,6 @@ "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1191,7 +1143,6 @@ "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1209,7 +1160,6 @@ "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1227,7 +1177,6 @@ "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1246,7 +1195,6 @@ "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1264,7 +1212,6 @@ "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1281,7 +1228,6 @@ "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1299,7 +1245,6 @@ "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1316,7 +1261,6 @@ "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1334,7 +1278,6 @@ "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1353,7 +1296,6 @@ "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -1373,7 +1315,6 @@ "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1391,7 +1332,6 @@ "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1409,7 +1349,6 @@ "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1426,7 +1365,6 @@ "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1444,7 +1382,6 @@ "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1462,7 +1399,6 @@ "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1482,7 +1418,6 @@ "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1500,7 +1435,6 @@ "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1518,7 +1452,6 @@ "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1537,7 +1470,6 @@ "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1554,7 +1486,6 @@ "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.4", "@babel/helper-plugin-utils": "^7.24.8" @@ -1572,7 +1503,6 @@ "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1592,7 +1522,6 @@ "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1710,7 +1639,6 @@ "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -1728,7 +1656,6 @@ "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1745,7 +1672,6 @@ "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1762,7 +1688,6 @@ "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1780,7 +1705,6 @@ "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1797,7 +1721,6 @@ "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1814,7 +1737,6 @@ "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1831,7 +1753,6 @@ "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1848,7 +1769,6 @@ "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1866,7 +1786,6 @@ "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1884,7 +1803,6 @@ "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8" @@ -2001,7 +1919,6 @@ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2037,8 +1954,7 @@ "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@babel/runtime": { "version": "7.26.10", @@ -2122,7 +2038,6 @@ "integrity": "sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cacheable/utils": "^2.3.3", "@keyv/bigmap": "^1.3.0", @@ -2136,7 +2051,6 @@ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hashery": "^1.4.0", "hookified": "^1.15.0" @@ -2165,7 +2079,6 @@ "integrity": "sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hashery": "^1.3.0", "keyv": "^5.6.0" @@ -2177,7 +2090,6 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -2236,7 +2148,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -2284,8 +2195,7 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT-0", - "peer": true + "license": "MIT-0" }, "node_modules/@csstools/css-tokenizer": { "version": "4.0.0", @@ -2324,7 +2234,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -2536,7 +2445,6 @@ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", "dev": true, - "peer": true, "dependencies": { "comment-parser": "1.4.1", "esquery": "^1.5.0", @@ -3445,8 +3353,7 @@ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@mdi/js": { "version": "7.4.47", @@ -3843,7 +3750,6 @@ "integrity": "sha512-RX+0FxpL1h2EzjNLeW0VSGTkbyWIq7WgV7QAjtyUmDbSGwf1ds9Zy5OcRkgXRHRIu/W0gB0DhS2iz9qXHphCzA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fast-xml-parser": "^4.2.5", "requireindex": "^1.2.0", @@ -3863,7 +3769,6 @@ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4212,7 +4117,6 @@ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", "dev": true, - "peer": true, "dependencies": { "eslint-scope": "5.1.1" } @@ -4270,7 +4174,6 @@ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12.4.0" } @@ -4290,7 +4193,6 @@ "hasInstallScript": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", @@ -4333,7 +4235,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4355,7 +4256,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4377,7 +4277,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4399,7 +4298,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4421,7 +4319,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4443,7 +4340,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4465,7 +4361,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4487,7 +4382,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4509,7 +4403,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4531,7 +4424,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4553,7 +4445,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4575,7 +4466,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4597,7 +4487,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4613,7 +4502,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=12" }, @@ -5219,8 +5107,7 @@ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@rushstack/node-core-library": { "version": "5.22.0", @@ -5253,6 +5140,7 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5428,7 +5316,6 @@ "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -5691,8 +5578,7 @@ "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/mdast": { "version": "4.0.4", @@ -5715,6 +5601,7 @@ "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -5825,7 +5712,6 @@ "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -5926,7 +5812,6 @@ "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" @@ -5962,7 +5847,6 @@ "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/utils": "7.18.0", @@ -5991,7 +5875,6 @@ "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -6006,7 +5889,6 @@ "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", @@ -6036,7 +5918,6 @@ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -6050,7 +5931,6 @@ "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -6074,7 +5954,6 @@ "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" @@ -6093,7 +5972,6 @@ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -6525,6 +6403,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6720,7 +6599,6 @@ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, - "peer": true, "engines": { "node": ">=14" } @@ -6835,7 +6713,6 @@ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", @@ -7025,7 +6902,6 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -7133,7 +7009,6 @@ "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -7149,7 +7024,6 @@ "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" @@ -7164,7 +7038,6 @@ "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -7176,7 +7049,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "peer": true, "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -7187,8 +7059,7 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true, - "peer": true + "hasInstallScript": true }, "node_modules/bail": { "version": "2.0.2", @@ -7322,8 +7193,7 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/brace-expansion": { "version": "2.1.0", @@ -7516,6 +7386,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7604,7 +7475,6 @@ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "peer": true, "engines": { "node": ">=6" }, @@ -7624,7 +7494,6 @@ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, - "peer": true, "dependencies": { "semver": "^7.0.0" } @@ -7634,7 +7503,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -7647,7 +7515,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -7662,8 +7529,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true + "dev": true }, "node_modules/byte-length": { "version": "1.0.2", @@ -7676,7 +7542,6 @@ "integrity": "sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cacheable/memory": "^2.0.7", "@cacheable/utils": "^2.3.3", @@ -7691,7 +7556,6 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -8051,8 +7915,7 @@ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", @@ -8108,7 +7971,6 @@ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, - "peer": true, "engines": { "node": ">= 12.0.0" } @@ -8391,7 +8253,6 @@ "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" } @@ -8402,7 +8263,6 @@ "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" @@ -8416,7 +8276,6 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "peer": true, "bin": { "cssesc": "bin/cssesc" }, @@ -8437,6 +8296,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@cypress/request": "^4.0.0", "@cypress/xvfb": "^1.2.4", @@ -8986,7 +8846,6 @@ "dev": true, "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -9354,7 +9213,6 @@ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -9394,8 +9252,7 @@ "url": "https://github.com/sponsors/fb55" } ], - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "5.0.3", @@ -9403,7 +9260,6 @@ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -9429,7 +9285,6 @@ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -9609,7 +9464,6 @@ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.12" }, @@ -9623,7 +9477,6 @@ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -9936,6 +9789,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -9991,7 +9845,6 @@ "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -10048,7 +9901,6 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "peer": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -10060,7 +9912,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -10107,7 +9958,6 @@ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "debug": "^3.2.7" }, @@ -10126,7 +9976,6 @@ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -10175,7 +10024,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz", "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==", "dev": true, - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.6.0", @@ -10232,7 +10080,6 @@ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10243,7 +10090,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -10253,7 +10099,6 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, - "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -10267,7 +10112,6 @@ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10280,7 +10124,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz", "integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==", "dev": true, - "peer": true, "dependencies": { "@es-joy/jsdoccomment": "~0.41.0", "are-docs-informative": "^0.0.2", @@ -10304,7 +10147,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -10317,7 +10159,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -10330,7 +10171,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -10345,8 +10185,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true + "dev": true }, "node_modules/eslint-plugin-n": { "version": "16.6.2", @@ -10383,7 +10222,6 @@ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10394,7 +10232,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "peer": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -10410,7 +10247,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -10424,7 +10260,6 @@ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10437,7 +10272,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -10453,7 +10287,6 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -10465,8 +10298,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true + "dev": true }, "node_modules/eslint-plugin-promise": { "version": "6.6.0", @@ -10601,7 +10433,6 @@ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -10618,7 +10449,6 @@ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -10632,7 +10462,6 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -10645,7 +10474,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10659,7 +10487,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -10669,7 +10496,6 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, - "peer": true, "engines": { "node": ">=10" } @@ -11133,7 +10959,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "strnum": "^1.0.5" }, @@ -11147,7 +10972,6 @@ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4.9.1" } @@ -11728,7 +11552,6 @@ "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -11833,7 +11656,6 @@ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "global-prefix": "^3.0.0" }, @@ -11847,7 +11669,6 @@ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -11862,8 +11683,7 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", @@ -11871,7 +11691,6 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -11885,7 +11704,6 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -11931,8 +11749,7 @@ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/gonzales-pe": { "version": "4.3.0", @@ -11988,7 +11805,6 @@ "integrity": "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12106,7 +11922,6 @@ "integrity": "sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hookified": "^1.14.0" }, @@ -12249,8 +12064,7 @@ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/hot-patcher": { "version": "2.0.1", @@ -12263,7 +12077,6 @@ "integrity": "sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20.10" }, @@ -12284,7 +12097,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", @@ -12378,8 +12190,7 @@ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -12420,7 +12231,6 @@ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -12637,7 +12447,6 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, - "peer": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -12654,7 +12463,6 @@ "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.6.3" } @@ -12665,7 +12473,6 @@ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -12933,7 +12740,6 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13359,7 +13165,6 @@ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", "dev": true, - "peer": true, "engines": { "node": ">=12.0.0" } @@ -13481,7 +13286,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13491,8 +13295,7 @@ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/kolorist": { "version": "1.8.0", @@ -13709,8 +13512,7 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -13729,8 +13531,7 @@ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -14036,7 +13837,6 @@ "integrity": "sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -14266,8 +14066,7 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/memoize-one": { "version": "6.0.0", @@ -15032,8 +14831,7 @@ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -15179,7 +14977,6 @@ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "boolbase": "^1.0.0" }, @@ -15294,7 +15091,6 @@ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -15856,6 +15652,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -15871,7 +15668,6 @@ "integrity": "sha512-OLF6P7qctfAWayOhLpcVnTGqVeJzu2W3WpIYelfz2+JV5oGxfkcEvweN9U4XpeqE0P98dcD9ssusGwlF0TK0uQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "htmlparser2": "^8.0.0", "js-tokens": "^9.0.0", @@ -15887,24 +15683,21 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/postcss-safe-parser": { "version": "6.0.0", @@ -15912,7 +15705,6 @@ "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12.0" }, @@ -15944,7 +15736,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=12.0" }, @@ -15958,7 +15749,6 @@ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15972,8 +15762,7 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/postcss-values-parser": { "version": "6.0.2", @@ -16179,7 +15968,6 @@ "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "hookified": "^1.14.0" }, @@ -16296,6 +16084,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -16308,6 +16097,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -16469,8 +16259,7 @@ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", @@ -16478,7 +16267,6 @@ "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -16489,8 +16277,7 @@ "node_modules/regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "peer": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -16498,7 +16285,6 @@ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -16530,7 +16316,6 @@ "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -16549,7 +16334,6 @@ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -16562,7 +16346,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, - "peer": true, "bin": { "jsesc": "bin/jsesc" } @@ -16740,7 +16523,6 @@ "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.5" } @@ -16813,7 +16595,6 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -16823,7 +16604,6 @@ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, - "peer": true, "engines": { "node": ">=10" } @@ -16973,6 +16753,7 @@ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -17089,21 +16870,6 @@ } } }, - "node_modules/rollup-plugin-license/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/rollup-plugin-node-externals": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rollup-plugin-node-externals/-/rollup-plugin-node-externals-9.0.1.tgz", @@ -17302,7 +17068,6 @@ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -17319,7 +17084,6 @@ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 14.18.0" }, @@ -17896,8 +17660,7 @@ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", @@ -18181,8 +17944,7 @@ "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/strtok3": { "version": "10.3.4", @@ -18288,7 +18050,6 @@ "integrity": "sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^12 || >=14" }, @@ -18316,7 +18077,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -18355,7 +18115,6 @@ "integrity": "sha512-lLW7hTIMBiTfjenGuDq2kyHA6fBWd/+Df7MO4/AWOxiFeXP9clbpKgg27kHfwA3H7UNMGC7aeP3mNlZB5LMmEQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.3.5", "stylelint-config-html": ">=1.0.0", @@ -18378,7 +18137,6 @@ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -18392,7 +18150,6 @@ "integrity": "sha512-H88kCC+6Vtzj76NsC8rv6x/LW8slBzIbyeSjsKVlS+4qaEJoDrcJR4L+8JdrR2ORdTscrBzYWiiT2jq6leYR1Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "css-tree": "^3.0.1", "is-plain-object": "^5.0.0", @@ -18415,8 +18172,7 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { "version": "7.1.1", @@ -18424,7 +18180,6 @@ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18462,7 +18217,6 @@ } ], "license": "MIT-0", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -18486,7 +18240,6 @@ } ], "license": "MIT-0", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -18500,7 +18253,6 @@ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18514,7 +18266,6 @@ "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 16" } @@ -18525,7 +18276,6 @@ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -18553,7 +18303,6 @@ "integrity": "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "flat-cache": "^6.1.20" } @@ -18564,7 +18313,6 @@ "integrity": "sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cacheable": "^2.3.2", "flatted": "^3.3.3", @@ -18577,7 +18325,6 @@ "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", @@ -18599,7 +18346,6 @@ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4" } @@ -18610,7 +18356,6 @@ "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18624,7 +18369,6 @@ "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" }, @@ -18652,7 +18396,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18.0" }, @@ -18681,7 +18424,6 @@ "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.16" }, @@ -18695,7 +18437,6 @@ "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" @@ -18713,7 +18454,6 @@ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -18776,7 +18516,6 @@ "integrity": "sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^5.0.1", "supports-color": "^10.2.2" @@ -18803,8 +18542,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/systeminformation": { "version": "5.32.0", @@ -18845,7 +18583,6 @@ "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -18863,7 +18600,6 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -18880,8 +18616,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", @@ -18889,7 +18624,6 @@ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -19011,6 +18745,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -19144,7 +18879,6 @@ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=16" }, @@ -19209,7 +18943,6 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, - "peer": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -19222,7 +18955,6 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "peer": true, "dependencies": { "minimist": "^1.2.0" }, @@ -19867,6 +19599,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19928,7 +19661,6 @@ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -19939,7 +19671,6 @@ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -19954,7 +19685,6 @@ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -19965,7 +19695,6 @@ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -19976,7 +19705,6 @@ "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" }, @@ -20363,6 +20091,7 @@ "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", @@ -20994,6 +20723,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -21020,6 +20750,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz", "integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.28", "@vue/compiler-sfc": "3.5.28", @@ -21049,7 +20780,6 @@ "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", @@ -21075,7 +20805,6 @@ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -21093,7 +20822,6 @@ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -21107,7 +20835,6 @@ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -21467,7 +21194,6 @@ "integrity": "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -21482,7 +21208,6 @@ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=14" }, @@ -21495,7 +21220,6 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, - "peer": true, "engines": { "node": ">=12" } diff --git a/src/settings/App.scss b/src/settings/App.scss index c726647c3..b1b8fd8e6 100644 --- a/src/settings/App.scss +++ b/src/settings/App.scss @@ -251,3 +251,58 @@ margin-bottom: 30px; } } + +.folder-filter-tabs { + display: flex; + gap: var(--default-grid-baseline); + margin: 10px 0; + + button { + padding: 6px 14px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius-large); + background: var(--color-main-background); + color: var(--color-text-lighter); + cursor: pointer; + font-size: 0.9em; + + &:hover { + color: var(--color-main-text); + border-color: var(--color-border-dark); + } + + &.active { + color: var(--color-primary-element-text); + background: var(--color-primary-element); + border-color: var(--color-primary-element); + } + } +} + +.folder-list-empty td { + padding: 32px 16px; + color: var(--color-text-maxcontrast); + text-align: center; +} + +.team-space-badge { + display: inline-block; + margin-right: 6px; + padding: 1px 6px; + border-radius: var(--border-radius); + background: var(--color-background-dark); + color: var(--color-text-maxcontrast); + font-size: 0.75em; + font-weight: 600; + vertical-align: middle; +} + +.team-space-locked { + color: var(--color-text-maxcontrast); + cursor: default; +} + +.icon-delete.disabled { + opacity: 0.3 !important; + pointer-events: none; +} diff --git a/src/settings/App.tsx b/src/settings/App.tsx index 0292aaa75..869346632 100644 --- a/src/settings/App.tsx +++ b/src/settings/App.tsx @@ -40,6 +40,8 @@ const pageSize = 50 export type SortKey = 'mount_point' | 'quota' | 'groups' | 'acl'; +export type FolderFilter = 'all' | 'space' | 'folder'; + export interface AppState { delegatedAdminGroups: DelegationGroup[], delegatedSubAdminGroups: DelegationGroup[], @@ -52,6 +54,7 @@ export interface AppState { editingMountPoint: number; renameMountPoint: string; filter: string; + folderFilter: FolderFilter; sort: SortKey; sortOrder: number; isAdminNextcloud: boolean; @@ -77,6 +80,7 @@ export class App extends Component implements OC.Plugin implements OC.Plugin { + // Tab filter: separate team spaces from regular team folders. + const isTeamSpace = folder.team_circle_id !== null && folder.team_circle_id !== undefined + if (this.state.folderFilter === 'space' && !isTeamSpace) { + return false + } + if (this.state.folderFilter === 'folder' && isTeamSpace) { + return false + } + // Text filter from the global search. if (this.state.filter === '') { return true } return folder.mount_point.toLowerCase().includes(this.state.filter.toLowerCase()) }) .sort((a, b) => a.sortIndex! - b.sortIndex!) - .slice(this.state.currentPage * pageSize, this.state.currentPage * pageSize + pageSize) + + const rows = filteredFolders + .slice(this.state.currentPage * pageSize, this.state.currentPage * pageSize + pageSize) .map(folder => { const id = folder.id + const isTeamSpace = folder.team_circle_id !== null && folder.team_circle_id !== undefined + const teamCircle = isTeamSpace + ? this.state.circles.find(c => c.singleId === folder.team_circle_id) + : undefined return - {this.state.editingMountPoint === id + {isTeamSpace && ( + + {t('groupfolders', 'Team space')} + + )} + {this.state.editingMountPoint === id && !isTeamSpace ? implements OC.Plugin - : + : isTeamSpace + ? + {folder.mount_point} + + : } { + edit={this.state.editingGroup === id && !isTeamSpace} + showEdit={isTeamSpace ? () => {} : event => { event.stopPropagation() this.setState({ editingGroup: id }) }} @@ -345,36 +371,58 @@ export class App extends Component implements OC.Plugin + value={folder.quota} + size={folder.size} + onChange={this.setQuota.bind(this, folder)}/> - this.setAcl(folder, event.target.checked)} - /> - - {folder.acl - && - } + {isTeamSpace ? ( + + {folder.acl ? t('groupfolders', 'Enabled') : t('groupfolders', 'Disabled')} + + ) : ( + <> + this.setAcl(folder, event.target.checked)} + /> + + {folder.acl + && + } + + )} - + + + + @@ -436,10 +505,14 @@ export class App extends Component implements OC.Plugin - {rows} + {filteredFolders.length === 0 + ? + + + : rows}
{emptyMessage}
-