diff --git a/docs/docs/Guides/_category_.json b/docs/docs/Guides/_category_.json
new file mode 100644
index 00000000..5707fc1c
--- /dev/null
+++ b/docs/docs/Guides/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Guides",
+ "position": 7
+}
diff --git a/docs/docs/Upgrading/_category_.json b/docs/docs/Upgrading/_category_.json
new file mode 100644
index 00000000..a2283e68
--- /dev/null
+++ b/docs/docs/Upgrading/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Upgrading",
+ "position": 8
+}
diff --git a/docs/docs/authorization-service.md b/docs/docs/authorization-service.md
index 93db3587..731d110f 100644
--- a/docs/docs/authorization-service.md
+++ b/docs/docs/authorization-service.md
@@ -6,7 +6,7 @@ title: Authorization Service
### Usage
-The Authorization service can be retrieved from the service manager using the name
+The Authorization service can be retrieved from the container using the name
`Lmc\Rbac\Service\AuthorizationServiceInterface` and injected into your code:
```php
@@ -163,4 +163,12 @@ class Module
}
```
+## Authorization Exception
+
+LmcRbac provides a `Lmc\Rbac\Exception\UnauthorizedException` exception class that can be thrown by a service
+when authorization is denied.
+
+This is for convenience as LmcRbac does not provide any handler for this exception
+and it is expected that applications will implement the exception handler.
+
diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md
index 7d940880..bd7af213 100644
--- a/docs/docs/configuration.md
+++ b/docs/docs/configuration.md
@@ -1,6 +1,6 @@
---
sidebar_label: Configuration
-sidebar_position: 7
+sidebar_position: 5
title: Configuring LmcRbac
---
@@ -14,6 +14,6 @@ a `config/autoload/lmcrbac.global.php` file. A sample configuration file is prov
| Key | Description |
|--|------------------------------------------------------------------------------------------------------------------------------------------------|
| `guest_role` | Defines the name of the `guest` role when no identity exists.
Defaults to `'guest'`. |
-| `role_provider` | Defines the role provider.
Defaults to `[]`
See the [Role Providers](role-providers) section. |
+| `role_provider` | Defines the role provider.
Defaults to `[]`
See the [Role Providers](roles) section. |
| `assertion_map` | Defines the dynamic assertions that are associated to permissions.
Defaults to `[]`.
See the [Dynamic Assertions](assertions) section. |
-| `assertion_manager` | Provides a configuration for the Assertion Plugin Manager.
Defaults to `[]`.
See the [Dynamic Assertion](assertions.md) section. |
+| `assertion_manager` | Provides a configuration for the Assertion Plugin Manager.
Defaults to `[]`.
See the [Dynamic Assertion](assertions.md) section. |
diff --git a/docs/docs/quick-start.md b/docs/docs/quick-start.md
index 05c9ef9c..d1bc5889 100644
--- a/docs/docs/quick-start.md
+++ b/docs/docs/quick-start.md
@@ -9,7 +9,7 @@ LmcRbac extends the components provided by [laminas-permissions-rbac](https://gi
LmcRbac can be used in Laminas MVC and in Mezzio applications.
:::tip
-If you are upgrading from LmcRbac v1 or from zfc-rbac v3, please read the [Upgrading section](Upgrading/to-v2.md)
+If you are upgrading from LmcRbac v1 or from zfc-rbac v3, please read the [Upgrading section](upgrading/to-v2)
:::
## Concepts
@@ -63,7 +63,8 @@ Install the module:
$ composer require lm-commons/lmc-rbac
```
-You will be prompted by the Laminas Component Installer plugin to inject LM-Commons\LmcRbac.
+You will be prompted by the Laminas Component Installer plugin to inject the package
+into the application's configuration.
:::note
**Manual installation:**
@@ -82,7 +83,7 @@ By default, no roles and no permissions are defined.
Roles and permissions are defined by a Role Provider. `LmcRbac` ships with two roles providers:
- a simple `InMemoryRoleProvider` that uses an associative array to define roles and their permission. This is the default.
-- a `ObjectRepositoyRoleProvider` that is based on Doctrine ORM.
+- a `ObjectRepositoyRoleProvider` that is based on Doctrine ORM. (*Deprecated since v2.3*)
To quickly get started, let's use the `InMemoryRoleProvider` role provider.
@@ -118,7 +119,7 @@ a child and with its own permission. If the hierarchy is flattened:
## Basic authorization
-The authorization service can get retrieved from the service manager container and used to check if a permission
+The authorization service can get retrieved from the container and used to check if a permission
is granted to an identity:
```php
diff --git a/docs/docs/roles/custom-provider.md b/docs/docs/roles/custom-provider.md
new file mode 100644
index 00000000..06ada961
--- /dev/null
+++ b/docs/docs/roles/custom-provider.md
@@ -0,0 +1,87 @@
+---
+title: Building Custom Providers
+sidebar_position: 4
+---
+
+To create a custom role provider, you first need to create a class that implements the
+`Lmc\Rbac\Role\RoleProviderInterface` interface.
+
+Then, you need to add it to the role provider manager:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ MyCustomRoleProvider::class => [
+ // Options
+ ],
+ ],
+ ],
+];
+```
+And the role provider is created using the service manager:
+```php
+return [
+ 'service_manager' => [
+ 'factories' => [
+ MyCustomRoleProvider::class => MyCustomRoleProviderFactory::class,
+ ],
+ ],
+];
+```
+### Role Factory
+
+A Role Factory is a factory that can be used to create basic role instances for a role returned by the role provider.
+
+LmcRbac provide a convenience interface `RoleFactoryInterface` that can be used by a role provider to create roles.
+
+```php
+namespace Lmc\Rbac\Role;
+
+use Laminas\Permissions\Rbac\RoleInterface;
+
+interface RoleFactoryInterface
+{
+ public function createRole(string $roleName): RoleInterface;
+}
+```
+
+LmcRbac does not provide an implementation for this interface and it is left to the custom role provider to implement
+the factory.
+
+Therefore, in your application, you need to define a factory that returns a factory
+in your container config. For example:
+
+```php title="src/MyRoleFactory.php"
+ [
+ 'factories' => [
+ Lmc\Rbac\Role\RoleProviderInterface::class => function (ContainerInterface $container) {
+ return new MyApp\MyRoleFactory();
+ }
+ ],
+ ],
+];
+```
+
+
+
+
diff --git a/docs/docs/roles/in-memory-provider.md b/docs/docs/roles/in-memory-provider.md
new file mode 100644
index 00000000..b8898f71
--- /dev/null
+++ b/docs/docs/roles/in-memory-provider.md
@@ -0,0 +1,75 @@
+---
+title: Lmc\Rbac\Role\InMemoryRoleProvider
+sidebar_position: 1
+---
+
+### `Lmc\Rbac\Role\InMemoryRoleProvider` (built-in)
+
+This built-in provider is ideal for small/medium sites with few roles/permissions. All the data is specified in a simple associative array in a
+PHP file.
+
+Here is an example of the format you need to use:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\InMemoryRoleProvider::class => [
+ 'admin' => [
+ 'children' => ['member'],
+ 'permissions' => ['article.delete']
+ ],
+ 'member' => [
+ 'children' => ['guest'],
+ 'permissions' => ['article.edit', 'article.archive']
+ ],
+ 'guest' => [
+ 'permissions' => ['article.read']
+ ],
+ ],
+ ],
+ ],
+];
+```
+
+The `children` and `permissions` subkeys are entirely optional. Internally, the `Lmc\Rbac\Role\InMemoryRoleProvider` creates
+`Laminas\Permissions\Rbac\Role` objects with children, if any.
+
+If you are more confident with flat RBAC, the previous config can be re-written to remove any inheritence between roles:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\InMemoryRoleProvider::class => [
+ 'admin' => [
+ 'permissions' => [
+ 'article.delete',
+ 'article.edit',
+ 'article.archive',
+ 'article.read'
+ ]
+ ],
+ 'member' => [
+ 'permissions' => [
+ 'article.edit',
+ 'article.archive',
+ 'article.read'
+ ]
+ ],
+ 'guest' => [
+ 'permissions' => ['article.read']
+ ]
+ ]
+ ]
+ ]
+];
+```
+
+### Handling non existent roles
+
+If the list of roles names to retrieve using this provider includes roles that are
+not defined in the provider's configuration, the role provider will create `Laminas\Permissions\Role\Role` objects
+for them with no permissions.
+
+
diff --git a/docs/docs/roles/index.md b/docs/docs/roles/index.md
new file mode 100644
index 00000000..1e9e5f7d
--- /dev/null
+++ b/docs/docs/roles/index.md
@@ -0,0 +1,106 @@
+---
+sidebar_label: Roles, permissions and Role providers
+title: Roles, Permissions and Role providers
+sidebar_position: 4
+---
+
+## Roles
+
+A role is an object that returns a list of permissions that the role has.
+
+LmcRbac uses the Role class defined by [laminas-permissions-rbac](https://github.com/laminas/laminas-permissions-rbac). Roles
+are defined using the `\Laminas\Permissions\Rbac\Role` class or by a class
+implementing `\Laminas\Permissions\Rbac\RoleInterface`.
+
+Roles can have child roles and therefore provides a hierarchy of roles where a role inherit the permissions of all its
+child roles.
+
+For example, a 'user' role may have the 'read' and 'write' permissions, and a 'admin' role
+may inherit the permissions of the 'user' role plus an additional 'delete' role. In this structure,
+the 'admin' role will have 'user' as its child role.
+
+
+:::tip[Flat roles]
+Previous version of LmcRbac used to make a distinction between flat roles and hierarchical roles.
+A flat role is just a simplification of a hierarchical role, i.e. a hierarchical role without children.
+
+In `laminas-permissions-rbac`, roles are hierarchical.
+:::
+
+## Permissions
+
+A permission in `laminas-permissions-rbac` is simply a string that represents the permission such as 'read', 'write' or 'delete'.
+But it can also be more precise like 'article.read' or 'article.write'.
+
+A permission can also be an object as long as it can be cast to a string. This could be the
+case, for example, when permissions are stored in a database where they could
+also have a identifier and a description.
+
+:::tip
+An object can be cast to a string by implementing the `__toString()` method.
+:::
+
+## Role Service
+
+LmcRbac provides a role service that will use a role providers to fetch the
+roles and their permissions associated with a given identity.
+
+It can be retrieved from the container be requesting the `Lmc\Rbac\Service\RoleServiceInterface` service.
+
+`Lmc\Rbac\Service\RoleServiceInterface` defines the following method:
+
+- `getIdentityRoles(object|null $identity = null): iterable`
+
+| Parameter | Description |
+|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `$identity` | The identity whose roles to retrieve.
If `$identity` is null, then the `guest` is used.
The `guest` role is definable via configuration and defaults to `'guest'`. |
+
+:::warning
+The `$identity` parameter must be an object that either implements the `Lmc\Rbac\Identity\IdentityInterface`
+interface or has a `getRoles()` method that returns an array of strings or an array of objects
+implementing the `Laminas\Permissions\Rbac\RoleInterface` interface.
+
+
+:::
+
+
+## Role Providers
+A role provider is an object that returns a list of roles. A role provider must implement the
+`Lmc\Rbac\Role\RoleProviderInterface` interface. The only required method is `getRoles`, and must return an array
+of `Laminas\Permissions\Rbac\RoleInterface` objects.
+
+```php
+use Laminas\Permissions\Rbac\RoleInterface;
+
+interface RoleProviderInterface
+{
+ /**
+ * Get the roles from the provider
+ *
+ * @param string[] $roleNames
+ * @return RoleInterface[]
+ */
+ public function getRoles(iterable $roleNames): iterable;
+}
+```
+
+Roles can come from one of many sources: in memory, from a file, from a database, etc. However, you can specify only one role provider per application.
+
+LmcRbac comes with two built-in role providers:
+- [`Lmc\Rbac\Role\InMemoryRoleProvider`](/docs/roles/in-memory-provider)
+- [`Lmc\Rbac\Role\ObjectRepositoryRoleProvider`](/docs/roles/object-repository-role-provider). **(deprecated as of v2.3)**
+
+A role provider must be added to the `role_provider` subkey in the
+configuration file. For example:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\InMemoryRoleProvider::class => [
+ // configuration
+ ],
+ ]
+ ]
+];
+```
diff --git a/docs/docs/roles/object-repository-role-provider-doctrine.md b/docs/docs/roles/object-repository-role-provider-doctrine.md
new file mode 100644
index 00000000..53df9198
--- /dev/null
+++ b/docs/docs/roles/object-repository-role-provider-doctrine.md
@@ -0,0 +1,68 @@
+---
+title: Lmc\Rbac\Role\Doctrine\ObjectRepositoryRoleProvider
+sidebar_position: 3
+---
+
+:::info
+New since v2.3
+:::
+
+### `Lmc\Rbac\Role\Doctrine\ObjectRepositoryRoleProvider`
+
+This provider fetches roles from a database using a Doctrine ORM Object Repository.
+
+### Installation
+
+```shell
+$ composer require lm-commons/lmc-rbac-role-provider-doctrine-orm
+```
+
+You can configure this provider by giving an object repository service name that is fetched from the container
+using the `object_repository` key:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\Doctrine\ObjectRepositoryRoleProvider::class => [
+ 'object_repository' => 'App\Repository\RoleRepository',
+ 'role_name_property' => 'name',
+ 'factory_interface' => MyRoleFactory::class,
+ ],
+ ],
+ ],
+];
+```
+
+Or you can specify the `object_manager` and `class_name` options:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\ObjectRepositoryRoleProvider::class => [
+ 'object_manager' => 'doctrine.entitymanager.orm_default',
+ 'class_name' => 'App\Entity\Role',
+ 'role_name_property' => 'name',
+ 'factory_interface' => MyRoleFactory::class,
+ ],
+ ],
+ ],
+];
+```
+
+In both cases, you need to define the `role_name_property` value, which is the name of the entity's property
+that holds the actual role name. This is used internally to only load the identity roles, instead of loading
+the whole table every time.
+
+Please note that your entity fetched from the table MUST implement the
+`Laminas\Permissions\Rbac\RoleInterface` interface.
+
+Sample ORM entity models are provided in the `/data` folder for flat role, hierarchical role and permission.
+
+### Handling non existent roles
+
+You also need to define the `factory_interface` value to specify a Role Factory that implements the
+`Lmc\Rbac\Role\RoleFactoryInterface`. The Role Factory can be used to create a
+Role as a fallback when a requested role is not found in the database.
+
diff --git a/docs/docs/roles/object-repository-role-provider.md b/docs/docs/roles/object-repository-role-provider.md
new file mode 100644
index 00000000..da3fb0ef
--- /dev/null
+++ b/docs/docs/roles/object-repository-role-provider.md
@@ -0,0 +1,64 @@
+---
+title: Lmc\Rbac\Role\ObjectRepositoryRoleProvider
+sidebar_position: 2
+---
+
+:::warning
+Deprecated since v2.3
+You should use `Lmc\Rbac\Role\Doctrine\ObjectRepositoryRoleProvider` instead
+:::
+
+### `Lmc\Rbac\Role\ObjectRepositoryRoleProvider` (built-in)
+
+This builtin provider fetches roles from a database using
+`Doctrine\Common\Persistence\ObjectRepository` interface.
+
+You can configure this provider by giving an object repository service name that is fetched from the service manager
+using the `object_repository` key:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\ObjectRepositoryRoleProvider::class => [
+ 'object_repository' => 'App\Repository\RoleRepository',
+ 'role_name_property' => 'name'
+ ],
+ ],
+ ],
+];
+```
+
+Or you can specify the `object_manager` and `class_name` options:
+
+```php
+return [
+ 'lmc_rbac' => [
+ 'role_provider' => [
+ Lmc\Rbac\Role\ObjectRepositoryRoleProvider::class => [
+ 'object_manager' => 'doctrine.entitymanager.orm_default',
+ 'class_name' => 'App\Entity\Role',
+ 'role_name_property' => 'name'
+ ],
+ ],
+ ],
+];
+```
+
+In both cases, you need to specify the `role_name_property` value, which is the name of the entity's property
+that holds the actual role name. This is used internally to only load the identity roles, instead of loading
+the whole table every time.
+
+Please note that your entity fetched from the table MUST implement the `Laminas\Permissions\Rbac\RoleInterface` interface.
+
+Sample ORM entity models are provided in the `/data` folder for flat role, hierarchical role and permission.
+
+### Handling non existent roles
+
+This provider assumes that all required roles are available in the database.
+
+If the list of roles names to retrieve using this provider includes roles that are
+not defined in the database, the role provider will throw an exception.
+
+Therefore, extra care must be taken to ensure that the roles of an identity have
+corresponsing roles defined in the database.
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index 3526559c..5b983d53 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -24,7 +24,7 @@ const config = {
projectName: 'LmcRbac',
trailingSlash: false,
- onBrokenLinks: 'throw',
+ onBrokenLinks: 'warn',
//onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set
@@ -56,7 +56,13 @@ const config = {
lastVersion: 'current',
versions: {
current: {
- label: '2.2 (Latest)',
+ label: '2.3 (Latest)',
+ },
+ "2.2": {
+ banner: 'none',
+ },
+ "2.0": {
+ banner: 'none',
},
"1.4": {
banner: 'none',
@@ -103,7 +109,8 @@ themeConfig:
type: "docsVersionDropdown",
position: "right",
versions: {
- current: {label: '2.2 (Latest)'},
+ current: {label: '2.3 (Latest)'},
+ '2.2': {label: '2.2'},
'2.0': {label: '2.0'},
'1.4': {label: '1.x'},
},
@@ -138,19 +145,29 @@ themeConfig:
{
title: 'More',
items: [
-/*
- {
- label: 'Blog',
- to: '/blog',
- },
-
- */
{
label: 'GitHub',
href: 'https://github.com/lm-commons/lmcrbac',
},
],
},
+ {
+ title: 'Other',
+ items: [
+ {
+ label: 'Disclaimer',
+ href: 'https://lm-commons.github.io/disclaimer'
+ },
+ {
+ label: 'Privacy',
+ href: 'https://lm-commons.github.io/privacy'
+ },
+ {
+ label: 'Disclaimer',
+ href: 'https://lm-commons.github.io/cookies-policy'
+ },
+ ],
+ },
],
copyright: `Copyright © ${new Date().getFullYear()} LM-Commons Organization. Built with Docusaurus.`,
},
diff --git a/docs/versioned_docs/version-2.0/role-providers.md b/docs/versioned_docs/version-2.0/role-providers.md
index a011763e..88a48445 100644
--- a/docs/versioned_docs/version-2.0/role-providers.md
+++ b/docs/versioned_docs/version-2.0/role-providers.md
@@ -95,7 +95,7 @@ return [
```
The `children` and `permissions` subkeys are entirely optional. Internally, the `Lmc\Rbac\Role\InMemoryRoleProvider` creates
-`Lmc\Rbac\Role\Role` objects with children, if any.
+`Laminas\Permissions\Rbac\Role` objects with children, if any.
If you are more confident with flat RBAC, the previous config can be re-written to remove any inheritence between roles:
@@ -168,7 +168,7 @@ In both cases, you need to specify the `role_name_property` value, which is the
that holds the actual role name. This is used internally to only load the identity roles, instead of loading
the whole table every time.
-Please note that your entity fetched from the table MUST implement the `Lmc\Rbac\Role\RoleInterface` interface.
+Please note that your entity fetched from the table MUST implement the `Laminas\Permissions\Rbac\RoleInterface` interface.
Sample ORM entity models are provided in the `/data` folder for flat role, hierarchical role and permission.
diff --git a/docs/versioned_docs/version-2.2/Guides/integrating.md b/docs/versioned_docs/version-2.2/Guides/integrating.md
new file mode 100644
index 00000000..b3dcf644
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/Guides/integrating.md
@@ -0,0 +1,92 @@
+---
+title: Integrating into applications
+---
+
+LmcRbac can be used in your application to implement role-based access control.
+
+However, it is important to note that Authorization service `isGranted()` method expects
+an identity to be provided. The identity must also implement the `Lmc\Rbac\Identity\IdentityInterface`.
+
+User authentication is not in the scope of LmcRbac and must be implemented by your application.
+
+## Laminas MVC applications
+
+In a Laminas MVC application, you can use the ['laminas-authentication'](https://docs.laminas.dev/laminas-authentication)
+component with an appropriate adapter to provide the identity.
+
+The `Laminas\Authentication\AuthenticationService` service provides the identity using the `getIdentity()` method.
+However, it is not prescriptive on the signature of the returned identity object. It is up to the
+authentication adapter to return a authentication result that contains an identity object that implements the
+`IdentityInterface`.
+
+For example:
+
+```php
+authenticationService = $authenticationService;
+ $this->authorizationService = $authorizationService;
+ }
+
+ public function doSomething()
+ {
+ $identity = $this->authenticationService->hasIdentity() ? $this->authenticationService->getIdentity() : null;
+
+ // Check for permission
+ if ($this->getAuthorizationService()->isGranted($identity, 'somepermssion')) {
+ // authorized
+ } else {
+ // not authorized
+ }
+ }
+
+}
+
+```
+### Other Laminas MVC components to use
+To facilitate integration in an MVC application, you can use [LmcUser](https://lm-commons.github.io/LmcUser/) for
+authentication.
+
+You can also use [LmcRbacMvc](https://lm-commons.github.io/LmcRbacMvc/) which extends LmcRbac by handling identities.
+It also provides additional functionalities like route guards and strategies for handling unauthorized access. For example,
+an unauthorized strategy could be to redirect to a login page.
+
+## Mezzio and PSR-7 applications
+
+In a Mezzio application, you can use the [`mezzio/mezzio-authentication`](https://docs.mezzio.dev/mezzio-authentication/)
+component to provide the identity. `mezzio/mezzio-authentication` will add a `UserInterface` object to the request attributes.
+
+From this point, assuming that you have configured your application to use the `Mezzio\Authentication\AuthenticationMiddleware`,
+you can use `MyUser` in your handler by retrieving it from the request:
+
+```php
+// Retrieve the UserInterface object from the request.
+$user = $request->getAttribute(UserInterface::class);
+
+// Check for permission, this works because $user implements IdentityInterface
+if ($this->getAuthorizationService()->isGranted($user, 'somepermssion')) {
+ // authorized
+} else {
+ // not authorized
+}
+```
+
+How you define roles and permissions in your application is up to you. One way would be to use the route name as
+a permission such that authorization can be set up based on routes and optionally on route+verb.
+
+
+### Other Mezzio components to use
+
+A LmcRbac Mezzio component is under development to provide factories and middleware to facilitate integration of LmcRbac
+in Mezzio applications.
diff --git a/docs/versioned_docs/version-2.2/Upgrading/migration.md b/docs/versioned_docs/version-2.2/Upgrading/migration.md
new file mode 100644
index 00000000..b5829389
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/Upgrading/migration.md
@@ -0,0 +1,22 @@
+---
+sidebar_label: From ZF-Commons Rbac v3
+sidebar_position: 2
+title: Migrating from ZF-Commons RBAC v3
+---
+
+The ZF-Commons Rbac was created for the Zend Framework. When the Zend Framework was migrated to
+the Laminas project, the LM-Commons organization was created to provide components formerly provided by ZF-Commons.
+
+When ZfcRbac was moved to LM-Commons, it was split into two repositories:
+
+- [LmcRbacMvc](https://github.com/LM-Commons/LmcRbacMvc) contains the old version 2 of ZfcRbac.
+- LmcRbac contains the version 3 of ZfcRbac, which was only released as v3.alpha.1.
+
+To upgrade to LmcRbac v2, it is suggested to do it in two steps:
+
+1. Upgrade to LmcRbac v1 with the following steps:
+ * Uninstall `zf-commons/zfc-rbac:3.0.0-alpha.1`.
+ * Install `lm-commons/lmc-rbac:~1.0`
+ * Change `zfc-rbac.global.php` to `lmcrbac.global.php` and update the key `zfc_rbac` to `lmc_rbac`.
+ * Review your code for usages of the `ZfcRbac/*` namespace to `LmcRbac/*` namespace.
+2. Upgrade to LmcRbac v2 using the instructions in this [section](to-v2.md).
diff --git a/docs/versioned_docs/version-2.2/Upgrading/to-v2.md b/docs/versioned_docs/version-2.2/Upgrading/to-v2.md
new file mode 100644
index 00000000..c43c345b
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/Upgrading/to-v2.md
@@ -0,0 +1,37 @@
+---
+sidebar_label: From v1 to v2
+sidebar_position: 1
+title: Upgrading from v1 to v2
+---
+
+LmcRbac v2 is a major version upgrade with many breaking changes that prevent
+straightforward upgrading.
+
+### Namespace change
+
+The namespace has been changed from LmcRbac to Lmc\Rbac.
+
+Please review your code to replace references to the `LmcRbac` namespace
+by the `Lmc\Rbac` namespace.
+
+### LmcRbac is based on laminas-permissions-rbac
+
+LmcRbac is now based on the role class and interface provided by laminas-permissions-rbac which
+provides a hierarchical role model only.
+
+Therefore the `Role`, `HierarchicalRole` classes and the `RoleInterface` and `HierarchicalRoleInterface` have been removed
+in version 2.
+
+The `PermissionInterface` interface has been removed as permissions in `laminas-permissions-rbac` as just strings or any
+objects that can be casted to a string. If you use objects to hold permissions, just make sure that the object can be
+casted to a string by, for example, implementing a `__toString()` method.
+
+### Refactoring the factories
+
+The factories for services have been refactored from the `LmcRbac\Container` namespace
+to be colocated with the service that a factory is creating. All factories in the `LmcRbac\Container` namespace have
+been removed.
+
+### Refactoring the Assertion Plugin Manager
+
+The `AssertionContainer` class, interface and factory have been replaced by `AssertionPluginManager` class, interface and factory.
diff --git a/docs/versioned_docs/version-2.2/assertions.md b/docs/versioned_docs/version-2.2/assertions.md
new file mode 100644
index 00000000..193560f3
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/assertions.md
@@ -0,0 +1,153 @@
+---
+sidebar_label: Dynamic Assertions
+sidebar_position: 6
+title: Dynamic Assertions
+---
+
+Dynamic Assertions provide the capability to perform extra validations when
+the authorization service's `isGranted()` method is called.
+
+As described in [Authorization Service](authorization-service#reference), it is possible to pass a context to the
+`isGranted()` method. This context is then passed to dynamic assertion functions. This context can be any object type.
+
+You can define dynamic assertion functions and assigned them to permission via configuration.
+
+## Defining a dynamic assertion function
+
+A dynamic assertion must implement the `Lmc\Rbac\Assertion\AssertionInterace` which defines only one method:
+
+```php
+public function assert(
+ string $permission,
+ object|null $identity = null,
+ mixed $context = null
+ ): bool
+```
+The assertion returns `true` when the access is granted, `false` otherwise.
+
+A simple assertion could be to check that user represented by `$identity`, for the permission
+represented by `$permission` owns the resource represented by `$context`.
+
+```php
+getOwnerId() === $identity->getId();
+ }
+ // This should not happen since this assertion should only be
+ // called when the 'edit' permission is checked
+ return true;
+ }
+}
+```
+## Configuring Assertions
+
+Dynamic assertions are configured in LmcRbac via an assertion map defined in the LmcRbac configuration where assertions
+are associated with permissions.
+
+The `assertion_map` key in the configuration is used to define the assertion map. If an assertion needs to be created via
+a factory, use the `assertion_manager` config key. The Assertion Manager is a standard
+plugin manager and its configuration should be a service manager configuration array.
+
+```php
+ [
+ /* the rest of the file */
+ 'assertion_map' => [
+ 'edit' => \My\Namespace\MyAssertion::class,
+ ],
+ 'assertion_manager' => [
+ 'factories' => [
+ \My\Namespace\MyAssertion::class => InvokableFactory::class
+ ],
+ ],
+ ],
+];
+```
+It is also possible to configure an assertion using a callable instead of a class:
+
+```php
+ [
+ /* the rest of the file */
+ 'assertion_map' => [
+ 'edit' => function assert(string $permission, object|null $identity = null, $context = null): bool
+ {
+ // for 'edit' permission
+ if ('edit' === $permission) {
+ /** @var MyObjectClass $context */
+ return $context->getOwnerId() === $identity->getId();
+ }
+ // This should not happen since this assertion should only be
+ // called when the 'edit' permission is checked
+ return true;
+ },
+ ],
+ ],
+];
+```
+## Dynamic Assertion sets
+
+LmcRbac supports the creation of dynamic assertion sets where multiple assertions can be combined using 'and/or' logic.
+Assertion sets are configured by associating an array of assertions to a permission in the assertion map:
+
+```php
+ [
+ /* the rest of the file */
+ 'assertion_map' => [
+ 'edit' => [
+ \My\Namespace\AssertionA::class,
+ \My\Namespace\AssertionB::class,
+ ],
+ 'read' => [
+ 'condition' => \Lmc\Rbac\Assertion\AssertionSet::CONDITION_OR,
+ \My\Namespace\AssertionC::class,
+ \My\Namespace\AssertionD::class,
+ ],
+ 'delete' => [
+ 'condition' => \Lmc\Rbac\Assertion\AssertionSet::CONDITION_OR,
+ \My\Namespace\AssertionE::class,
+ [
+ 'condition' => \Lmc\Rbac\Assertion\AssertionSet::CONDITION_AND,
+ \My\Namespace\AssertionF::class,
+ \My\Namespace\AssertionC::class,
+ ],
+ ],
+ /** the rest of the file */
+ ],
+];
+```
+By default, an assertion set combines assertions using a 'and' condition. This is demonstrated by the map associated with
+the `'edit'` permission above.
+
+It is possible to combine assertions using a 'or' condition by adding a `condition` equal to `AssertionSet::CONDITION_OR`
+to the assertion set as demonstrated by the map associated with the `'read'` permission above.
+
+Furthermore, it is possible to nest assertion sets in order to create more complex logic as demonstrated by the map
+associated with the `'delete'` permission above.
+
+The default logic is to combine assertions using 'and' logic but this can be explicitly set as shown above for `'delete'`
+permission.
+
+## Defining dynamic assertions at run-time
+
+Although dynamic assertions are typically defined in the application's configuration, it is possible to set
+dynamic assertions at run-time by using the Authorization Service utility methods for adding/getting assertions.
+
+These methods are described in the Authorization Service [reference](authorization-service.md#reference).
diff --git a/docs/versioned_docs/version-2.2/authorization-service.md b/docs/versioned_docs/version-2.2/authorization-service.md
new file mode 100644
index 00000000..93db3587
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/authorization-service.md
@@ -0,0 +1,166 @@
+---
+sidebar_label: Authorization service
+sidebar_position: 5
+title: Authorization Service
+---
+
+### Usage
+
+The Authorization service can be retrieved from the service manager using the name
+`Lmc\Rbac\Service\AuthorizationServiceInterface` and injected into your code:
+
+```php
+get(Lmc\Rbac\Service\AuthorizationServiceInterface::class);
+
+```
+### Reference
+
+`Lmc\Rbac\Service\AuthorizationServiceInterface` defines the following methods:
+
+#### `isGranted(object|null $identity, string $permission, $context = null): bool`
+
+Checks that the identity has is granted the permission for the (optional) context.
+
+ | Parameter | Description |
+ |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+ | `$identity` | The identity whose roles to checks.
If `$identity` is null, then the `guest` is used.
The `guest` role is definable via configuration and defaults to `'guest'`. |
+ | `$permission` | The permission to check against |
+ | `$context` | A context that will be passed to dynamic assertions that are defined for the permission |
+
+#### `setAssertions(array $assertions, bool $merge = false): void`
+
+Allows to define dynamic assertions at run-time.
+
+ | Parameter | Description |
+ |---------------|-----------------------------------------------------------------------------------------|
+ | `$assertions` | An array of assertions to merge or to replace |
+ | `$merge` | if `true` the content of `$assertions` will be merged with existing assertions. |
+
+
+#### `setAssertion(string $permission, AssertionInterface|callable|string $assertion): void`
+Allows to define a dynamic assertion at run-time.
+
+ | Parameter | Description |
+ |---------------|-----------------------------------------|
+ | `$permission` | Permission name |
+ | `$assertion` | The assertion to set for `$permission` |
+
+#### `hasAssertion(string $permission): bool`
+Checks if the authorization has a dynamic assertion for a given permission.
+
+ | Parameter | Description |
+ |---------------|--------------------------|
+ | `$permission` | Permission name |
+
+
+#### `getAssertions(): array`
+
+Returns all the dynamic assertions defined.
+
+#### `getAssertion(string $permission): AssertionInterface|callable|string|null`
+
+Returns the dynamic assertion for the give permission
+
+ | Parameter | Description |
+ |---------------|-----------------------------|
+ | `$permission` | Permission permission name |
+
+More on dynamic assertions can be found in the [Assertions](assertions.md) section.
+
+More on the `guest` role can be found in the [Configuration](configuration.md) section.
+
+## Injecting the Authorization Service
+
+There are a few methods to inject the Authorization Service into your service.
+
+### Using a factory
+
+You can inject the AuthorizationService into your own objects using a factory. The Authorization Service
+can be retrieved from the container using `'Lmc\Rbac\Service\AuthorizationServiceInterface'`.
+
+Here is a classic example for injecting the Authorization Service into your own service
+
+*in your app's Module*
+
+```php
+use Lmc\Rbac\Service\AuthorizationServiceInterface;
+class Module
+{
+ public function getConfig()
+ {
+ return [
+ 'service_manager' => [
+ 'factories' => [
+ 'MyService' => function($sm) {
+ $authService = $sm->get('AuthorizationServiceInterface');
+ return new MyService($authService);
+ }
+ ],
+ ],
+ ];
+ }
+}
+````
+
+### Using traits
+
+For convenience, LmcRbac provides a `AuthorizationServiceAwareTrait` that adds the `$authorizationService` property and
+setter/getter methods.
+
+### Using delegators
+
+LmcRbac ships with a `Lmc\Rbac\Service\AuthorizationServiceDelegatorFactory` [delegator factory](https://docs.laminas.dev/laminas-servicemanager/delegators/)
+to automatically inject the authorization service into your classes.
+
+Your class must implement the `Lmc\Rbac\Service\AuthorizationServiceAwareInterface` and use the above trait, as shown below:
+
+```php
+namespace MyModule;
+
+use Lmc\Rbac\Service\AuthorizationServiceAwareInterface;
+use Lmc\Rbac\Service\AuthorizationServiceAwareTrait;
+
+class MyClass implements AuthorizationServiceAwareInterface
+{
+ use AuthorizationServiceAwareTrait;
+
+ public function doSomethingThatRequiresAuth()
+ {
+ if (! $this->getAuthorizationService()->isGranted($identity, 'deletePost')) {
+ throw new \Exception('You are not allowed !');
+ }
+ return true;
+ }
+}
+```
+
+And add your class to the right delegator:
+
+```php
+namespace MyModule;
+use Lmc\Rbac\Service\AuthorizationServiceDelegatorFactory;
+class Module
+{
+ // ...
+
+ public function getConfig()
+ {
+ return [
+ 'service_manager' => [
+ 'factories' => [
+ MyClass::class => InvokableFactory::class,
+ ],
+ 'delegators' => [
+ MyClass::class => [
+ AuthorizationServiceDelegatorFactory::class,
+ ],
+ ],
+ ],
+ ];
+ }
+}
+```
+
+
diff --git a/docs/versioned_docs/version-2.2/configuration.md b/docs/versioned_docs/version-2.2/configuration.md
new file mode 100644
index 00000000..7d940880
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/configuration.md
@@ -0,0 +1,19 @@
+---
+sidebar_label: Configuration
+sidebar_position: 7
+title: Configuring LmcRbac
+---
+
+LmcRbac is configured via the `lmc_rbac` key in the application config.
+
+This is typically achieved by creating
+a `config/autoload/lmcrbac.global.php` file. A sample configuration file is provided in the `config/` folder.
+
+## Reference
+
+| Key | Description |
+|--|------------------------------------------------------------------------------------------------------------------------------------------------|
+| `guest_role` | Defines the name of the `guest` role when no identity exists.
Defaults to `'guest'`. |
+| `role_provider` | Defines the role provider.
Defaults to `[]`
See the [Role Providers](role-providers) section. |
+| `assertion_map` | Defines the dynamic assertions that are associated to permissions.
Defaults to `[]`.
See the [Dynamic Assertions](assertions) section. |
+| `assertion_manager` | Provides a configuration for the Assertion Plugin Manager.
Defaults to `[]`.
See the [Dynamic Assertion](assertions.md) section. |
diff --git a/docs/versioned_docs/version-2.2/quick-start.md b/docs/versioned_docs/version-2.2/quick-start.md
new file mode 100644
index 00000000..05c9ef9c
--- /dev/null
+++ b/docs/versioned_docs/version-2.2/quick-start.md
@@ -0,0 +1,196 @@
+---
+title: Quick Start
+sidebar_position: 1
+---
+
+LmcRbac offers components and services to implement role-based access control (RBAC) in your application.
+LmcRbac extends the components provided by [laminas-permissions-rbac](https://github.com/laminas/laminas-permissions-rbac).
+
+LmcRbac can be used in Laminas MVC and in Mezzio applications.
+
+:::tip
+If you are upgrading from LmcRbac v1 or from zfc-rbac v3, please read the [Upgrading section](Upgrading/to-v2.md)
+:::
+
+## Concepts
+
+[Role-Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)
+is an approach to restricting system access to authorized users by putting emphasis
+on roles and their permissions.
+
+In the RBAC model:
+
+- an **identity** has one of more roles.
+- a **role** has one of more permissions.
+- a **permission** is typically an action like "read", "write", "delete".
+- a **role** can have **child roles** thus providing a hierarchy of roles where a role will inherit the permissions of all its child roles.
+
+### Authorization
+
+An identity will be authorized to perform an action, such as accessing a resource, if it is granted
+the permission that controls the execution of the action.
+
+For example, deleting an item could be restricted to identities that have at least one role that has the
+`item.delete` permission. This could be implemented by defining a `member` role that has the `item.delete` and assigning
+this role of an authenticated user.
+
+### Dynamic Assertions
+
+In some cases, just checking if the identity has the `item.delete` permission is not enough.
+It would also be necessary to check, for example, that the `item` belongs to the identity. Dynamic assertion allow
+to specify some extra checks before granting access to perform an action such as, in this case, being the owner of the
+resource.
+
+### Identities
+
+An identity is typically provided by an authentication process within the application.
+
+Authentication is not in the scope of `LmcRbac` and it is assumed that an identity entity that can provide the assigned
+roles is available when using the authorization service. If no identity is available, as it would be the case when no
+user is "logged in", then a guest role is assumed.
+
+## Requirements
+
+- PHP 8.2 or higher
+
+## Installation
+
+LmcRbac only officially supports installation through Composer.
+
+Install the module:
+
+```sh
+$ composer require lm-commons/lmc-rbac
+```
+
+You will be prompted by the Laminas Component Installer plugin to inject LM-Commons\LmcRbac.
+
+:::note
+**Manual installation:**
+
+- In Mezzio applications, enable the component by adding 'Lmc\Rbac\ConfigProvider' to the `config/config.php` file
+- In MVC applications, enable the module by adding `Lmc\Rbac` key to your
+`application.config.php` or `modules.config.php`,
+:::
+
+Customize the module by copy-pasting
+the `lmcrbac.global.php` file to your `config/autoload` folder.
+
+## Defining roles
+
+By default, no roles and no permissions are defined.
+
+Roles and permissions are defined by a Role Provider. `LmcRbac` ships with two roles providers:
+- a simple `InMemoryRoleProvider` that uses an associative array to define roles and their permission. This is the default.
+- a `ObjectRepositoyRoleProvider` that is based on Doctrine ORM.
+
+To quickly get started, let's use the `InMemoryRoleProvider` role provider.
+
+In the `config/autoload/lmcrbac.global.php`, add the following:
+
+```php
+ [
+ 'role_provider' => [
+ Lmc\Rbac\Role\InMemoryRoleProvider::class => [
+ 'guest',
+ 'user' => [
+ 'permissions' => ['create', 'edit'],
+ ],
+ 'admin' => [
+ 'children' => ['user'],
+ 'permissions' => ['delete'],
+ ],
+ ],
+ ],
+ ],
+];
+```
+
+This defines 3 roles: a `guest` role, a `user` role having 2 permissions, and a `admin` role which has the `user` role as
+a child and with its own permission. If the hierarchy is flattened:
+
+- `guest` has no permission
+- `user` has permissions `create` and `edit`
+- `admin` has permissions `create`, `edit` and `delete`
+
+## Basic authorization
+
+The authorization service can get retrieved from the service manager container and used to check if a permission
+is granted to an identity:
+
+```php
+get('\Lmc\Rbac\Service\AuthorizationServiceInterface');
+
+ /** @var \Lmc\Rbac\Identity\IdentityInterface|object $identity */
+ if ($authorizationService->isGranted($identity, 'create')) {
+ /** do something */
+ }
+```
+
+If `$identity` has the role `user` and/or `admin` then the authorization is granted. If the identity has the role `guest`, then authorization
+is denied.
+
+:::info
+If `$identity` is null (no identity), then the guest role is assumed which is set to `'guest'` by default. The guest role
+can be configured in the `lmcrbac.config.php` file. More on this in the [Configuration](configuration.md) section.
+:::
+
+:::warning
+`LmcRbac` does not provide any logic to instantiate an identity entity.
+It is assumed that the application will instantiate an entity that either
+implements `\Lmc\Rbac\Identity\IdentityInterface` which defines the `getRoles()`
+method, or implements a `getRoles()` method.
+:::
+
+## Using assertions
+
+Even if an identity has the `user` role granting it the `edit` permission, it should not have the authorization to edit another identity's resource.
+
+This can be achieved using dynamic assertion.
+
+An assertion is a function that implements the `\Lmc\Rbac\Assertion\AssertionInterface` and is configured in the configuration
+file.
+
+Let's modify the `lmcrbac.config.php` file as follows:
+
+```php
+ [
+ 'role_provider' => [
+ /* roles and permissions */
+ ],
+ 'assertion_map' => [
+ 'edit' => function ($permission, $identity = null, $resource = null) {
+ if ($resource->getOwnerId() === $identity->getId()) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ ],
+ ],
+];
+```
+
+Then use the authorization service passing the resource (called a 'context') in addition to the permission:
+
+```php
+get('\Lmc\Rbac\Service\AuthorizationServiceInterface');
+
+ /** @var \Lmc\Rbac\Identity\IdentityInterface $identity */
+ if ($authorizationService->isGranted($identity, 'edit', $resource)) {
+ /** do something */
+ }
+```
+
+Dynanmic assertions are further discussed in the [Dynamic Assertions](assertions) section.
diff --git a/docs/docs/role-providers.md b/docs/versioned_docs/version-2.2/role-providers.md
similarity index 100%
rename from docs/docs/role-providers.md
rename to docs/versioned_docs/version-2.2/role-providers.md
diff --git a/docs/versioned_sidebars/version-2.2-sidebars.json b/docs/versioned_sidebars/version-2.2-sidebars.json
new file mode 100644
index 00000000..5f41a72e
--- /dev/null
+++ b/docs/versioned_sidebars/version-2.2-sidebars.json
@@ -0,0 +1,8 @@
+{
+ "documentationSidebar": [
+ {
+ "type": "autogenerated",
+ "dirName": "."
+ }
+ ]
+}
diff --git a/docs/versions.json b/docs/versions.json
index 84b64c94..8a05aa0d 100644
--- a/docs/versions.json
+++ b/docs/versions.json
@@ -1,5 +1,6 @@
[
"current",
+ "2.2",
"2.0",
"1.4"
]
diff --git a/docs/yarn.lock b/docs/yarn.lock
index 125306eb..a4285393 100644
--- a/docs/yarn.lock
+++ b/docs/yarn.lock
@@ -2,10 +2,10 @@
# yarn lockfile v1
-"@ai-sdk/gateway@2.0.17":
- version "2.0.17"
- resolved "https://registry.yarnpkg.com/@ai-sdk/gateway/-/gateway-2.0.17.tgz#b89819798c685f7c59c589b3e31ce13b1473aa5f"
- integrity sha512-oVAG6q72KsjKlrYdLhWjRO7rcqAR8CjokAbYuyVZoCO4Uh2PH/VzZoxZav71w2ipwlXhHCNaInGYWNs889MMDA==
+"@ai-sdk/gateway@2.0.18":
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/@ai-sdk/gateway/-/gateway-2.0.18.tgz#7e81bdedddb7363af2c38d2cf7f34ac2d5e5eaa7"
+ integrity sha512-sDQcW+6ck2m0pTIHW6BPHD7S125WD3qNkx/B8sEzJp/hurocmJ5Cni0ybExg6sQMGo+fr/GWOwpHF1cmCdg5rQ==
dependencies:
"@ai-sdk/provider" "2.0.0"
"@ai-sdk/provider-utils" "3.0.18"
@@ -28,24 +28,24 @@
json-schema "^0.4.0"
"@ai-sdk/react@^2.0.30":
- version "2.0.104"
- resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-2.0.104.tgz#ae42a57c6f4ad368ad0d96f80be97f673dd25e0e"
- integrity sha512-vpRNUwOrHXSsywZuEge78/LPbYMR/3tkBnwijGpIGnORMa/SzYhuVsE+sZBFVo/v0m5K/tg+CXNNvuJrVZ/MBQ==
+ version "2.0.109"
+ resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-2.0.109.tgz#1f5dd07643bd8371015d05e9c9348110889cbb68"
+ integrity sha512-5qM8KuN7bv7E+g6BXkSAYLFjwIfMSTKOA1prjg1zEShJXJyLSc+Yqkd3EfGibm75b7nJAqJNShurDmR/IlQqFQ==
dependencies:
"@ai-sdk/provider-utils" "3.0.18"
- ai "5.0.104"
+ ai "5.0.108"
swr "^2.2.5"
throttleit "2.1.0"
-"@algolia/abtesting@1.11.0":
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.11.0.tgz#e6561f2cb17978445eb8b8aff339ee7a2f985daa"
- integrity sha512-a7oQ8dwiyoyVmzLY0FcuBqyqcNSq78qlcOtHmNBumRlHCSnXDcuoYGBGPN1F6n8JoGhviDDsIaF/oQrzTzs6Lg==
+"@algolia/abtesting@1.12.0":
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.12.0.tgz#fad11266e85f33acf1a37961f4110459491428f5"
+ integrity sha512-EfW0bfxjPs+C7ANkJDw2TATntfBKsFiy7APh+KO0pQ8A6HYa5I0NjFuCGCXWfzzzLXNZta3QUl3n5Kmm6aJo9Q==
dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
"@algolia/autocomplete-core@1.19.2":
version "1.19.2"
@@ -67,126 +67,126 @@
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz#c0b7b8dc30a5c65b70501640e62b009535e4578f"
integrity sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==
-"@algolia/client-abtesting@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.45.0.tgz#7e1984b02d58ce965bf190080b3ffa10c738ddbd"
- integrity sha512-WTW0VZA8xHMbzuQD5b3f41ovKZ0MNTIXkWfm0F2PU+XGcLxmxX15UqODzF2sWab0vSbi3URM1xLhJx+bXbd1eQ==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
-
-"@algolia/client-analytics@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.45.0.tgz#4f58d6c1c8d43afeedfd8ef7b84b49e3e7cdff14"
- integrity sha512-I3g7VtvG/QJOH3tQO7E7zWTwBfK/nIQXShFLR8RvPgWburZ626JNj332M3wHCYcaAMivN9WJG66S2JNXhm6+Xg==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
-
-"@algolia/client-common@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.45.0.tgz#c674f7f47a5f0013e3ab717929e51a6109af2dd2"
- integrity sha512-/nTqm1tLiPtbUr+8kHKyFiCOfhRfgC+JxLvOCq471gFZZOlsh6VtFRiKI60/zGmHTojFC6B0mD80PB7KeK94og==
-
-"@algolia/client-insights@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.45.0.tgz#ca7128edec95da8217da76f867b8cd2c2a05f682"
- integrity sha512-suQTx/1bRL1g/K2hRtbK3ANmbzaZCi13487sxxmqok+alBDKKw0/TI73ZiHjjFXM2NV52inwwcmW4fUR45206Q==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
-
-"@algolia/client-personalization@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.45.0.tgz#e674b76b4dd5a8e89d9f157cbc958d68fbeb1c60"
- integrity sha512-CId/dbjpzI3eoUhPU6rt/z4GrRsDesqFISEMOwrqWNSrf4FJhiUIzN42Ac+Gzg69uC0RnzRYy60K1y4Na5VSMw==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
-
-"@algolia/client-query-suggestions@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.45.0.tgz#6bad2a7eaa7e1a6ecf1a7960c2056e08ee0302b6"
- integrity sha512-tjbBKfA8fjAiFtvl9g/MpIPiD6pf3fj7rirVfh1eMIUi8ybHP4ovDzIaE216vHuRXoePQVCkMd2CokKvYq1CLw==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
-
-"@algolia/client-search@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.45.0.tgz#709f5fb2a13487fa6327b31306654a2c694c0fe9"
- integrity sha512-nxuCid+Nszs4xqwIMDw11pRJPes2c+Th1yup/+LtpjFH8QWXkr3SirNYSD3OXAeM060HgWWPLA8/Fxk+vwxQOA==
- dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+"@algolia/client-abtesting@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.46.0.tgz#488eadc7220a53f585077010fc2093d0c58dc37e"
+ integrity sha512-eG5xV8rujK4ZIHXrRshvv9O13NmU/k42Rnd3w43iKH5RaQ2zWuZO6Q7XjaoJjAFVCsJWqRbXzbYyPGrbF3wGNg==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
+
+"@algolia/client-analytics@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.46.0.tgz#5523c9a6ed2b67a9bdafc033cc323f43e5163806"
+ integrity sha512-AYh2uL8IUW9eZrbbT+wZElyb7QkkeV3US2NEKY7doqMlyPWE8lErNfkVN1NvZdVcY4/SVic5GDbeDz2ft8YIiQ==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
+
+"@algolia/client-common@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.46.0.tgz#004ad40adbdc6da7e23e4ef4d7a0ff48422af012"
+ integrity sha512-0emZTaYOeI9WzJi0TcNd2k3SxiN6DZfdWc2x2gHt855Jl9jPUOzfVTL6gTvCCrOlT4McvpDGg5nGO+9doEjjig==
+
+"@algolia/client-insights@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.46.0.tgz#4166d8e135aa38cf81ad7103edddd0d2026b586a"
+ integrity sha512-wrBJ8fE+M0TDG1As4DDmwPn2TXajrvmvAN72Qwpuv8e2JOKNohF7+JxBoF70ZLlvP1A1EiH8DBu+JpfhBbNphQ==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
+
+"@algolia/client-personalization@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.46.0.tgz#fc9f8f3e5099810770be9524ffe9fcd4ef0644e3"
+ integrity sha512-LnkeX4p0ENt0DoftDJJDzQQJig/sFQmD1eQifl/iSjhUOGUIKC/7VTeXRcKtQB78naS8njUAwpzFvxy1CDDXDQ==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
+
+"@algolia/client-query-suggestions@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.0.tgz#94952019e3d73475ce255dae4b51b9a9bfd86fb0"
+ integrity sha512-aF9tc4ex/smypXw+W3lBPB1jjKoaGHpZezTqofvDOI/oK1dR2sdTpFpK2Ru+7IRzYgwtRqHF3znmTlyoNs9dpA==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
+
+"@algolia/client-search@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.46.0.tgz#5b84fd1530d5be8300a949b428560a4bbf432c06"
+ integrity sha512-22SHEEVNjZfFWkFks3P6HilkR3rS7a6GjnCIqR22Zz4HNxdfT0FG+RE7efTcFVfLUkTTMQQybvaUcwMrHXYa7Q==
+ dependencies:
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
"@algolia/events@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950"
integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==
-"@algolia/ingestion@1.45.0":
- version "1.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.45.0.tgz#f99eb766a0cff112d65834ee1a43e08d18bc5f2a"
- integrity sha512-t+1doBzhkQTeOOjLHMlm4slmXBhvgtEGQhOmNpMPTnIgWOyZyESWdm+XD984qM4Ej1i9FRh8VttOGrdGnAjAng==
+"@algolia/ingestion@1.46.0":
+ version "1.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.46.0.tgz#aeb7385e342f0ae8e030c4e69d6d0216f9e005e9"
+ integrity sha512-2LT0/Z+/sFwEpZLH6V17WSZ81JX2uPjgvv5eNlxgU7rPyup4NXXfuMbtCJ+6uc4RO/LQpEJd3Li59ke3wtyAsA==
dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
-"@algolia/monitoring@1.45.0":
- version "1.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.45.0.tgz#09e7320973741f829badb5fa47c54cbc512bb0bc"
- integrity sha512-IaX3ZX1A/0wlgWZue+1BNWlq5xtJgsRo7uUk/aSiYD7lPbJ7dFuZ+yTLFLKgbl4O0QcyHTj1/mSBj9ryF1Lizg==
+"@algolia/monitoring@1.46.0":
+ version "1.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.46.0.tgz#98feadf8a029ec7d43921bea15415647012dbcc6"
+ integrity sha512-uivZ9wSWZ8mz2ZU0dgDvQwvVZV8XBv6lYBXf8UtkQF3u7WeTqBPeU8ZoeTyLpf0jAXCYOvc1mAVmK0xPLuEwOQ==
dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
-"@algolia/recommend@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.45.0.tgz#06dc022d85f8a0b6a93dd70c690a236d4ee745a3"
- integrity sha512-1jeMLoOhkgezCCPsOqkScwYzAAc1Jr5T2hisZl0s32D94ZV7d1OHozBukgOjf8Dw+6Hgi6j52jlAdUWTtkX9Mg==
+"@algolia/recommend@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.46.0.tgz#9b2fec2f9c0e74073ad9324330b8e3571aadf919"
+ integrity sha512-O2BB8DuySuddgOAbhyH4jsGbL+KyDGpzJRtkDZkv091OMomqIA78emhhMhX9d/nIRrzS1wNLWB/ix7Hb2eV5rg==
dependencies:
- "@algolia/client-common" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+ "@algolia/client-common" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
-"@algolia/requester-browser-xhr@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.45.0.tgz#0cb197014e2344a7f58aef245c10831597d23fdd"
- integrity sha512-46FIoUkQ9N7wq4/YkHS5/W9Yjm4Ab+q5kfbahdyMpkBPJ7IBlwuNEGnWUZIQ6JfUZuJVojRujPRHMihX4awUMg==
+"@algolia/requester-browser-xhr@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.0.tgz#099d980fe5b699b5f0d1ff6dfbd28fd76af43861"
+ integrity sha512-eW6xyHCyYrJD0Kjk9Mz33gQ40LfWiEA51JJTVfJy3yeoRSw/NXhAL81Pljpa0qslTs6+LO/5DYPZddct6HvISQ==
dependencies:
- "@algolia/client-common" "5.45.0"
+ "@algolia/client-common" "5.46.0"
-"@algolia/requester-fetch@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.45.0.tgz#df040b30f67e70b074e7a740874befd191bb6067"
- integrity sha512-XFTSAtCwy4HdBhSReN2rhSyH/nZOM3q3qe5ERG2FLbYId62heIlJBGVyAPRbltRwNlotlydbvSJ+SQ0ruWC2cw==
+"@algolia/requester-fetch@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.46.0.tgz#3262bc1670fa8f47ad851c65573709f589e3fb1c"
+ integrity sha512-Vn2+TukMGHy4PIxmdvP667tN/MhS7MPT8EEvEhS6JyFLPx3weLcxSa1F9gVvrfHWCUJhLWoMVJVB2PT8YfRGcw==
dependencies:
- "@algolia/client-common" "5.45.0"
+ "@algolia/client-common" "5.46.0"
-"@algolia/requester-node-http@5.45.0":
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.45.0.tgz#d96196d538d3ad5c25e3e21b469e92b19b442153"
- integrity sha512-8mTg6lHx5i44raCU52APsu0EqMsdm4+7Hch/e4ZsYZw0hzwkuaMFh826ngnkYf9XOl58nHoou63aZ874m8AbpQ==
+"@algolia/requester-node-http@5.46.0":
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.46.0.tgz#45b8a76e7391f9d11a7fce04b1e03dbef29af7f2"
+ integrity sha512-xaqXyna5yBZ+r1SJ9my/DM6vfTqJg9FJgVydRJ0lnO+D5NhqGW/qaRG/iBGKr/d4fho34el6WakV7BqJvrl/HQ==
dependencies:
- "@algolia/client-common" "5.45.0"
+ "@algolia/client-common" "5.46.0"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1":
version "7.27.1"
@@ -1371,6 +1371,11 @@
"@csstools/postcss-progressive-custom-properties" "^4.2.1"
"@csstools/utilities" "^2.0.0"
+"@csstools/postcss-position-area-property@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-position-area-property/-/postcss-position-area-property-1.0.0.tgz#41f0cbc737a81a42890d5ec035fa26a45f4f4ad4"
+ integrity sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==
+
"@csstools/postcss-progressive-custom-properties@^4.2.1":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.2.1.tgz#c39780b9ff0d554efb842b6bd75276aa6f1705db"
@@ -1423,6 +1428,14 @@
"@csstools/css-parser-algorithms" "^3.0.5"
"@csstools/css-tokenizer" "^3.0.4"
+"@csstools/postcss-system-ui-font-family@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-system-ui-font-family/-/postcss-system-ui-font-family-1.0.0.tgz#bd65b79078debf6f67b318dc9b71a8f9fa16f8c8"
+ integrity sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==
+ dependencies:
+ "@csstools/css-parser-algorithms" "^3.0.5"
+ "@csstools/css-tokenizer" "^3.0.4"
+
"@csstools/postcss-text-decoration-shorthand@^4.0.3":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.3.tgz#fae1b70f07d1b7beb4c841c86d69e41ecc6f743c"
@@ -2422,13 +2435,13 @@
"@types/send" "*"
"@types/express@*":
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.5.tgz#3ba069177caa34ab96585ca23b3984d752300cdc"
- integrity sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.6.tgz#2d724b2c990dcb8c8444063f3580a903f6d500cc"
+ integrity sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "^5.0.0"
- "@types/serve-static" "^1"
+ "@types/serve-static" "^2"
"@types/express@^4.17.21":
version "4.17.25"
@@ -2533,9 +2546,9 @@
"@types/node" "*"
"@types/node@*":
- version "24.10.1"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01"
- integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==
+ version "25.0.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.0.tgz#c0e0022c3c7b41635c49322e6b3a0279fffa7d62"
+ integrity sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==
dependencies:
undici-types "~7.16.0"
@@ -2635,6 +2648,14 @@
"@types/node" "*"
"@types/send" "<1"
+"@types/serve-static@^2":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-2.2.0.tgz#d4a447503ead0d1671132d1ab6bd58b805d8de6a"
+ integrity sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==
+ dependencies:
+ "@types/http-errors" "*"
+ "@types/node" "*"
+
"@types/sockjs@^0.3.36":
version "0.3.36"
resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535"
@@ -2855,12 +2876,12 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
-ai@5.0.104, ai@^5.0.30:
- version "5.0.104"
- resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.104.tgz#b2a1bf7fb2bd50e1f63c945353a28949595a29b7"
- integrity sha512-MZOkL9++nY5PfkpWKBR3Rv+Oygxpb9S16ctv8h91GvrSif7UnNEdPMVZe3bUyMd2djxf0AtBk/csBixP0WwWZQ==
+ai@5.0.108, ai@^5.0.30:
+ version "5.0.108"
+ resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.108.tgz#b1b6e66b705baabcf98370336b03ebaacbf1874f"
+ integrity sha512-Jex3Lb7V41NNpuqJHKgrwoU6BCLHdI1Pg4qb4GJH4jRIDRXUBySJErHjyN4oTCwbiYCeb/8II9EnqSRPq9EifA==
dependencies:
- "@ai-sdk/gateway" "2.0.17"
+ "@ai-sdk/gateway" "2.0.18"
"@ai-sdk/provider" "2.0.0"
"@ai-sdk/provider-utils" "3.0.18"
"@opentelemetry/api" "1.9.0"
@@ -2912,24 +2933,24 @@ algoliasearch-helper@^3.26.0:
"@algolia/events" "^4.0.1"
algoliasearch@^5.28.0, algoliasearch@^5.37.0:
- version "5.45.0"
- resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.45.0.tgz#90abba15b26d6722360a97c1e1931bc920f9c555"
- integrity sha512-wrj4FGr14heLOYkBKV3Fbq5ZBGuIFeDJkTilYq/G+hH1CSlQBtYvG2X1j67flwv0fUeQJwnWxxRIunSemAZirA==
- dependencies:
- "@algolia/abtesting" "1.11.0"
- "@algolia/client-abtesting" "5.45.0"
- "@algolia/client-analytics" "5.45.0"
- "@algolia/client-common" "5.45.0"
- "@algolia/client-insights" "5.45.0"
- "@algolia/client-personalization" "5.45.0"
- "@algolia/client-query-suggestions" "5.45.0"
- "@algolia/client-search" "5.45.0"
- "@algolia/ingestion" "1.45.0"
- "@algolia/monitoring" "1.45.0"
- "@algolia/recommend" "5.45.0"
- "@algolia/requester-browser-xhr" "5.45.0"
- "@algolia/requester-fetch" "5.45.0"
- "@algolia/requester-node-http" "5.45.0"
+ version "5.46.0"
+ resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.46.0.tgz#109e8976a4aee611112306de735c8c205e7e6bf8"
+ integrity sha512-7ML6fa2K93FIfifG3GMWhDEwT5qQzPTmoHKCTvhzGEwdbQ4n0yYUWZlLYT75WllTGJCJtNUI0C1ybN4BCegqvg==
+ dependencies:
+ "@algolia/abtesting" "1.12.0"
+ "@algolia/client-abtesting" "5.46.0"
+ "@algolia/client-analytics" "5.46.0"
+ "@algolia/client-common" "5.46.0"
+ "@algolia/client-insights" "5.46.0"
+ "@algolia/client-personalization" "5.46.0"
+ "@algolia/client-query-suggestions" "5.46.0"
+ "@algolia/client-search" "5.46.0"
+ "@algolia/ingestion" "1.46.0"
+ "@algolia/monitoring" "1.46.0"
+ "@algolia/recommend" "5.46.0"
+ "@algolia/requester-browser-xhr" "5.46.0"
+ "@algolia/requester-fetch" "5.46.0"
+ "@algolia/requester-node-http" "5.46.0"
ansi-align@^3.0.1:
version "3.0.1"
@@ -3012,7 +3033,7 @@ astring@^1.8.0:
resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef"
integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==
-autoprefixer@^10.4.19, autoprefixer@^10.4.21:
+autoprefixer@^10.4.19, autoprefixer@^10.4.22:
version "10.4.22"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.22.tgz#90b27ab55ec0cf0684210d1f056f7d65dac55f16"
integrity sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==
@@ -3073,10 +3094,10 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-baseline-browser-mapping@^2.8.25:
- version "2.8.32"
- resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz#5de72358cf363ac41e7d642af239f6ac5ed1270a"
- integrity sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==
+baseline-browser-mapping@^2.9.0:
+ version "2.9.6"
+ resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz#82de0f7ee5860df86d60daf0d9524ae7227eeee7"
+ integrity sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==
batch@0.6.1:
version "0.6.1"
@@ -3093,23 +3114,23 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
-body-parser@1.20.3:
- version "1.20.3"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
- integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
+body-parser@~1.20.3:
+ version "1.20.4"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.4.tgz#f8e20f4d06ca8a50a71ed329c15dccad1cdc547f"
+ integrity sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==
dependencies:
- bytes "3.1.2"
+ bytes "~3.1.2"
content-type "~1.0.5"
debug "2.6.9"
depd "2.0.0"
- destroy "1.2.0"
- http-errors "2.0.0"
- iconv-lite "0.4.24"
- on-finished "2.4.1"
- qs "6.13.0"
- raw-body "2.5.2"
+ destroy "~1.2.0"
+ http-errors "~2.0.1"
+ iconv-lite "~0.4.24"
+ on-finished "~2.4.1"
+ qs "~6.14.0"
+ raw-body "~2.5.3"
type-is "~1.6.18"
- unpipe "1.0.0"
+ unpipe "~1.0.0"
bonjour-service@^1.2.1:
version "1.3.0"
@@ -3167,16 +3188,16 @@ braces@^3.0.3, braces@~3.0.2:
dependencies:
fill-range "^7.1.1"
-browserslist@^4.0.0, browserslist@^4.23.0, browserslist@^4.24.0, browserslist@^4.26.0, browserslist@^4.26.3, browserslist@^4.27.0, browserslist@^4.28.0:
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.0.tgz#9cefece0a386a17a3cd3d22ebf67b9deca1b5929"
- integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==
+browserslist@^4.0.0, browserslist@^4.23.0, browserslist@^4.24.0, browserslist@^4.26.3, browserslist@^4.27.0, browserslist@^4.28.0:
+ version "4.28.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95"
+ integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==
dependencies:
- baseline-browser-mapping "^2.8.25"
- caniuse-lite "^1.0.30001754"
- electron-to-chromium "^1.5.249"
+ baseline-browser-mapping "^2.9.0"
+ caniuse-lite "^1.0.30001759"
+ electron-to-chromium "^1.5.263"
node-releases "^2.0.27"
- update-browserslist-db "^1.1.4"
+ update-browserslist-db "^1.2.0"
buffer-from@^1.0.0:
version "1.1.2"
@@ -3195,7 +3216,7 @@ bytes@3.0.0:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
-bytes@3.1.2:
+bytes@3.1.2, bytes@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
@@ -3277,10 +3298,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001754:
- version "1.0.30001757"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz#a46ff91449c69522a462996c6aac4ef95d7ccc5e"
- integrity sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001754, caniuse-lite@^1.0.30001759:
+ version "1.0.30001760"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz#bdd1960fafedf8d5f04ff16e81460506ff9b798f"
+ integrity sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==
ccount@^2.0.0:
version "2.0.1"
@@ -3541,7 +3562,7 @@ content-disposition@0.5.2:
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==
-content-disposition@0.5.4:
+content-disposition@~0.5.4:
version "0.5.4"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
@@ -3558,15 +3579,15 @@ convert-source-map@^2.0.0:
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
-cookie-signature@1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
- integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
+cookie-signature@~1.0.6:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454"
+ integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==
-cookie@0.7.1:
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
- integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==
+cookie@~0.7.1:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7"
+ integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
copy-webpack-plugin@^11.0.0:
version "11.0.0"
@@ -3723,10 +3744,10 @@ css-what@^6.0.1, css-what@^6.1.0:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.2.2.tgz#cdcc8f9b6977719fdfbd1de7aec24abf756b9dea"
integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==
-cssdb@^8.4.2:
- version "8.4.2"
- resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.4.2.tgz#1a367ab1904c97af0bb2c7ae179764deae7b078b"
- integrity sha512-PzjkRkRUS+IHDJohtxkIczlxPPZqRo0nXplsYXOMBRPjcVRjj1W4DfvRgshUYTVuUigU7ptVYkFJQ7abUB0nyg==
+cssdb@^8.5.2:
+ version "8.5.2"
+ resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.5.2.tgz#8a8c16c43785e32749453e589f18debcd936c7d1"
+ integrity sha512-Pmoj9RmD8RIoIzA2EQWO4D4RMeDts0tgAH0VXdlNdxjuBGI3a9wMOIcUwaPNmD4r2qtIa06gqkIf7sECl+cBCg==
cssesc@^3.0.0:
version "3.0.0"
@@ -3896,7 +3917,7 @@ define-properties@^1.2.1:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
-depd@2.0.0:
+depd@2.0.0, depd@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
@@ -3911,7 +3932,7 @@ dequal@^2.0.0, dequal@^2.0.3:
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
-destroy@1.2.0:
+destroy@1.2.0, destroy@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
@@ -4051,10 +4072,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
-electron-to-chromium@^1.5.249:
- version "1.5.262"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz#c31eed591c6628908451c9ca0f0758ed514aa003"
- integrity sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==
+electron-to-chromium@^1.5.263:
+ version "1.5.267"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7"
+ integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==
emoji-regex@^8.0.0:
version "8.0.0"
@@ -4338,38 +4359,38 @@ execa@5.1.1:
strip-final-newline "^2.0.0"
express@^4.21.2:
- version "4.21.2"
- resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32"
- integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==
+ version "4.22.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.22.1.tgz#1de23a09745a4fffdb39247b344bb5eaff382069"
+ integrity sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
- body-parser "1.20.3"
- content-disposition "0.5.4"
+ body-parser "~1.20.3"
+ content-disposition "~0.5.4"
content-type "~1.0.4"
- cookie "0.7.1"
- cookie-signature "1.0.6"
+ cookie "~0.7.1"
+ cookie-signature "~1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~2.0.0"
escape-html "~1.0.3"
etag "~1.8.1"
- finalhandler "1.3.1"
- fresh "0.5.2"
- http-errors "2.0.0"
+ finalhandler "~1.3.1"
+ fresh "~0.5.2"
+ http-errors "~2.0.0"
merge-descriptors "1.0.3"
methods "~1.1.2"
- on-finished "2.4.1"
+ on-finished "~2.4.1"
parseurl "~1.3.3"
- path-to-regexp "0.1.12"
+ path-to-regexp "~0.1.12"
proxy-addr "~2.0.7"
- qs "6.13.0"
+ qs "~6.14.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
- send "0.19.0"
- serve-static "1.16.2"
+ send "~0.19.0"
+ serve-static "~1.16.2"
setprototypeof "1.2.0"
- statuses "2.0.1"
+ statuses "~2.0.1"
type-is "~1.6.18"
utils-merge "1.0.1"
vary "~1.1.2"
@@ -4462,17 +4483,17 @@ fill-range@^7.1.1:
dependencies:
to-regex-range "^5.0.1"
-finalhandler@1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
- integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
+finalhandler@~1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.2.tgz#1ebc2228fc7673aac4a472c310cc05b77d852b88"
+ integrity sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==
dependencies:
debug "2.6.9"
encodeurl "~2.0.0"
escape-html "~1.0.3"
- on-finished "2.4.1"
+ on-finished "~2.4.1"
parseurl "~1.3.3"
- statuses "2.0.1"
+ statuses "~2.0.2"
unpipe "~1.0.0"
find-cache-dir@^4.0.0:
@@ -4521,7 +4542,7 @@ fraction.js@^5.3.4:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-5.3.4.tgz#8c0fcc6a9908262df4ed197427bdeef563e0699a"
integrity sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==
-fresh@0.5.2:
+fresh@0.5.2, fresh@~0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
@@ -4810,14 +4831,14 @@ hast-util-to-jsx-runtime@^2.0.0:
vfile-message "^4.0.0"
hast-util-to-parse5@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz#477cd42d278d4f036bc2ea58586130f6f39ee6ed"
- integrity sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz#95aa391cc0514b4951418d01c883d1038af42f5d"
+ integrity sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==
dependencies:
"@types/hast" "^3.0.0"
comma-separated-tokens "^2.0.0"
devlop "^1.0.0"
- property-information "^6.0.0"
+ property-information "^7.0.0"
space-separated-tokens "^2.0.0"
web-namespaces "^2.0.0"
zwitch "^2.0.0"
@@ -4977,6 +4998,17 @@ http-errors@~1.6.2:
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
+http-errors@~2.0.0, http-errors@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b"
+ integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==
+ dependencies:
+ depd "~2.0.0"
+ inherits "~2.0.4"
+ setprototypeof "~1.2.0"
+ statuses "~2.0.2"
+ toidentifier "~1.0.1"
+
http-parser-js@>=0.5.1:
version "0.5.10"
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.10.tgz#b3277bd6d7ed5588e20ea73bf724fcbe44609075"
@@ -5020,7 +5052,7 @@ hyperdyperid@^1.2.0:
resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b"
integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==
-iconv-lite@0.4.24:
+iconv-lite@~0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -5075,7 +5107,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
-inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
+inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3, inherits@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -6398,9 +6430,9 @@ node-emoji@^2.1.0:
skin-tone "^2.0.0"
node-forge@^1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.2.tgz#d0d2659a26eef778bf84d73e7f55c08144ee7750"
- integrity sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.3.tgz#0ad80f6333b3a0045e827ac20b7f735f93716751"
+ integrity sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==
node-releases@^2.0.27:
version "2.0.27"
@@ -6481,7 +6513,7 @@ obuf@^1.0.0, obuf@^1.1.2:
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
-on-finished@2.4.1, on-finished@^2.4.1:
+on-finished@2.4.1, on-finished@^2.4.1, on-finished@~2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
@@ -6680,11 +6712,6 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-path-to-regexp@0.1.12:
- version "0.1.12"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
- integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
-
path-to-regexp@3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz#f7f31d32e8518c2660862b644414b6d5c63a611b"
@@ -6697,6 +6724,11 @@ path-to-regexp@^1.7.0:
dependencies:
isarray "0.0.1"
+path-to-regexp@~0.1.12:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
+ integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
+
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -7109,9 +7141,9 @@ postcss-place@^10.0.0:
postcss-value-parser "^4.2.0"
postcss-preset-env@^10.2.1:
- version "10.4.0"
- resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.4.0.tgz#fa6167a307f337b2bcdd1d125604ff97cdeb5142"
- integrity sha512-2kqpOthQ6JhxqQq1FSAAZGe9COQv75Aw8WbsOvQVNJ2nSevc9Yx/IKZGuZ7XJ+iOTtVon7LfO7ELRzg8AZ+sdw==
+ version "10.5.0"
+ resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.5.0.tgz#fa9af5b635c053f6d68f91132eab3a0b5c4e53c8"
+ integrity sha512-xgxFQPAPxeWmsgy8cR7GM1PGAL/smA5E9qU7K//D4vucS01es3M0fDujhDJn3kY8Ip7/vVYcecbe1yY+vBo3qQ==
dependencies:
"@csstools/postcss-alpha-function" "^1.0.1"
"@csstools/postcss-cascade-layers" "^5.0.2"
@@ -7140,21 +7172,23 @@ postcss-preset-env@^10.2.1:
"@csstools/postcss-nested-calc" "^4.0.0"
"@csstools/postcss-normalize-display-values" "^4.0.0"
"@csstools/postcss-oklab-function" "^4.0.12"
+ "@csstools/postcss-position-area-property" "^1.0.0"
"@csstools/postcss-progressive-custom-properties" "^4.2.1"
"@csstools/postcss-random-function" "^2.0.1"
"@csstools/postcss-relative-color-syntax" "^3.0.12"
"@csstools/postcss-scope-pseudo-class" "^4.0.1"
"@csstools/postcss-sign-functions" "^1.1.4"
"@csstools/postcss-stepped-value-functions" "^4.0.9"
+ "@csstools/postcss-system-ui-font-family" "^1.0.0"
"@csstools/postcss-text-decoration-shorthand" "^4.0.3"
"@csstools/postcss-trigonometric-functions" "^4.0.9"
"@csstools/postcss-unset-value" "^4.0.0"
- autoprefixer "^10.4.21"
- browserslist "^4.26.0"
+ autoprefixer "^10.4.22"
+ browserslist "^4.28.0"
css-blank-pseudo "^7.0.1"
css-has-pseudo "^7.0.3"
css-prefers-color-scheme "^10.0.0"
- cssdb "^8.4.2"
+ cssdb "^8.5.2"
postcss-attribute-case-insensitive "^7.0.1"
postcss-clamp "^4.1.0"
postcss-color-functional-notation "^7.0.12"
@@ -7327,11 +7361,6 @@ prop-types@^15.6.2, prop-types@^15.7.2:
object-assign "^4.1.1"
react-is "^16.13.1"
-property-information@^6.0.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec"
- integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==
-
property-information@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d"
@@ -7362,12 +7391,12 @@ pupa@^3.1.0:
dependencies:
escape-goat "^4.0.0"
-qs@6.13.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
- integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
+qs@~6.14.0:
+ version "6.14.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930"
+ integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==
dependencies:
- side-channel "^1.0.6"
+ side-channel "^1.1.0"
queue-microtask@^1.2.2:
version "1.2.3"
@@ -7396,15 +7425,15 @@ range-parser@^1.2.1, range-parser@~1.2.1:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-raw-body@2.5.2:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
- integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
+raw-body@~2.5.3:
+ version "2.5.3"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.3.tgz#11c6650ee770a7de1b494f197927de0c923822e2"
+ integrity sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==
dependencies:
- bytes "3.1.2"
- http-errors "2.0.0"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
+ bytes "~3.1.2"
+ http-errors "~2.0.1"
+ iconv-lite "~0.4.24"
+ unpipe "~1.0.0"
rc@1.2.8:
version "1.2.8"
@@ -7417,9 +7446,9 @@ rc@1.2.8:
strip-json-comments "~2.0.1"
react-dom@^19.0.0:
- version "19.2.0"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.0.tgz#00ed1e959c365e9a9d48f8918377465466ec3af8"
- integrity sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==
+ version "19.2.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.1.tgz#ce3527560bda4f997e47d10dab754825b3061f59"
+ integrity sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==
dependencies:
scheduler "^0.27.0"
@@ -7499,9 +7528,9 @@ react-router@5.3.4, react-router@^5.3.4:
tiny-warning "^1.0.0"
react@^19.0.0:
- version "19.2.0"
- resolved "https://registry.yarnpkg.com/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5"
- integrity sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==
+ version "19.2.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-19.2.1.tgz#8600fa205e58e2e807f6ef431c9f6492591a2700"
+ integrity sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==
readable-stream@^2.0.1:
version "2.3.8"
@@ -7926,6 +7955,25 @@ send@0.19.0:
range-parser "~1.2.1"
statuses "2.0.1"
+send@~0.19.0:
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.19.1.tgz#1c2563b2ee4fe510b806b21ec46f355005a369f9"
+ integrity sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~2.0.0"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
serialize-javascript@^6.0.0, serialize-javascript@^6.0.1, serialize-javascript@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
@@ -7959,7 +8007,7 @@ serve-index@^1.9.1:
mime-types "~2.1.17"
parseurl "~1.3.2"
-serve-static@1.16.2:
+serve-static@~1.16.2:
version "1.16.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
@@ -7986,7 +8034,7 @@ setprototypeof@1.1.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
-setprototypeof@1.2.0:
+setprototypeof@1.2.0, setprototypeof@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
@@ -8049,7 +8097,7 @@ side-channel-weakmap@^1.0.2:
object-inspect "^1.13.3"
side-channel-map "^1.0.1"
-side-channel@^1.0.6:
+side-channel@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
@@ -8199,6 +8247,11 @@ statuses@2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+statuses@~2.0.1, statuses@~2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382"
+ integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==
+
std-env@^3.7.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b"
@@ -8360,9 +8413,9 @@ tapable@^2.0.0, tapable@^2.2.0, tapable@^2.2.1, tapable@^2.3.0:
integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==
terser-webpack-plugin@^5.3.11, terser-webpack-plugin@^5.3.9:
- version "5.3.14"
- resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06"
- integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==
+ version "5.3.15"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.15.tgz#0a26860b765eaffa8e840170aabc5b3a3f6f6bb9"
+ integrity sha512-PGkOdpRFK+rb1TzVz+msVhw4YMRT9txLF4kRqvJhGhCM324xuR3REBSHALN+l+sAhKUmz0aotnjp5D+P83mLhQ==
dependencies:
"@jridgewell/trace-mapping" "^0.3.25"
jest-worker "^27.4.5"
@@ -8417,7 +8470,7 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
-toidentifier@1.0.1:
+toidentifier@1.0.1, toidentifier@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
@@ -8580,15 +8633,15 @@ universalify@^2.0.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
-unpipe@1.0.0, unpipe@~1.0.0:
+unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
-update-browserslist-db@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a"
- integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==
+update-browserslist-db@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz#cfb4358afa08b3d5731a2ecd95eebf4ddef8033e"
+ integrity sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==
dependencies:
escalade "^3.2.0"
picocolors "^1.1.1"