diff --git a/.gitignore b/.gitignore index 8be35952c..3c71334bd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ dist .pnpm-debug.log* .netlify .turbo +.retype # Mac .DS_Store diff --git a/docs/getting-started/create-host.md b/docs/getting-started/create-host.md index 27a89ca6e..7a76a5381 100644 --- a/docs/getting-started/create-host.md +++ b/docs/getting-started/create-host.md @@ -23,17 +23,17 @@ Create a new application (we'll refer to ours as `host`), then open a terminal a +++ pnpm ```bash pnpm add -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript @types/react @types/react-dom -pnpm add @squide/firefly react react-dom react-router-dom react-error-boundary +pnpm add @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ yarn ```bash yarn add -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript @types/react @types/react-dom -yarn add @squide/firefly react react-dom react-router-dom react-error-boundary +yarn add @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ npm ```bash npm install -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript @types/react @types/react-dom -npm install @squide/firefly react react-dom react-router-dom react-error-boundary +npm install @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ @@ -53,7 +53,6 @@ host ├──── App.tsx ├──── RootLayout.tsx ├──── HomePage.tsx -├──── NotFoundPage.tsx ├──── bootstrap.tsx ├──── index.ts ├──── register.tsx @@ -126,14 +125,20 @@ import { RouterProvider, createBrowserRouter } from "react-router-dom"; export function App() { return ( - Loading...} - errorElement={
An error occured!
} - waitForMsw={false} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }} ); } @@ -154,7 +159,7 @@ import { type RenderSectionFunction } from "@squide/firefly"; -const renderItem: RenderItemFunction = (item, index, level) => { +const renderItem: RenderItemFunction = (item, key) => { // To keep thing simple, this sample doesn't support nested navigation items. // For an example including support for nested navigation items, have a look at // https://gsoft-inc.github.io/wl-squide/reference/routing/userenderednavigationitems/ @@ -165,7 +170,7 @@ const renderItem: RenderItemFunction = (item, index, level) => { const { label, linkProps, additionalProps } = item; return ( -
  • +
  • {label} @@ -173,9 +178,9 @@ const renderItem: RenderItemFunction = (item, index, level) => { ); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
      +
        {elements}
      ); @@ -227,7 +232,7 @@ export const registerHost: ModuleRegisterFunction = runtime => { }; ``` -And an [hoisted route](../reference/runtime/runtime-class.md#register-an-hoisted-route) to render the `RootLayout` and the [ManagedRoutes](../reference/routing/ManagedRoutes.md) placeholder: +And an [hoisted route](../reference/runtime/runtime-class.md#register-an-hoisted-route) to render the `RootLayout` and the [ManagedRoutes](../reference/routing/managedRoutes.md) placeholder: ```tsx !#8,12,15 host/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; @@ -255,7 +260,7 @@ export const registerHost: ModuleRegisterFunction = runtime => { ``` !!!info -The [ManagedRoutes](../reference/routing/ManagedRoutes.md) placeholder indicates where routes that are neither hoisted or nested with a [parentPath](../reference/runtime/runtime-class.md#register-nested-navigation-items) or [parentName](../reference/runtime/runtime-class.md#register-a-named-route) option will be rendered. In this example, the homepage route is considered as a managed route and will be rendered under the `ManagedRoutes` placeholder. +The [ManagedRoutes](../reference/routing/managedRoutes.md) placeholder indicates where routes that are neither hoisted or nested with a [parentPath](../reference/runtime/runtime-class.md#register-nested-navigation-items) or [parentName](../reference/runtime/runtime-class.md#register-a-named-route) option will be rendered. In this example, the homepage route is considered as a managed route and will be rendered under the `ManagedRoutes` placeholder. !!! Finally, update the bootstrapping code to [register](../reference/registration/registerLocalModules.md) the newly created local module: @@ -305,7 +310,7 @@ export function NotFoundPage() { Then, register the newly created component as the `*` route: -```tsx !#19-24 host/src/register.tsx +```tsx !#8,19-24 host/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; import { HomePage } from "./HomePage.tsx"; import { NotFoundPage } from "./NotFoundPage.tsx"; @@ -313,7 +318,7 @@ import { RootLayout } from "./RootLayout.tsx"; export const registerHost: ModuleRegisterFunction = runtime => { runtime.registerRoute({ - // Pathless route to declare a root layout. + $name: "root-layout", element: , children: [ // Placeholder to indicate where managed routes (routes that are not hoisted or nested) @@ -328,7 +333,7 @@ export const registerHost: ModuleRegisterFunction = runtime => { path: "*", element: }, { - hoist: true + parentName: "root-layout" }); runtime.registerRoute({ @@ -462,8 +467,9 @@ If you are experiencing issues with this guide: - `[squide] 1/4 Registering local module.` - `[squide] 1/4 Local module registration completed.` - `[squide] Found 1 remote module to register.` - - `[squide] 1/1 Loading module "./register" from container "remote1" of remote "http://localhost:8081/remoteEntry.js".` - - `[squide] 1/1 Container "remote1" of remote "http://localhost:8081/remoteEntry.js" registration completed.` + - `[squide] 1/1 Loading module "register" of "remote1".` + - `[squide] 1/1 Registering module "register" of remote "remote1".` + - `[squide] 1/1 The registration of the remote "remote1" is completed.` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/basic/host). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/getting-started/create-local-module.md b/docs/getting-started/create-local-module.md index 94853fdbb..14b9eebad 100644 --- a/docs/getting-started/create-local-module.md +++ b/docs/getting-started/create-local-module.md @@ -15,7 +15,7 @@ npx degit https://github.com/gsoft-inc/wl-squide/templates/getting-started Local modules are regular modules that are part of the **host application build**. They are independent modules that expose a `registration` function to the host application's bootstrapping code. A local module can be a standalone package, a sibling project (in a monorepo setup), or even a local folder within the host application. -Local modules have many uses but are especially useful when **migrating** from a **monolithic application** to a distributed application or when **launching** a **new product** with an unrefined business domain. +Local modules have many uses but are especially useful when **launching** a **new product** with an unrefined business domain or **migrating** from a **monolithic application** to a distributed application. Let's add a local module to demonstrate how it's done! @@ -26,17 +26,17 @@ Create a new application (we'll refer to ours as `local-module`), then open a te +++ pnpm ```bash pnpm add -D @workleap/tsup-configs tsup typescript @types/react @types/react-dom -pnpm add @squide/firefly react react-dom react-router-dom react-error-boundary +pnpm add @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ yarn ```bash yarn add -D @workleap/tsup-configs tsup typescript @types/react @types/react-dom -yarn add @squide/firefly react @squide/firefly react-dom react-router-dom react-error-boundary +yarn add @squide/firefly react @squide/firefly react-dom react-router-dom @tanstack/react-query ``` +++ npm ```bash npm add -D @workleap/tsup-configs tsup typescript @types/react @types/react-dom -npm install @squide/firefly react react-dom react-router-dom react-error-boundary +npm install @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ @@ -86,7 +86,7 @@ Finally, configure the package to be shareable by adding the `name`, `version`, Next, register the local module routes and navigation items with [registerRoute](/reference/runtime/runtime-class.md#register-routes) and [registerNavigationItem](/reference/runtime/runtime-class.md#register-navigation-items) functions: -```tsx !#5-8,10-13 local-module/src/register.tsx +```tsx !#5-8,10-14 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Page } from "./Page.tsx"; @@ -97,6 +97,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "local-page", $label: "Local/Page", to: "/local/page" }); @@ -125,6 +126,10 @@ Go back to the `host` application and add a dependency to the `@getting-started/ } ``` +!!!info +If your project is set up as a monorepo, use `workspace:*` for the version instead of `0.0.1`. +!!! + Then, register the local module with the [registerLocalModules](/reference/registration/registerLocalModules.md) function: ```tsx !#3,21 host/src/bootstrap.tsx @@ -212,7 +217,7 @@ Start the `host`, `remote-module` and `local-module` applications in development If you are experiencing issues with this guide: - Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs and error messages if something went wrong: - - `[squide] The following route has been registered. Newly registered item: ...` - - `[squide] The following navigation item has been registered to the "root" menu for a total of 2 items. Newly registered item: ...` + - `[squide] The following route has been registered.` + - `[squide] The following static navigation item has been registered to the "root" menu for a total of 2 static items.` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/basic/local-module). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/getting-started/create-remote-module.md b/docs/getting-started/create-remote-module.md index 8cfdfb45f..ddff29259 100644 --- a/docs/getting-started/create-remote-module.md +++ b/docs/getting-started/create-remote-module.md @@ -24,17 +24,17 @@ Create a new application (we'll refer to ours as `remote-module`), then open a t +++ pnpm ```bash pnpm add -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss @types/react @types/react-dom -pnpm add @squide/firefly react react-dom react-router-dom react-error-boundary +pnpm add @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ yarn ```bash yarn add -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss @types/react @types/react-dom -yarn add @squide/firefly react react-dom react-router-dom react-error-boundary +yarn add @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ npm ```bash npm install -D @workleap/swc-configs @workleap/browserslist-config @squide/firefly-webpack-configs webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss @types/react @types/react-dom -npm install @squide/firefly react react-dom react-router-dom react-error-boundary +npm install @squide/firefly react react-dom react-router-dom @tanstack/react-query ``` +++ @@ -71,7 +71,7 @@ Then, ensure that you are developing your module using [ESM syntax](https://deve Next, register the remote module routes and navigation items with the [registerRoute](/reference/runtime/runtime-class.md#register-routes) and [registerNavigationItem](/reference/runtime/runtime-class.md#register-navigation-items) functions: -```tsx !#5-8,10-13 remote-module/src/register.tsx +```tsx !#5-8,10-14 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Page } from "./Page.tsx"; @@ -82,6 +82,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "remote-page", $label: "Remote/Page", to: "/remote/page" }); @@ -185,8 +186,8 @@ Start the `host` and the `remote-module` applications in development mode using If you are experiencing issues with this guide: - Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs and error messages if something went wrong: - - `[squide] The following route has been registered. Newly registered item: ...` - - `[squide] The following navigation item has been registered to the "root" menu for a total of 2 items. Newly registered item: ...` + - `[squide] The following route has been registered.` + - `[squide] The following static navigation item has been registered to the "root" menu for a total of 2 static items.` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/basic/remote-module). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/getting-started/default.md b/docs/getting-started/default.md index 96a56a3a8..09d540046 100644 --- a/docs/getting-started/default.md +++ b/docs/getting-started/default.md @@ -4,9 +4,13 @@ icon: rocket expanded: true --- +!!!contrast +The documentation for Squide firefly v8 is available [here](https://squide-firefly-v8.netlify.app/getting-started/). +!!! + # Getting started -Welcome to Squide (yes :squid: with an **"e"**), a shell for [Workleap](https://workleap.com/) federated applications. In this getting started section, you'll find an overview of the shell and a [quick start](create-host.md) guide to create a new federated application from scratch. +Welcome to Squide (yes :squid: with an **"e"**), a shell for [Workleap](https://workleap.com/) web applications built on top of [Module Federation](https://module-federation.io/), [React Router](https://reactrouter.com) and [TanStack Query](https://tanstack.com/query/latest). In this getting started section, you'll find an overview of the shell and a [quick start](create-host.md) guide to create a new application from scratch. -## Why a shell? +## Why Squide? + +We originally built this shell to facilitate the adoption of federated applications at Workleap by **enforcing patterns** that we believe are essential for teams to successfully implement a distributed frontend architecture. + +While Squide remains a great shell for federated applications, as we experimented with new products, we discovered that Squide also **offers** significant **value** for **non-federated** web applications: + +- With the power of [local modules](../reference/registration/registerLocalModules.md) and the [Runtime API](../reference/runtime/runtime-class.md), Squide addresses a long-lasting challenge at Workleap: _How can we effectively enforce the boundaries of a business subdomain in the frontend?_ Squide's modular design naturally upholds these boundaries. -We have built this shell to facilitate the adoption of federated applications at Workleap by **enforcing patterns** that we believe will help feature teams successfully implement a distributed architecture. +- With Squide, teams can confidently start new products with a simple **monorepo** architecture, knowing that as new members are onboarded, their development **velocity** can **scale** seamlessly by gradually migrating local modules to remote modules without refactoring the core application architecture. -The shell itself is a lightweight [API layer](/reference) built on top of [Module Federation](https://module-federation.io/) and [React Router](https://reactrouter.com), with the goal of maximizing the strength of both libraries while interfering as little as possible with their functionality. +For both, federated and non-federated web applications, Squide offers a lightweight [API layer](/reference) combining the strengths of industry-leading third-party libraries: ### Module Federation -We have identified **2 major challenges** with frontend federated applications: +We identified **2 major challenges** with federated applications: - How can we prevent loading the same large dependencies twice when switching between *modules*? - How can we offer a cohesive experience that doesn't feel *modular*? @@ -48,35 +58,43 @@ With Module Federation, we hope to develop federated applications that provide t ### React Router -React Router [nested routes](https://reactrouter.com/en/main/start/tutorial#nested-routes) feature is ideal for federated applications as it enables highly **composable** and **decoupled** UI. For a more in-depth explanation, refer to this [article](https://www.infoxicator.com/why-react-router-is-excellent-for-micro-frontends). +React Router [nested routes](https://reactrouter.com/en/main/start/tutorial#nested-routes) feature is ideal for modular applications as it enables highly **composable** and **decoupled** UI. For a more in-depth explanation, refer to this [article](https://www.infoxicator.com/why-react-router-is-excellent-for-micro-frontends). + +### TanStack Query + +TanStack Query simplifies server state management with an innovative approach to data fetching, caching, and synchronization, enhancing both the perceived performance and the user experience. + +TanStack Query is particularly well-suited for modular applications due to its ability to **manage** server **state across** multiple **independent** React **components**. It’s an effective solution for modular applications that require **isolating data** and **state** between independent parts. ## Module registration The most distinctive aspect of this shell is the conventions it enforces for loading and registering remote modules. Here's a brief overview of the flow: -1. During bootstrap, the host application attempts to [load predefined modules](/reference/registration/registerRemoteModules.md) and calls a registration function with a specific name and signature for each successfully loaded module. +1. During bootstrap, the host application attempts to [load predefined modules](/reference/registration/registerLocalModules.md) and calls a registration function with a specific name and signature for each successfully loaded module. -2. During registration, a module receives [the shared services](/reference/runtime/runtime-class.md) of the federated application and use them to dynamically register its [routes](/reference/runtime/runtime-class.md#register-routes) and [navigation items](/reference/runtime/runtime-class.md#register-navigation-items). +2. During registration, a module receives the [runtime](/reference/runtime/runtime-class.md) of the federated application and use the instance to dynamically register its [routes](/reference/runtime/runtime-class.md#register-routes) and [navigation items](/reference/runtime/runtime-class.md#register-navigation-items). -3. Once [all the modules are registered](/reference/registration/useAreModulesReady.md), the host application will create a React Router [instance](https://reactrouter.com/en/main/routers/create-browser-router) with the registered routes and [renders a navigation menu](/reference/routing/useRenderedNavigationItems.md) with the registered navigation items. +3. Once all the modules are registered, the host application will create a React Router [instance](https://reactrouter.com/en/main/routers/create-browser-router) with the registered routes and [renders a navigation menu](/reference/routing/useRenderedNavigationItems.md) with the registered navigation items. -That's a nutshell overview. Of course, there is more to it, but these are the main ideas. +This is a high-level overview. Of course, there is more to it, but these are the main ideas. ## Guiding principles While developing the [API](/reference) of Squide, we kept a few guiding principles in mind. Those principles are not settled stones, you might want to diverge from them from time to time, but adhering to those will make your experience more enjoyable: -- A module should always correspond to a subdomain of the application's business domain. +- A module should correspond to a subdomain of the application's business domain. + +- A module should be autonomous. -- A module should be fully autonomous. It shouldn't have to coordinate with other parts of the application for things as trivial as navigation links. +- A module should not directly reference the other modules of the application. To coordinate with other modules, including the host application, a module should always use Squide's [Runtime API](../reference/runtime/runtime-class.md). -- A federated application should feel cohesive. Different parts of a federation application should have the ability to communicate with each others and react to changes happening outside of their boundaries. +- A modular application should feel cohesive. Different parts of the application should have the ability to communicate with each others and react to changes happening outside of their boundaries (without taking an hard reference on other parts of the application). -- Data and state should never be shared between parts of a federated application. Even if two parts require the same data or the same state values, they should load, store and manage them independently. +- Data and state should never be shared between modules. Even if two modules require the same data or the same state values, they should load, store and manage those independently. ## Limitations -Module Federation comes with a few manageable limitations that are important to consider when architecting your distributed application: +If you choose to include remote modules to your application, Module Federation comes with a few manageable limitations that are important to consider when architecting a distributed application: - A [shared dependency](https://module-federation.io/configure/shared.html) cannot be tree-shaken. Since remote modules are loaded at runtime, module federation cannot infer which parts of a shared dependency will be used by the application modules. Therefore, tree-shaking is disabled for shared dependencies. @@ -84,4 +102,4 @@ Module Federation comes with a few manageable limitations that are important to ## Create your project -To get started, follow the [quick start](create-host.md) guide to create a new federated application from scratch. +To get started, follow the [quick start](create-host.md) guide to create a new Squide's application from scratch. diff --git a/docs/getting-started/deploy.md b/docs/getting-started/deploy.md index b02801213..2ddd067f7 100644 --- a/docs/getting-started/deploy.md +++ b/docs/getting-started/deploy.md @@ -4,9 +4,9 @@ order: 10 # Deploy -The deployment process for a federated application can vary depending on various factors, including the chosen hosting provider. Therefore, we do not recommend any specific deployment setup. +The deployment process for a modular application can vary depending on various factors, including the chosen hosting provider. Therefore, we do not recommend any specific deployment setup. -However, there are a few essential configurations that need to be made regardless of your deployment choices. +However, there are a few essential configurations that need to be made regardless of your architectural and deployment choices. ## Add a default redirect @@ -33,11 +33,14 @@ Or by adding a `_redirects` file into the Netlify publish directory: ## Set the remote URL -Configure the remote modules production URL: +If your modular applications includes [remote modules](../reference/registration/registerRemoteModules.md), configure the remote modules production URL: -```ts -import { RemoteDefinition } from "@squide/firefly-webpack-configs"; +```js +// @ts-check +/** + * @typedef {import("@squide/firefly-webpack-configs").RemoteDefinition[]} + */ const Remotes: RemoteDefinition[] = [ { name: "remote1", diff --git a/docs/getting-started/learn-the-api.md b/docs/getting-started/learn-the-api.md index 207b9904c..d48a95014 100644 --- a/docs/getting-started/learn-the-api.md +++ b/docs/getting-started/learn-the-api.md @@ -34,7 +34,7 @@ const runtime = new FireflyRuntime({ }); ``` -Then, log entries from any parts of your federated application with the `useLogger` hook: +Then, log entries from any parts of your modular application with the `useLogger` hook: ```ts import { useLogger } from "@squide/firefly"; @@ -48,7 +48,7 @@ The logger is also available from the [FireflyRuntime](/reference/runtime/runtim ## Messaging -It's crucial that the parts of a federated application remains loosely coupled. To help with that, Squide offers a built-in [Event Bus](/reference/messaging/EventBus.md). +It's crucial that the parts of a modular application remains loosely coupled. To help with that, Squide offers a built-in [Event Bus](/reference/messaging/EventBus.md). First, listen to an event with the [useEventBusListener](/reference/messaging/useEventBusListener.md) hook: @@ -77,56 +77,6 @@ You can use the event bus to enable various communication scenarios, such as not The event bus is also available from the [FireflyRuntime](/reference/runtime/runtime-class.md#use-the-event-bus) instance. -## Session - -Most of our applications (if not all) will eventually require the user to authenticate. To facilitate this process, the Squide [FireflyRuntime](/reference/runtime/runtime-class.md) class accepts a [sessionAccessor](/reference/fakes/localStorageSessionManager.md#integrate-with-a-runtime-instance) function. Once the shell registration flow is completed, the function will be made accessible to every module of the application. - -First, define a `sessionAccessor` function: - -```ts host/src/session.ts -import type { SessionAccessorFunction } from "@squide/firefly"; -import { LocalStorageSessionManager } from "@squide/fakes"; - -export const sessionManager = new LocalStorageSessionManager(); - -const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; -``` - -!!!warning -Our security department reminds you to refrain from using a fake `LocalStorageSessionManager` in a production application :blush: -!!! - -Then register the accessor function: - -```ts host/src/boostrap.tsx -import { FireflyRuntime } from "@squide/firefly"; -import { sessionAccessor } from "./session.ts"; - -const runtime = new FireflyRuntime({ - sessionAccessor -}); -``` - -Finally, access the session from any parts of the application with the [useSession](/reference/runtime/useSession.md) hook: - -```ts -import { useSession } from "@squide/firefly"; - -const session = useSession(); -``` - -Or determine whether or not the user is authenticated with the [useIsAuthenticated](/reference/session/useIsAuthenticated.md) hook: - -```ts -import { useIsAuthenticated } from "@squide/firefly"; - -const isAuthenticated = useIsAuthenticated(); -``` - -The session is also available from the [FireflyRuntime](/reference/runtime/runtime-class.md#retrieve-the-current-session) instance. - ## Plugins To keep Squide lightweight, not all functionalities should be integrated as a core functionality. However, to accommodate a broad range of technologies, a [plugin system](../reference/plugins/plugin.md) has been implemented to fill the gap. @@ -138,7 +88,7 @@ import { FireflyRuntime } from "@squide/firefly"; import { MyPlugin } from "@sample/my-plugin"; const runtime = new FireflyRuntime({ - plugins: [new MyPlugin()] + plugins: [x => new MyPlugin(x)] }); ``` @@ -164,7 +114,7 @@ Explore the [guides](../guides/default.md) section to learn about Squide advance Be sure to read, at a minimum, the following guides: - [Setup Mock Service Worker](../guides/setup-msw.md) -- [Fetch initial data](../guides/fetch-initial-data.md) +- [Fetch global data](../guides/fetch-global-data.md) - [Fetch page data](../guides/fetch-page-data.md) - [Manage shared state](../guides/manage-shared-state.md) - [Isolate module failures](../guides/isolate-module-failures.md) diff --git a/docs/guides/add-a-public-page.md b/docs/guides/add-a-public-page.md deleted file mode 100644 index 03636f061..000000000 --- a/docs/guides/add-a-public-page.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -order: 900 ---- - -# Add a public page - -By default, when a route is registered with the [registerRoute](../reference/runtime/runtime-class.md#register-routes) function, the route is considered as "protected". This doesn't imply that the route becomes inacessible to unauthenticated users thought; as this protection is typically granted by an [authentication boundary](./add-authentication.md#add-an-authentication-boundary). What it means is that if the [AppRouter](../reference/routing/appRouter.md) component's [onLoadPublicData](../reference/routing/appRouter.md#load-public-data) and [onLoadProtectedData](../reference/routing/appRouter.md#load-protected-data) handlers are defined, both handlers will be executed when the route is requested (assuming it is the initial request). - -Therefore, if a route and its layout do not rely on the initial protected data of the application, the route should be declared as `public` using the `$visibility` option: - -```tsx !#6 src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import { Page } from "./Page.tsx"; - -export const register: ModuleRegisterFunction = runtime => { - runtime.registerRoute({ - $visibility: "public", - path: "/page", - element: - }); -} -``` - -By doing so, only the `onLoadPublicData` handler will be executed when the public route is requested (assuming it is the initial request). diff --git a/docs/guides/add-a-public-route.md b/docs/guides/add-a-public-route.md new file mode 100644 index 000000000..f5f68907b --- /dev/null +++ b/docs/guides/add-a-public-route.md @@ -0,0 +1,24 @@ +--- +order: 900 +--- + +# Add a public route + +A route can have one of two visibility values: `"public"` or `"protected"`. However, these visibility values do not determine whether a route is accessible to everyone or restricted to authenticated users. That protection is typically enforced by an [authentication boundary](./add-authentication.md#add-an-authentication-boundary). + +In a Squide application, if both the [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md) and [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hooks are defined, the following will occur: if the initially requested route is hinted as `"protected"`, both hooks will execute their respective requests. However, if the requested route is hinted as `"public"`, only the `usePublicDataQueries` hook will execute its requests. + +By default, when a route is registered with the [registerRoute](../reference/runtime/runtime-class.md#register-routes) function, the route is considered as `"protected"`. Therefore, if a route and its layout do not rely on the initial protected data of the application, the route should be explicitly declared as `"public"` using the `$visibility` option: + +```tsx !#6 remote/src/register.tsx +import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; +import { Page } from "./Page.tsx"; + +export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + $visibility: "public", + path: "/page", + element: + }); +} +``` diff --git a/docs/guides/add-a-shared-dependency.md b/docs/guides/add-a-shared-dependency.md index d0804864e..510f4e3a3 100644 --- a/docs/guides/add-a-shared-dependency.md +++ b/docs/guides/add-a-shared-dependency.md @@ -4,15 +4,15 @@ order: 760 # Add a shared dependency -[Shared dependencies](https://module-federation.io/configure/shared.html) represent one of the most powerful concepts of Module Federation. However, mastering its configuration can be quite challenging. **Failure** to configure shared dependencies properly in a federated application using Module Federation can significantly **impact** both **user** and **developer experiences**. +[Shared dependencies](https://module-federation.io/configure/shared.html) is one of the most powerful concepts of Module Federation. However, mastering its configuration can be quite challenging. **Failure** to configure shared dependencies properly in a federated application using Module Federation can significantly **impact** both **user** and **developer experiences**. -Squide aims to simplify the configuration of shared dependencies by abstracting the shared dependencies necessary for building an application with React, React Router, and optionally MSW and i18next. Nevertheless, every federated application will inevitably have to configure additional custom shared dependencies. +Squide aims to **simplify** the configuration of shared dependencies by abstracting the shared dependencies necessary for building an application with React, React Router, and optionally MSW and i18next. Nevertheless, every federated application will inevitably have to configure additional custom shared dependencies. For a more comprehensive documentation of the Module Federation APIs, their functionality, and their benefits, please refer to this [article](https://www.infoxicator.com/en/module-federation-shared-api). ## Understanding singleton dependencies -A [singleton](https://module-federation.io/configure/shared.html#singleton) shared dependency does exactly what its name suggests: it loads only a single instance of a dependency. This means that a dependency will be included in just one bundle file of the federated application. +A [singleton](https://module-federation.io/configure/shared.html#singleton) shared dependency does exactly what its name suggests: it loads a single instance of a dependency. This means that a dependency will be included in just one bundle file of the federated application. ### Strict versioning diff --git a/docs/guides/add-authentication.md b/docs/guides/add-authentication.md index ab738c251..d84f3d4e3 100644 --- a/docs/guides/add-authentication.md +++ b/docs/guides/add-authentication.md @@ -5,12 +5,10 @@ order: 920 # Add authentication !!!warning -Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) and [Fetch initial data](./fetch-initial-data.md) guides. +Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) and [Fetch global data](./fetch-global-data.md) guides. !!! -Most of our applications (if not all) will eventually requires the user to authenticate. To facilitate this process, the Squide [FireflyRuntime](/reference/runtime/runtime-class.md) class accepts a [sessionAccessor](/reference/fakes/localStorageSessionManager.md#integrate-with-a-runtime-instance) function. Once the application registration flow is completed, the function will be made accessible to every module of the application. - -When combined with a [React Router](https://reactrouter.com/en/main) authentication boundary and a login page, the shared `sessionAccessor` function is of great help to manage authentication concerns. +Most of Workleap's applications, if not all, will eventually require user authentication. While Squide doesn't offer built-in primitives for this process, it can assist by providing a **well-established recipe** to integrate an authentication flow with Squide. ## Add a login page @@ -36,7 +34,7 @@ While you can use any package manager to develop an application with Squide, it Then, add a [Mock Service Worker](https://mswjs.io/) (MSW) request handler to authenticate a user: -```ts !#28-30,40-42 host/mocks/handlers.ts +```ts !#29-31,41-44 host/mocks/handlers.ts import { HttpResponse, http, type HttpHandler } from "msw"; import { LocalStorageSessionManager } from "@squide/fakes"; @@ -54,6 +52,7 @@ const Users = [ export interface Session { username: string; + preferredLanguage: string; } // For simplicity, we are using a local storage session manager for this guide. @@ -77,7 +76,8 @@ export const requestHandlers: HttpHandler[] = [ // Login the user by storing the session to the local storage. sessionManager.setSession({ - username: user.username + username: user.username, + preferredLanguage: user.preferredLanguage }); return new HttpResponse(null, { @@ -111,10 +111,9 @@ export const registerHost: ModuleRegisterFunction = async runtim Then, create a login page: -```tsx !#14-23,27 host/src/Login.tsx +```tsx !#13-22,26 host/src/Login.tsx import { useCallback, useState, type ChangeEvent, type MouseEvent } from "react"; import { Navigate, useNavigate } from "react-router-dom"; -import { useIsAuthenticated } from "@squide/firefly"; export function Login() { const [username, setUserName] = useState(""); @@ -150,12 +149,6 @@ export function Login() { setPassword(event.target.value); }, []); - const isAuthenticated = useIsAuthenticated(); - - if (isAuthenticated) { - return ; - } - return (

      Login

      @@ -179,9 +172,9 @@ export function Login() { } ``` -After the user logs in, the application is reloaded. This is a requirement of the [AppRouter](../reference/routing/appRouter.md) component's [onLoadPublicData](../reference/routing/appRouter.md#load-public-data) and [onLoadProtectedData](../reference/routing/appRouter.md#load-protected-data) handlers. Nevertheless, it's not a significant concern because Workleap's applications utilize a third-party service for authentication which requires a full refresh of the application. +After the user logs in, the application is reloaded, this is a requirement of the [AppRouter](../reference/routing/appRouter.md) component. Nevertheless, it's not a concern because Workleap's applications use a third-party service for authentication which requires a full refresh of the application. -## Create a session accessor function +## Create a session manager Next, create a shared type for the session and the session manager: @@ -193,23 +186,46 @@ export interface Session { } export interface SessionManager { - setSession: (session: Session) => void; getSession: () => Session | undefined; clearSession: () => void; } ``` -Then, define a `sessionAccessor` function wrapping an `InMemorySessionManager` instance: +Then, create a shared `SessionManagerContext` along with some utility hooks. This React context will be used to share the `SessionManager` instance down the components tree: + +```ts shared/src/session.ts +export const SessionManagerContext = createContext(undefined); + +export function useSessionManager() { + return useContext(SessionManagerContext); +} + +export function useSession() { + const sessionManager = useSessionManager(); + + return sessionManager?.getSession(); +} + +export function useIsAuthenticated() { + const sessionManager = useSessionManager(); + + return !!sessionManager?.getSession(); +} +``` + +Finally, let's go back to the host application and create a [TanStack Query](https://tanstack.com/query/latest) implementation of the shared `SessionManager` interface created previously: -```tsx host/src/session.ts -import type { SessionAccessorFunction } from "@squide/firefly"; -import type { Session, SessionManager } from "@sample/shared"; +```ts host/src/sessionManager.ts +import type { SessionManager, Session } from "@sample/shared"; +import { useQueryClient, type QueryClient } from "@tanstack/react-query"; -export class InMemorySessionManager implements SessionManager { - #session?: Session; +class TanstackQuerySessionManager implements SessionManager { + #session: Session | undefined; + readonly #queryClient: QueryClient; - setSession(session: Session) { + constructor(session: Session, queryClient: QueryClient) { this.#session = session; + this.#queryClient = queryClient; } getSession() { @@ -218,32 +234,23 @@ export class InMemorySessionManager implements SessionManager { clearSession() { this.#session = undefined; + + this.#queryClient.invalidateQueries({ queryKey: ["/api/session"], refetchType: "inactive" }); } } -export const sessionManager = new InMemorySessionManager(); - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; -``` - -Finally, create the [FireflyRuntime](/reference/runtime/runtime-class.md) instance with the new `sessionAccessor` function: +export function useSessionManagerInstance(session: Session) { + const queryClient = useQueryClient(); -```ts #5 host/src/bootstrap.tsx -import { FireflyRuntime } from "@squide/firefly"; -import { sessionAccessor } from "./session.ts"; - -const runtime = new FireflyRuntime({ - sessionAccessor -}); + return useMemo(() => new TanstackQuerySessionManager(session, queryClient), [session, queryClient]); +} ``` ## Fetch the session -Now, let's create an MSW request handler that returns a session object if a user is authenticated: +Next, create an MSW request handler that returns a session object if a user is authenticated: -```ts !#49-60 host/mocks/handlers.ts +```ts !#50-61 host/mocks/handlers.ts import { HttpResponse, http, type HttpHandler } from "msw"; import { LocalStorageSessionManager } from "@squide/fakes"; @@ -261,6 +268,7 @@ const Users = [ export interface Session { username: string; + preferredLanguage: string; } // For simplicity, we are using a local storage session manager for this guide. @@ -307,81 +315,140 @@ export const requestHandlers: HttpHandler[] = [ ]; ``` -Then, update the host application `App` component to load the session when a user navigate to a protected page for the first time: +Then, update the host application `App` component to load the session with the [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hook and create an instance of `TanstackQuerySessionManager` with the retrieved session to share the sessuib via the `SessionManagerContext`: -```tsx !#19,21,25,27-29,33-34 host/src/App.tsx -import { AppRouter } from "@squide/firefly"; -import type { Session } from "@sample/shared"; -import { sessionManager } from "./session.ts"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; +```tsx !#7-28,30,37,47,57 host/src/App.tsx +import { AppRouter, useProtectedDataQueries, useIsBootstrapping } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { SessionManagerContext, ApiError, isApiError, type Session } from "@sample/shared"; +import { useSessionManagerInstance } from "./sessionManager.ts"; -async function fetchProtectedData(setIsSessionLoaded: (isLoaded: boolean) => void,signal: AbortSignal) { - const response = await fetch("/api/session", { - signal - }); +function BootstrappingRoute() { + const [session] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const response = await fetch("/api/session"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } - const data = await response.json(); + const data = await response.json(); - const session: Session = { - user: { - name: data.username + const result: Session = { + user: { + name: data.username, + } + }; + + return result; + } } - }; + ], error => isApiError(error) && error.status === 401); - sessionManager.setSession(session); + const sessionManager = useSessionManagerInstance(session!); - setIsSessionLoaded(true); + if (useIsBootstrapping()) { + return
      Loading...
      ; + } + + return ( + + + + ); } export function App() { - const [isSessionLoaded, setIsSessionLoaded] = useState(false); - - const handleLoadProtectedData = useCallback((signal: AbortSignal) => { - return fetchProtectedData(setIsSessionLoaded, signal); - }, []); - return ( - Loading...} - errorElement={
      An error occured!
      } - waitForMsw={true} + - {(routes, providerProps) => ( - - )} + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } ``` -!!!info -Since the `sessionManager` doesn't trigger a re-render, a `isSessionLoaded` state value is added to trigger a re-render when the session has been loadded. -!!! +The previous example uses the following implementation of the `ApiError` class: -## Add an authentication boundary +```ts shared/src/apiError.ts +export class ApiError extends Error { + readonly #status: number; + readonly #statusText: string; + readonly #stack?: string; + + constructor(status: number, statusText: string, innerStack?: string) { + super(`${status} ${statusText}`); + + this.#status = status; + this.#statusText = statusText; + this.#stack = innerStack; + } + + get status() { + return this.#status; + } + + get statusText() { + return this.#statusText; + } + + get stack() { + return this.#stack; + } +} + +export function isApiError(error?: unknown): error is ApiError { + return error !== undefined && error !== null && error instanceof ApiError; +} +``` -Next, create a new React Router authentication boundary component using the [useIsAuthenticated](../reference/session/useIsAuthenticated.md) hook: +## Add an authentication boundary -> Internally, the `useIsAuthenticated` hook utilize the `sessionAccessor` function that we created previously to determine whether or not the user is authenticated. +Next, create an authentication boundary component using the shared `useIsAuthenticated` hook created earlier to redirect unauthenticated user to the login page: -```tsx !#5 host/src/AuthenticationBoundary.tsx +```tsx host/src/AuthenticationBoundary.tsx import { Navigate, Outlet } from "react-router-dom"; -import { useIsAuthenticated } from "@squide/firefly"; +import { useIsAuthenticated } from "@sample/shared"; export function AuthenticationBoundary() { - return useIsAuthenticated() ? : ; + const isAuthenticated = useIsAuthenticated(); + + if (isAuthenticated) { + return ; + } + + return ; } ``` ## Define an authenticated layout -Now that authentication is in place, thanks to the `AuthenticationBoundary`, we can expect to render the navigation items exclusively for authenticated users. +Now, let's add a specific layout for authenticated users that passes through the `AuthenticationBoundary` component. First, add a MSW request handler to log out a user: -```ts !#49-56 host/mocks/handlers.ts +```ts !#50-57 host/mocks/handlers.ts import { HttpResponse, http, type HttpHandler } from "msw"; import { LocalStorageSessionManager } from "@squide/fakes"; @@ -399,6 +466,7 @@ const Users = [ export interface Session { username: string; + preferredLanguage: string; } // For simplicity, we are using a local storage session manager for this guide. @@ -454,10 +522,10 @@ export const requestHandlers: HttpHandler[] = [ ]; ``` -Then, introduce a new `AuthenticatedLayout` displaying the name of the logged-in user along with a logout button: +Then, introduce a new `AuthenticatedLayout` component displaying the name of the logged-in user along with a logout button. This layout will retrieve the active user session from the shared `useSessionManager` hook introduced earlier: -```tsx !#41,43-60,72,75 host/src/AuthenticatedLayout.tsx -import { useCallback, type ReactNode, type MouseEvent, type HTMLButtonElement } from "react"; +```tsx !#40-41,43-60,72,75 host/src/AuthenticatedLayout.tsx +import { Suspense, useCallback, type ReactNode, type MouseEvent, type HTMLButtonElement } from "react"; import { Link, Outlet, navigate } from "react-router-dom"; import { useNavigationItems, @@ -466,9 +534,9 @@ import { type RenderItemFunction, type RenderSectionFunction } from "@squide/react-router"; -import type { Session } from "@sample/shared"; +import { useSessionManager } from "@sample/shared"; -const renderItem: RenderItemFunction = (item, index, level) => { +const renderItem: RenderItemFunction = (item, key) => { // To keep things simple, this sample doesn't support nested navigation items. // For an example including support for nested navigation items, have a look at // https://gsoft-inc.github.io/wl-squide/reference/routing/userenderednavigationitems/ @@ -479,7 +547,7 @@ const renderItem: RenderItemFunction = (item, index, level) => { const { label, linkProps, additionalProps } = item; return ( -
    • +
    • {label} @@ -487,17 +555,17 @@ const renderItem: RenderItemFunction = (item, index, level) => { ); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
        +
          {elements}
        ); }; export function AuthenticatedLayout() { - // Retrieve the current user session. - const session = useSession() as Session; + const sessionManager = useSessionManager(); + const session = sessionManager?.getSession(); const handleLogout = useCallback(async (event: MouseEvent) => { event.preventDefault(); @@ -511,7 +579,7 @@ export function AuthenticatedLayout() { if (response.ok) { // Clear the in-memory session to ensure the authentication boundary can do his job. - sessionManager.clearSession(); + sessionManager?.clearSession(); // Redirect the user to the login page. navigate("/login"); @@ -528,27 +596,32 @@ export function AuthenticatedLayout() { {renderedNavigationItems}
        - (User: {session.user.name}) + (User: {session?.user.name})
        - + Loading...}> + + ); } ``` -By creating a new `AuthenticatedLayout`, much of the layout code has been transferred from the `RootLayout` to the `AuthenticatedLayout`, leaving the root layout responsible only for styling the outer wrapper of the application for now: +By creating a new `AuthenticatedLayout` component, much of the layout code has been transferred from the `RootLayout` to the `AuthenticatedLayout`, leaving the root layout responsible only for styling the outer wrapper of the application for now: ```tsx host/src/RootLayout.tsx +import { Suspense } from "react"; import { Outlet } from "react-router-dom"; export function RootLayout() { return (
        - + Loading...
        }> + + ); } @@ -558,58 +631,39 @@ export function RootLayout() { Finally, assemble everything: -```tsx !#17,22,25,46-52 host/src/register.tsx +```tsx !#15,19,27-33 host/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; import { RootLayout } from "./Rootlayout.tsx"; -import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; import { AuthenticationBoundary } from "./AuthenticationBoundary.tsx"; -import { ModuleErrorBoundary } from "./ModuleErrorBoundary.tsx"; import { LoginPage } from "./LoginPage.tsx"; import { HomePage } from "./Homepage.tsx"; import { NotFoundPage } from "./NotFoundPage.tsx"; export const registerHost: ModuleRegisterFunction = async runtime => { runtime.registerRoute({ + $name: "root-layout", element: , children: [ { - // The root error boundary is a named route, allowing the logging and logout pages - // to be nested under it using a "parentName" option. - $name: "root-error-boundary", - errorElement: , + // Every page beyond the authenticated boundary are protected. + element: , children: [ { - // Every page beyond the authenticated boundary are protected. - element: , - children: [ - { - element: , - children: [ - { - // By having the error boundary under the authenticated layout, modules unmanaged errors - // will be displayed inside the layout rather than replacing the whole page. - errorElement: , - children: [ - ManagedRoutes - ] - } - ] - } - ] + // All the managed routes will render the authenticated layout. + element: , + children: ManagedRoutes } ] } ] }); - // The login page is nested under the root error boundary to be defined before the - // authentication boundary and be publicly accessible. runtime.registerRoute({ $visibility: "public", path: "/login", element: }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -617,7 +671,7 @@ export const registerHost: ModuleRegisterFunction = async runtim path: "*", element: }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ diff --git a/docs/guides/default.md b/docs/guides/default.md index f53af6865..da8623c4e 100644 --- a/docs/guides/default.md +++ b/docs/guides/default.md @@ -7,18 +7,18 @@ expanded: true # Guides - [Setup Mock Service Worker](./setup-msw.md) -- [Fetch initial data](./fetch-initial-data.md) +- [Fetch global data](./fetch-global-data.md) - [Fetch page data](./fetch-page-data.md) - [Manage shared state](./manage-shared-state.md) - [Isolate module failures](./isolate-module-failures.md) - [Add authentication](./add-authentication.md) -- [Add a public page](./add-a-public-page.md) +- [Add a public route](./add-a-public-route.md) - [Override the host layout](./override-the-host-layout.md) -- [Federated tabs](./federated-tabs.md) +- [Use federated tabs](./use-federated-tabs.md) - [Use feature flags](./use-feature-flags.md) - [Setup i18next](./setup-i18next.md) - [Develop a module in isolation](./develop-a-module-in-isolation.md) - [Override a React context](./override-a-react-context.md) - [Add a shared dependency](./add-a-shared-dependency.md) - [Implement a custom logger](./implement-a-custom-logger.md) -- [Migrate from a monolithic application](./migrate-from-a-monolith.md) +- [Migrate to firefly v9](./migrate-to-firefly-v9.md) diff --git a/docs/guides/develop-a-module-in-isolation.md b/docs/guides/develop-a-module-in-isolation.md index 2c074cf38..71b87cfad 100644 --- a/docs/guides/develop-a-module-in-isolation.md +++ b/docs/guides/develop-a-module-in-isolation.md @@ -4,9 +4,9 @@ order: 800 # Develop a module in isolation -To develop their own independent module, a team **shouldn't be required to install the host application** or any **other modules** of the application **that they do not own**. However, they should have a means to integrate their module with the application shell (`RootLayout`, `RootErrorBoundary`, etc..) while working on their module in isolation. +To develop their own independent module, a team **should not need to install the host application** or any **other modules** of the application **they do not own**. However, they should have a way to integrate their module with the application shell (e.g., `RootLayout`, `RootErrorBoundary`, etc..) while working in isolation. -To achieve this, the first step is to extract the application shell from the host application. There are several approaches to accomplish this, but in this guide, we'll transform the host application into a monorepo and introduce a new local package named `@sample/shell` for this purpose: +To achieve this, the first step is to extract the application shell from the host application. There are various ways to accomplish this, but in this guide, we'll transform the host application into a monorepo and introduce a new local package named `@sample/shell` specifically for this purpose: ``` !#4 host @@ -26,7 +26,9 @@ host ## Create a shell package -> The implementation details of the `RootLayout` and `RootErrorBoundary` won't be covered by this guide as it already has been covered many times by other guides. +!!!info +The implementation details of the `RootLayout` and `RootErrorBoundary` components won't be covered by this guide as it already has been covered many times by other guides. +!!! First, create a new package (we'll refer to ours as `shell`) and add the following fields to the `package.json` file: @@ -47,23 +49,34 @@ First, create a new package (we'll refer to ours as `shell`) and add the followi Then, install the package dependencies and configure the new package with [tsup](https://gsoft-inc.github.io/wl-web-configs/tsup/). -Then, create a `AppRouter` component in the shell package to provide a **reusable router configuration** that can be utilized by both the host application and the isolated modules. The new `AppRouter` component should be based on the `@squide/firefly` [AppRouter](../reference/routing/appRouter.md) component: +Then, create an `AppRouter` component in the shell package to provide a **reusable router configuration** that can be shared between the host application and the isolated modules. This new `AppRouter` component should wrap the `@squide/firefly` [AppRouter](../reference/routing/appRouter.md) component: ```tsx shell/src/AppRouter.tsx import { AppRouter as FireflyAppRouter } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter } from "react-router-dom"; -export function AppRouter() { +export function FireflyAppRouter() { return ( - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={false} - /> + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }} + ); } ``` -Finally, create a local module to register the **application shell** that will also be utilized by the host application and the isolated modules: +Finally, create a local module to register the **application shell**. This module will be used by both the host application and the isolated modules: ```tsx shell/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; @@ -88,12 +101,12 @@ export const registerShell: ModuleRegisterFunction = runtime => ``` !!!info -This guide only covers the `RootLayout` and `RootErrorBoundary` but the same goes for other shell assets such as an `AuthenticationBoundary`. +This guide only covers the `RootLayout` and `RootErrorBoundary` components but the same goes for other shell assets such as an `AuthenticationBoundary` component. !!! ## Update the host application -Now, let's revisit the host application by first adding a dependency to the new `@sample/shell` package: +Now, let's revisit the host application by adding the new `@sample/shell` package as a dependency: ```json host/package.json { @@ -103,7 +116,7 @@ Now, let's revisit the host application by first adding a dependency to the new } ``` -Then, incorporate the newly introduced `AppRouter` component: +Then, integrate the `AppRouter` component from the `@sample/shell` package into the application: ```tsx host/src/App.tsx import { AppRouter } from "@sample/shell"; @@ -115,7 +128,7 @@ export function App() { } ``` -And the `registerShell` function to setup the `RootLayout`, the `RootErrorBoundary` and any other shell assets: +And finally include the `registerShell` function to setup the `RootLayout` and `RootErrorBoundary` components as well as any other shell assets: ```tsx !#16 host/src/bootstrap.tsx import { createRoot } from "react-dom/client"; @@ -190,7 +203,7 @@ import { register as registerModule } from "./register.tsx"; import { registerDev } from "./dev/register.tsx"; import { registerShell } from "@sample/shell"; -// Services, loggers, sessionAccessor, etc... could be reuse through a +// Services, loggers, etc... could be reuse through a // shared packages or faked when in isolation. const runtime = new FireflyRuntime({ loggers: [new ConsoleLogger()] @@ -211,7 +224,7 @@ root.render( ### App.tsx -The `App.tsx` file uses the newly created `AppRouter` component to setup [React Router](https://reactrouter.com/): +The `App.tsx` file uses the newly created `AppRouter` component to setup Squide's primitives with a [React Router](https://reactrouter.com/) instance: ```tsx remote-module/src/App.tsx import { AppRouter } from "@sample/shell"; @@ -225,7 +238,7 @@ export function App() { ### DevHome.tsx -The `DevHome` component purpose is strictly to serve as an `index` page when developing the remote module in isolation. +The `DevHome` component is the homepage when the remote module is developed in isolation: ```tsx remote-module/src/dev/DevHome.tsx function DevHome() { @@ -238,7 +251,7 @@ function DevHome() { } ``` -To register the development homepage, let's create a new local module specifically for registering what is needed to develop the module in isolation: +To register the development homepage, create a new local module specifically for configuring the remote during isolated development: ```tsx remote-module/src/dev/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -254,7 +267,7 @@ export const registerDev: ModuleRegisterFunction = runtime => { ### Add a new CLI script -Next, add a new `dev-isolated` script to the `package.json` file to start the local development server in **"isolation"**: +Next, add a new `dev-isolated` script to the `package.json` file to start the local development server in **isolation**: ```json !#3 remote-module/package.json { @@ -267,14 +280,10 @@ Next, add a new `dev-isolated` script to the `package.json` file to start the lo If your project's `package.json` file does not already include the [cross-env](https://www.npmjs.com/package/cross-env) dependency, be sure to install `cross-env` as a development dependency. !!! -The `dev-isolated` script is similar to the `dev` script but introduces a `ISOLATED` environment variable. This new environment variable will be utilized by the `webpack.dev.js` file to conditionally setup the development server for development in **isolation** or to be consumed by a host application through the `/remoteEntry.js` entry point: +The `dev-isolated` script is similar to the `dev` script but introduces an `ISOLATED` environment variable. This variable will be used by the `webpack.dev.js` file to conditionally configure the development server to either serve the module as an application for isolated development or as a remote endpoint by the host application through the `/remoteEntry.js` entry point. ### Configure webpack -!!!info -If you are having issues configuring webpack, refer to the [@workleap/webpack-configs](https://gsoft-inc.github.io/wl-web-configs/webpack/) documentation website. -!!! - First, open the `public/index.html` file created at the beginning of this guide and copy/paste the following [HtmlWebpackPlugin](https://webpack.js.org/plugins/html-webpack-plugin/) template: ```html host/public/index.html @@ -315,6 +324,10 @@ if (!process.env.ISOLATED) { export default config; ``` +!!!info +If you encounter issues configuring webpack, refer to the [@workleap/webpack-configs](https://gsoft-inc.github.io/wl-web-configs/webpack/) documentation. +!!! + ### Try it :rocket: Start the remote module in isolation by running the `dev-isolated` script. The application shell should wrap the pages of the module and the default page should be `DevHome`. @@ -329,9 +342,9 @@ If you are experiencing issues with this section of the guide: ## Setup a local module -Similarly to remote modules, the same isolated setup can be achieved for local modules. The main difference is that the `webpack.config.js` file of a local module serves the sole purpose of starting a development server for isolated development. Typically, local modules do not rely on webpack and [Module Federation](https://module-federation.io/). +Similarly to remote modules, local modules can also be set up for isolated development. The key difference is that the `webpack.config.js` file for a local module strictly serves the purpose of starting a development server for isolated development. Typically, local modules do not depend on webpack or [Module Federation](https://module-federation.io/). -First, open a terminal at the root of the local module application and install the `@squide/firefly-webpack-configs` package and its dependencies: +First, open a terminal at the root of the local module project and install the `@squide/firefly-webpack-configs` package and its dependencies: +++ pnpm ```bash @@ -398,10 +411,6 @@ These files are similar to the `dev/DevHome.tsx` and `dev/register.tsx` files of ### Configure webpack -!!!info -If you are having issues configuring webpack, refer to the [@workleap/webpack-configs](https://gsoft-inc.github.io/wl-web-configs/webpack/) documentation website. -!!! - First, open the `public/index.html` file and copy/paste the following [HtmlWebpackPlugin](https://webpack.js.org/plugins/html-webpack-plugin/) template: ```html local-module/public/index.html @@ -444,6 +453,10 @@ import { swcConfig } from "./swc.config.js"; export default defineDevHostConfig(swcConfig, "local1", 8080, []); ``` +!!!info +If you encounter issues configuring webpack, refer to the [@workleap/webpack-configs](https://gsoft-inc.github.io/wl-web-configs/webpack/) documentation. +!!! + ### Add a new CLI script Next, add a new `dev-isolated` script to the `package.json` file to start the local development server: diff --git a/docs/guides/fetch-global-data.md b/docs/guides/fetch-global-data.md new file mode 100644 index 000000000..52185fcd3 --- /dev/null +++ b/docs/guides/fetch-global-data.md @@ -0,0 +1,469 @@ +--- +order: 980 +--- + +# Fetch global data + +!!!warning +Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) guide. +!!! + +Retrieving the global data of an application is a crucial aspect that isn't always straightforward to implement. That's why we encourage feature teams to build their global data fetching strategy on top of the Squide [AppRouter](../reference/routing/appRouter.md) component. + +## Challenges with global data + +At first glance, one might wonder what could be so complicated about fetching the global data of an application. It's only fetches ...right? Well, there are several concerns to take into account for a Squide application: + +- When in development, the global data cannot be fetched until the Mock Service Worker (MSW) **request handlers** are **registered** and **MSW is ready**. + +- To register the MSW request handlers, the **modules** (including the remote modules) must be **registered** first. + +- If the requested page is _public_, only the global public data should be fetched. + +- If the requested page is _protected_, **both** the global **public** and **protected data** should be **fetched**. + +- The requested page rendering must be delayed until the global data has been fetched. + +- A **unique loading spinner** should be displayed to the user during this process, ensuring there's **no flickering** due to different spinners being rendered. + +To help manage those concerns, Squide offer an `AppRouter` component that takes care of setuping Squide's primitive and orchestrating the different states. + +## Fetch public data + +### Add an endpoint + +First, define in the host application an MSW request handler that returns the number of times it has been fetched: + +```ts host/mocks/handlers.ts +import { HttpResponse, http, type HttpHandler } from "msw"; + +let fetchCount = 0; + +export const requestHandlers: HttpHandler[] = [ + http.get("/api/count", () => { + fetchCount += 1; + + return HttpResponse.json([{ + "count": fetchCount + }]); + }) +]; +``` + +Then, register the request handler using the module registration function: + +```tsx !#7 host/src/register.tsx +import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; + +export const register: ModuleRegisterFunction = async runtime => { + if (runtime.isMswEnabled) { + // Files that includes an import to the "msw" package are included dynamically to prevent adding + // unused MSW stuff to the application bundles. + const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers; + + runtime.registerRequestHandlers(requestHandlers); + } +} +``` + +### Create a shared context + +Then, in a shared project, create a React context named `FetchCountContext`: + +```ts shared/src/fetchCountContext.ts +import { createContext, useContext } from "react"; + +export const FetchCountContext = createContext(0); + +export function useFetchCount() { + return useContext(FetchCountContext); +} +``` + +!!!info +Ensure that the shared project is configured as a [shared dependency](./add-a-shared-dependency.md). +!!! + +### Create a custom error class + +Then, in the same shared project, create a `ApiError` class: + +```ts shared/src/apiError.ts +export class ApiError extends Error { + readonly #status: number; + readonly #statusText: string; + readonly #stack?: string; + + constructor(status: number, statusText: string, innerStack?: string) { + super(`${status} ${statusText}`); + + this.#status = status; + this.#statusText = statusText; + this.#stack = innerStack; + } + + get status() { + return this.#status; + } + + get statusText() { + return this.#statusText; + } + + get stack() { + return this.#stack; + } +} + +export function isApiError(error?: unknown): error is ApiError { + return error !== undefined && error !== null && error instanceof ApiError; +} +``` + +### Fetch the data + +Finally, update the `App` component to add the [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md) hook. The hook will fetch the data from `/api/count` and forward the retrieved `fetchCount` value through `FetchCountContext`: + +```tsx !#6-21,23-25,38 host/src/App.tsx +import { AppRouter, usePublicDataQueries, useIsBootstrapping } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { FetchCountContext, ApiError } from "@sample/shared"; + +function BootstrappingRoute() { + const [fetchCount] = usePublicDataQueries([ + { + queryKey: ["/api/count"], + queryFn: async () => { + const response = await fetch("/api/count"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + return data.count as number; + } + } + ]); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ( + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +#### `usePublicDataQueries` + +The `usePublicDataQueries` hook is a wrapper around TanStack Query's native [useQueries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) hook. This wrapper coordinates the execution of the queries with the `AppRouter` component's state. + +#### `waitForPublicData` & `useIsBootstrapping` + +To ensure the `AppRouter` component wait for the public data to be ready before rendering the requested route, set the [waitForPublicData](../reference/routing/appRouter.md#delay-rendering-until-the-public-data-is-ready) property to `true`. + +Combine the `usePublicDataQueries` with the [useIsBootstrapping](../reference/routing/useIsBootstrapping.md) hook to display a loader until the public data is fetched and the application is ready. + +### Use the endpoint data + +Now, create a `GlobalDataLayout` component that uses the count retrieved from `FetchCountContext` and render pages with a green background color if the value is odd: + +```tsx !#5,10 host/src/GlobalDataLayout.tsx +import { useFetchCount } from "@sample/shared"; +import { Outlet } from "react-router-dom"; + +export function GlobalDataLayout() { + const fetchCount = useFetchCount(); + + const isOdd = fetchCount % 2 === 0; + + return ( +
        + +
        + ) +} +``` + +Then, create a `Page` component: + +```tsx host/src/Page.tsx +export function Page() { + return ( +
        When the fetch count is odd, my background should be green.
        + ) +} +``` + +Finally, register both components, either in the host application or within any module: + +```tsx !#8,12 host/src/register.tsx +import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; +import { GlobalDataLayout } from "./GlobalDataLayout.tsx"; +import { Page } from "./Page.tsx"; + +export const register: ModuleRegisterFunction = async runtime => { + runtime.registerRoute({ + path: "/global-data", + element: , + children: [ + { + index: true, + element: + } + ] + }); + + runtime.registerNavigationItem({ + $key: "global-data", + $label: "Global data Page", + to: "/global-data" + }); + + // Files that includes an import to the "msw" package are included dynamically to prevent adding + // unused MSW stuff to the application bundles. + const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers; + + runtime.registerRequestHandlers(requestHandlers); +} +``` + +### Try it :rocket: + +Start the application in a development environment using the `dev` script and navigate to the `/global-data` page. Refresh the page a few times, the background color should alternate between transparent and green. + +#### Troubleshoot issues + +If you are experiencing issues with this section of the guide: + +- Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs (including MSW request handlers) and error messages if something went wrong. +- Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). +- Refer to the [troubleshooting](../troubleshooting.md) page. + +## Fetch protected data + +Now, let's load _protected_ data. The process is similar to fetching public data, but this time, we'll use the [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hook instead. + +### Add an endpoint + +First, define a MSW request handler that returns a user tenant subscription data: + +```ts !#14-21 host/mocks/handlers.ts +import { HttpResponse, http, type HttpHandler } from "msw"; + +let fetchCount = 0; + +export const requestHandlers: HttpHandler[] = [ + http.get("/api/count", () => { + fetchCount += 1; + + return HttpResponse.json([{ + "count": fetchCount + }]); + }), + + http.get("/api/subscription", () => { + // NOTE: + // The user id should be retrieved from the current session and the subscription should be retrieved from a database with this id. + // For the sake of simplicity, we haven't done it for this guide, instead we return hardcoded data. + return HttpResponse.json([{ + "status": "paid" + }]); + }) +]; +``` + +If you've registered the [public data request handler](#add-an-endpoint), the newly created request handler should be automatically registered. + +### Create a shared context + +Then, in a shared project, create a `SubscriptionContext`: + +```ts shared/src/subscriptionContext.ts +import { createContext, useContext } from "react"; + +export interface Subscription { + status: string +} + +export const SubscriptionContext = createContext(Subscription | undefined); + +export function useSubscription() { + return useContext(SubscriptionContext); +} +``` + +!!!info +If you're not adding the `SubscriptionContext` to the shared project created earlier for the public data example, make sure to configure this new shared project as a [shared dependency](./add-a-shared-dependency.md). +!!! + +### Fetch the data + +Finally, update the `App` component to add the [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hook. The hook will fetch the data from `/api/subscription` and forward the retrieved `subscription` data through `SubscriptionContext`: + +```tsx !#23-42,62 host/src/App.tsx +import { AppRouter, usePublicDataQueries, useProtectedDataQueries, useIsBootstrapping } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { FetchCountContext, SubscriptionContext, ApiError, isApiError, type Subscription } from "@sample/shared"; + +function BootstrappingRoute() { + const [fetchCount] = usePublicDataQueries([ + { + queryKey: ["/api/count"], + queryFn: async () => { + const response = await fetch("/api/count"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + return data.count as number; + } + } + ]); + + const [subscription] = useProtectedDataQueries([ + { + queryKey: ["/api/subscription"], + queryFn: async () => { + const response = await fetch("/api/subscription"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + const subscription: Subscription = { + status: data.status + }; + + return subscription; + } + } + ], error => isApiError(error) && error.status === 401); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ( + + + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +#### `useProtectedDataQueries` + +The `useProtectedDataQueries` hook is a wrapper around TanStack Query's native [useQueries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) hook. This wrapper coordinates the execution of the queries with the `AppRouter` component's state. + +#### `waitForProtectedData` + +To ensure the `AppRouter` component wait for the protected data to be ready before rendering the requested route, set the [waitForProtectedData](../reference/routing/appRouter.md#delay-rendering-until-the-public-data-is-ready) property to `true`. + +### Use the endpoint data + +Now, update the `GlobalDataLayout` component that was previously created for the [public data example](#use-the-endpoint-data) to render the user tenant subscription status: + +```tsx !#6,11 host/src/GlobalDataLayout.tsx +import { useFetchCount, useSubscription } from "@sample/shared"; +import { Outlet } from "react-router-dom"; + +export function GlobalDataLayout() { + const fetchCount = useFetchCount(); + const subscription = useSubscription(); + + const isOdd = fetchCount % 2 === 0; + + return ( +
        Subscription status: {subscription?.status}
        +
        + +
        + ) +} +``` + +### Try it :rocket: + +Start the application in a development environment using the `dev` script and navigate to the `/global-data` page. You should notice the subscription status. + +#### Troubleshoot issues + +If you are experiencing issues with this section of the guide: + +- Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs (including MSW request handlers) and error messages if something went wrong. +- Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). +- Refer to the [troubleshooting](../troubleshooting.md) page. + + + + diff --git a/docs/guides/fetch-initial-data.md b/docs/guides/fetch-initial-data.md deleted file mode 100644 index 14cbb2bb9..000000000 --- a/docs/guides/fetch-initial-data.md +++ /dev/null @@ -1,397 +0,0 @@ ---- -order: 980 ---- - -# Fetch initial data - -!!!warning -Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) guide. -!!! - -Retrieving the initial data of an application is a crucial aspect that isn't always straightforward to implement. That's why we encourage feature teams to build their initial data fetching strategy on top of the Squide [AppRouter](../reference/routing/appRouter.md) component. - -## Challenges with initial data - -At first glance, one might wonder what could be so complicated about fetching the initial data of an application. It's only fetches ...right? Well, there are several concerns to take into account for a Squide application: - -- When in development, the initial data cannot be fetched until the Mock Service Worker (MSW) **request handlers** are **registered** and **MSW is started**. - -- To register the MSW request handlers, the **remote modules** must be **registered** first. - -- If the requested page is _public_, only the initial public data should be fetched. - -- If the requested page is _protected_, **both** the initial **public** and **protected data** should be **fetched**. - -- The requested page cannot be rendered until the initial data has been fetched. - -- A **unique loading spinner** should be displayed to the user while the modules are being registered, the MSW request handlers are being registered and the initial data is being fetched, ensuring **no flickering** due to different spinners being rendered. - -To help manage those concerns, Squide offer an `AppRouter` component that takes care of setuping Squide federated primitive and orchestrating the different states. - -## Fetch public data - -### Add an endpoint - -First, define an MSW request handler that returns the number of times it has been fetched: - -```ts mocks/handlers.ts -import { HttpResponse, http, type HttpHandler } from "msw"; - -let fetchCount = 0; - -export const requestHandlers: HttpHandler[] = [ - http.get("/api/count", () => { - fetchCount += 1; - - return HttpResponse.json([{ - "count": fetchCount - }]); - }) -]; -``` - -Then, register the request handler using the module registration function: - -```tsx !#7 src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; - -export const register: ModuleRegisterFunction = async runtime => { - if (runtime.isMswEnabled) { - // Files that includes an import to the "msw" package are included dynamically to prevent adding - // unused MSW stuff to the application bundles. - const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers; - - runtime.registerRequestHandlers(requestHandlers); - } -} -``` - -### Create a shared context - -Then, in a shared project, create a React context named `FetchCountContext`: - -```ts shared/src/fetchCountContext.ts -import { createContext, useContext } from "react"; - -export const FetchCountContext = createContext(0); - -export function useFetchCount() { - return useContext(FetchCountContext); -} -``` - -!!!info -Ensure that the shared project is configured as a [shared dependency](./add-a-shared-dependency.md). -!!! - -### Fetch the data - -Finally, open the host application code and update the `App` component to utilize the `AppRouter` component's [onLoadPublicData](../reference/routing/appRouter.md#load-public-data) handler. This handler will fetch the count and forward the retrieved value through `FetchCountContext`: - -```tsx !#8,17,19-21,24,26-27 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter } from "@squide/firefly"; -import { FetchCountContext } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; - -async function fetchPublicData(setFetchCount: (fetchCount: number) => void, signal: AbortSignal) { - const response = await fetch("/api/count", { - signal - }); - - const data = await response.json(); - - setFetchCount(data.count); -} - -export function App() { - const [fetchCount, setFetchCount] = useState(0); - - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFetchCount, signal); - }, []); - - return ( - - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} -
        -
        - ); -} -``` - -!!!info -The `onLoadPublicData` handler receives as first argument an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) that should be forwarded to the HTTP client initiating the public data GET request. The signal will cancel the previous HTTP request when the `onLoadPublicData` handler is called twice due to the `AppRouter` being re-rendered. -!!! - -!!!info -The `onLoadPublicData` handler must return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object. When the [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) keyword is included in a function signature, the function will automatically return a `Promise` object. -!!! - -!!!info -The `isPublicDataLoaded` must be provided to indicate whether or not the public data loading is completed. -!!! - -### Use the endpoint data - -Now, create a `InitialDataLayout` component that utilizes the count retrieved from `FetchCountContext` and render pages with a green background color if the value is odd: - -```tsx !#5,10 src/InitialDataLayout.tsx -import { useFetchCount } from "@sample/shared"; -import { Outlet } from "react-router-dom"; - -export function InitialDataLayout() { - const fetchCount = useFetchCount(); - - const isOdd = fetchCount % 2 === 0; - - return ( -
        - -
        - ) -} -``` - -Then, create a `Page` component: - -```tsx src/Page.tsx -export function Page() { - return ( -
        When the fetch count is odd, my background should be green.
        - ) -} -``` - -Finally, register both components: - -```tsx !#8,12 src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import { InitialDataLayout } from "./InitialDataLayout.tsx"; -import { Page } from "./Page.tsx"; - -export const register: ModuleRegisterFunction = async runtime => { - runtime.registerRoute({ - path: "/initial-data", - element: , - children: [ - { - index: true, - element: - } - ] - }); - - runtime.registerNavigationItem({ - $label: "Initial data Page", - to: "/initial-data" - }); - - // Files that includes an import to the "msw" package are included dynamically to prevent adding - // unused MSW stuff to the application bundles. - const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers; - - runtime.registerRequestHandlers(requestHandlers); -} -``` - -### Try it :rocket: - -Start the application in a development environment using the `dev` script and navigate to the `/initial-data` page. Refresh the page a few times, the background color should alternate between transparent and green. - -#### Troubleshoot issues - -If you are experiencing issues with this section of the guide: - -- Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs (including MSW request handlers) and error messages if something went wrong. -- Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). -- Refer to the [troubleshooting](../troubleshooting.md) page. - -## Fetch protected data - -Now, let's load _protected_ data. The process is similar to fetching public data, but this time, we'll use the [onLoadProtectedData](../reference/routing/appRouter.md#load-protected-data) handler of the `AppRouter` component instead. - -### Add an endpoint - -First, define a MSW request handler that returns a user tenant subscription data: - -```ts !#14-21 mocks/handlers.ts -import { HttpResponse, http, type HttpHandler } from "msw"; - -let fetchCount = 0; - -export const requestHandlers: HttpHandler[] = [ - http.get("/api/count", () => { - fetchCount += 1; - - return HttpResponse.json([{ - "count": fetchCount - }]); - }), - - http.get("/api/subscription", () => { - // NOTE: - // The user id should be retrieved from the current session and the subscription should be retrieved from a database with this id. - // For the sake of simplicity, we haven't done it for this guide, instead we return hardcoded data. - return HttpResponse.json([{ - "status": "paid" - }]); - }) -]; -``` - -If you've registered the [public data request handler](#add-an-endpoint), the newly created request handler should be automatically registered. - -!!!warning -In the previous code sample, for the sake of simplicity, we haven't secured the request handler or implemented session management. However, please be aware that you should do it for a real Workleap application. -!!! - -### Create a shared context - -Then, in a shared project, create a `SubscriptionContext`: - -```ts shared/src/subscriptionContext.ts -import { createContext, useContext } from "react"; - -export interface Subscription { - status: string -} - -export const SubscriptionContext = createContext(Subscription | undefined); - -export function useSubscription() { - return useContext(SubscriptionContext); -} -``` - -!!!info -Ensure that the shared project is configured as a [shared dependency](./add-a-shared-dependency.md). -!!! - -### Fetch the data - -Finally, open the host application code and update the `App` component to utilize the `AppRouter` component's `onLoadProtectedData` handler. This handler will fetch the user tenant subscription and forward the retrieved value through `SubscriptionContext`: - -```tsx !#18,32,38-40,44,47,49 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter } from "@squide/firefly"; -import { FetchCountContext, SubscriptionContext, type Subscription } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; - -async function fetchPublicData(setFetchCount: (fetchCount: number) => void, signal: AbortSignal) { - const response = await fetch("/api/count", { - signal - }); - - const data = await response.json(); - - setFetchCount(data.count); -} - -async function fetchProtectedData(setSubscription: (subscription: Subscription) => void, signal: AbortSignal) { - const response = await fetch("/api/subscription", { - signal - }); - - const data = await response.json(); - - const subscription: Subscription = { - status: data.status - }; - - setSubscription(subscription); -} - -export function App() { - const [fetchCount, setFetchCount] = useState(0); - const [subscription, setSubscription] = useState(); - - const handleLoadPublicData = useCallback((signal: AbortController) => { - return fetchPublicData(setFetchCount, signal); - }, []); - - const handleLoadProtectedData = useCallback((signal: AbortController) => { - return fetchProtectedData(setSubscription, signal); - }, []); - - return ( - - - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} -
        - -
        - ); -} -``` - -!!!info -The `onLoadProtectedData` handler receives as first argument an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) that should be forwarded to the HTTP client initiating the public data GET request. The signal will cancel the previous HTTP request when the `onLoadProtectedData` handler is called twice due to the `AppRouter` being re-rendered. -!!! - -!!!info -The `onLoadProtectedData` handler must return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object. When the [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) keyword is included in a function signature, the function will automatically return a `Promise` object. -!!! - -!!!info -The `isProtectedDataLoaded` must be provided to indicate whether or not the protected data loading is completed. -!!! - -### Use the endpoint data - -Now, update the `InitialDataLayout` component that was previously created for the [public data example](#use-the-endpoint-data) to render the user tenant subscription status: - -```tsx !#6,11 src/InitialDataLayout.tsx -import { useFetchCount, useSubscription } from "@sample/shared"; -import { Outlet } from "react-router-dom"; - -export function InitialDataLayout() { - const fetchCount = useFetchCount(); - const subscription = useSubscription(); - - const isOdd = fetchCount % 2 === 0; - - return ( -
        Subscription status: {subscription?.status}
        -
        - -
        - ) -} -``` - -### Try it :rocket: - -Start the application in a development environment using the `dev` script and navigate to the `/initial-data` page. You should notice the subscription status. - -#### Troubleshoot issues - -If you are experiencing issues with this section of the guide: - -- Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs (including MSW request handlers) and error messages if something went wrong. -- Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). -- Refer to the [troubleshooting](../troubleshooting.md) page. - - - - diff --git a/docs/guides/fetch-page-data.md b/docs/guides/fetch-page-data.md index 1b0495980..cc3ec08eb 100644 --- a/docs/guides/fetch-page-data.md +++ b/docs/guides/fetch-page-data.md @@ -8,11 +8,11 @@ order: 975 Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) guide. !!! -There are various approaches to fetching data for pages. At Workleap, our preference is usually to develop a dedicated endpoint per page, returning a denormalized document specifically tailored for that page. We rely on server state as our singular source of truth and leverage [React Query](https://tanstack.com/query/latest/) to manage data fetching and ensure our data remains up-to-date. +There are various approaches to fetching data for pages. At Workleap, our preference is to develop a backend for frontend (BFF) with a **dedicated endpoint per page**, returning a **data** structure specifically **tailored** for that **page**. We rely on **server state** as our single **source of truth** and leverage [TanStack Query](https://tanstack.com/query/latest/) to manage data fetching. -Although this approach works well, a few adjustments are necessary when transitioning from a monolithic application to a federated application. +Although this approach works well, a few adjustments are necessary for modular applications. -## Install React Query +## Install TanStack Query First, open a terminal at the root of the module and install the following packages: @@ -41,7 +41,7 @@ While you can use any package manager to develop an application with Squide, it Then, instanciate a [QueryClient](https://tanstack.com/query/latest/docs/react/reference/QueryClient) instance in the module registration function and wrap the routes element with a [QueryClientProvider](https://tanstack.com/query/latest/docs/react/reference/QueryClientProvider): -```tsx !#7,12 src/register.tsx +```tsx !#7,12 remote/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Page } from "./Page.tsx"; @@ -57,6 +57,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "page", $label: "Page", to: "/page" }); @@ -64,14 +65,14 @@ export const register: ModuleRegisterFunction = runtime => { ``` !!!info -To minimize unexpected situations and faciliate maintenance, the React Query cache shouldn't be shared between the host application and the modules. As the React Query cache is located in the `QueryClient`, both the host application and the modules should instantiate their own `QueryClient` instance. +To minimize unexpected situations and faciliate maintenance, the TanStack Query cache shouldn't be shared between the host application and the modules. As the TanStack Query cache is located in the `QueryClient`, both the host application and the modules should instantiate their own `QueryClient` instance. !!! ## Create a component for providers If the module register multiple routes, to prevent duplicating registration code, you can create a `Providers` component: -```tsx !#9-15,20 src/register.tsx +```tsx !#9-15,20 remote/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Page } from "./Page.tsx"; @@ -95,6 +96,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "page", $label: "Page", to: "/page" }); @@ -103,11 +105,11 @@ export const register: ModuleRegisterFunction = runtime => { ## Setup the development tools -To faciliate development, React Query provides [devtools](https://tanstack.com/query/latest/docs/react/devtools) to help visualize all of the inner workings of React Query. +To faciliate development, TanStack Query provides [devtools](https://tanstack.com/query/latest/docs/react/devtools) to help visualize all of the inner workings of TanStack Query. -However, the React Query devtools has not been developed to handle a federated application with multiple `QueryClient` instances. To use the devtools, you must define a `ReactQueryDevtools` component for each `QueryClient` instance: +However, the TanStack Query devtools has not been developed to handle a federated application with multiple `QueryClient` instances. To use the devtools, you must define a `ReactQueryDevtools` component for each `QueryClient` instance: -```tsx !#14 src/register.tsx +```tsx !#14 remote/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; @@ -133,15 +135,16 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "page", $label: "Page", to: "/page" }); } ``` -Then, depending on which page of the application has been rendered, a distinct devtools instance will be accessible. For a better experience, we recommend activating the React Query devtools exclusively when developing a module [in isolation](./develop-a-module-in-isolation.md): +Then, depending on which page of the application has been rendered, a distinct devtools instance will be accessible. For a better experience, we **recommend activating** the TanStack Query **devtools** exclusively when **developing** a **module** [in isolation](./develop-a-module-in-isolation.md): -```tsx !#14-16 src/register.tsx +```tsx !#14-16 remote/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; @@ -169,6 +172,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "page", $label: "Page", to: "/page" }); @@ -179,7 +183,7 @@ export const register: ModuleRegisterFunction = runtime => { Now, let's fetch some data. First, add a [Mock Service Worker](https://mswjs.io/) (MSW) request handler to the local module: -```ts mocks/handlers.ts +```ts remote/mocks/handlers.ts import { HttpResponse, http, type HttpHandler } from "msw"; export const requestHandlers: HttpHandler[] = [ @@ -199,7 +203,7 @@ export const requestHandlers: HttpHandler[] = [ Then, register the request handler using the module registration function: -```tsx !#7 src/register.tsx +```tsx !#7 remote/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; export const register: ModuleRegisterFunction = async runtime => { @@ -215,7 +219,7 @@ export const register: ModuleRegisterFunction = async runtime => Then, update the `Page` component to fetch and render the data with `useSuspenseQuery`: -```tsx !#10-15 src/Page.tsx +```tsx !#10-14 remote/src/Page.tsx import { useSuspenseQuery } from "@tanstack/react-query"; interface Character { @@ -227,10 +231,9 @@ interface Character { export function Page() { const { data: characters } = useSuspenseQuery({ queryKey: ["/api/characters"], queryFn: () => { const response = await fetch("/api/characters"); - const data = await response.json(); - - return data; - } }); + + return await response.json(); + }}); return (
        @@ -270,9 +273,9 @@ export function RootLayout() { ## Try it :rocket: -Start the local module in a development environment using the `dev-isolated` script. If you haven't completed the [develop a module in isolation](./develop-a-module-in-isolation.md) guide, use the `dev` script instead and skip the part about React Query devtools. Then, navigate to the `/page` page. +Start the local module in a development environment using the `dev-isolated` script. If you haven't completed the [develop a module in isolation](./develop-a-module-in-isolation.md) guide, use the `dev` script instead and skip the part about TanStack Query devtools. Then, navigate to the `/page` page. -You should notice that the character's data is being fetch from the MSW request handler and rendered on the page. Additionally, you should notice that the React Query devtools are available (a ribbon at the bottom right corner). +You should notice that the character's data is being fetch from the MSW request handler and rendered on the page. Additionally, you should notice that the TanStack Query devtools are available (a ribbon at the bottom right corner). #### Troubleshoot issues diff --git a/docs/guides/isolate-module-failures.md b/docs/guides/isolate-module-failures.md index bcbee4d32..3602886d9 100644 --- a/docs/guides/isolate-module-failures.md +++ b/docs/guides/isolate-module-failures.md @@ -6,13 +6,13 @@ order: 940 One of the key characteristics of micro-frontends implementations like [iframes](https://martinfowler.com/articles/micro-frontends.html#Run-timeIntegrationViaIframes) and subdomains is the ability to isolate failures within individual modules, preventing them from breaking the entire application. -However, in a [Module Federation](https://module-federation.io/) implementation, this is not the case as all the modules share the same browsing context (e.g. the same [Document object](https://developer.mozilla.org/en-US/docs/Web/API/Document), the same [Window object](https://developer.mozilla.org/en-US/docs/Web/API/Window), and the same DOM). A failure in one module can potentially breaks the entire application. +However, with a [Module Federation](https://module-federation.io/) implementation, this is not the case as all the modules share the same browsing context (e.g. the same [Document object](https://developer.mozilla.org/en-US/docs/Web/API/Document), the same [Window object](https://developer.mozilla.org/en-US/docs/Web/API/Window), and the same DOM). A failure in one module can potentially breaks the entire application. -Nevertheless, an application can get very close to iframes failure isolation by utilizing React Router's [Outlet](https://reactrouter.com/en/main/components/outlet) component and the [errorElement](https://reactrouter.com/en/main/route/error-element) property of a React Router's routes. +Nevertheless, an application, federated or non-federated, can get very close to iframes failure isolation by utilizing React Router's [Outlet](https://reactrouter.com/en/main/components/outlet) component and the [errorElement](https://reactrouter.com/en/main/route/error-element) property of a React Router's routes. ## Create an error boundary -First, define an error boundary to catch module errors. For this example we'll name it `RootErrorBoundary`: +First, define a React Router's error boundary to catch module errors. For this example we'll name it `RootErrorBoundary`: ```tsx host/src/RootErrorBoundary.tsx export function RootErrorBoundary() { @@ -24,7 +24,9 @@ export function RootErrorBoundary() { ## Register the error boundary -Then, update the host application `registerHost` function to declare the `RootErrorBoundary` component below the `RootLayout` but above the routes of the modules. By doing so, if a module encounters an unhandled error, the error boundary will only replace the section rendered by the `Outlet` component within the `RootLayout` rather than the entire page: +Then, update the host application `registerHost` function to declare the `RootErrorBoundary` component below the `RootLayout` component but above the routes of the modules. By doing so, if a module encounters an unhandled error, the error boundary will only replace the section rendered by the `Outlet` component within the root layout rather than the entire page. + +A React Router's error boundary is declared with the [errorElement](https://reactrouter.com/en/main/route/error-element) of a route: ```tsx !#7,11 host/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; @@ -53,7 +55,7 @@ By implementing this mechanism, the level of failure isolation achieved is **com ### Hoisted pages -If your application is [hoisting pages](../reference/runtime/runtime-class.md#register-an-hoisted-route), it's important to note that they will be rendered outside of the host application's root error boundary. To prevent breaking the entire application when an hoisted page encounters unhandled errors, it is highly recommended to declare a React Router's `errorElement` property for each hoisted page: +If your application is [hoisting pages](../reference/runtime/runtime-class.md#register-an-hoisted-route), it's important to note that they will be rendered outside of the host application's `RootErrorBoundary` component. To prevent breaking the entire application when an hoisted page encounters unhandled errors, it is highly recommended to declare a React Router's error boundary for each hoisted page as well, again using [errorElement](https://reactrouter.com/en/main/route/error-element): ```tsx !#9,11 remote-module/src/register.tsx import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; @@ -73,7 +75,7 @@ export const register: ModuleRegisterFunction = runtime => { ## Try it :rocket: -Start the application in a development environment using the `dev` script. Update any of your application routes that is rendered under the newly created error boundary (e.g. that is not hoisted) and throw an `Error`. The error should be handled by the error boundary instead of breaking the whole application. +Start the application in a development environment using the `dev` script. Update any of your application routes that is rendered under the newly created error boundary (e.g. that is not hoisted) and throw an `Error`. The error should be handled by the `RootErrorBoundary` component instead of breaking the whole application. ### Troubleshoot issues diff --git a/docs/guides/manage-shared-state.md b/docs/guides/manage-shared-state.md index 72f66e3f9..fd2a8b48c 100644 --- a/docs/guides/manage-shared-state.md +++ b/docs/guides/manage-shared-state.md @@ -4,16 +4,14 @@ order: 960 # Manage shared state -Effective management of the shared state is a crucial aspect of a federated application and can become problematic if not handled carefully. As a general rule, a host application and its modules should never share state. +Proper management of shared state is crucial in a modular application and can become problematic if not handled carefully. As a general rule, a host application and its modules should never share state. -## Forward the initial data +## Forward the global data -However, at certain points in the lifecycle of a federated application, the host will fetch initial data that should be fordwarded to the modules. Such examples include a user session and a user tenant subscription status: +However, in the lifecycle of a modular application, the host will fetch the global data that should be fordwarded to the modules. Such examples include a user session or a user tenant subscription status. -- To forward a user session object, a built-in [sessionAccessor](../reference/runtime/runtime-class.md#parameters) function is available. +As shown in the [Fetch global data](./fetch-global-data.md#fetch-the-data-1) guide, the global data can be forwarded to modules through a React context. -- To forward other types of initial data, such as a user tenant subscription, as shown in the [Fetch initial data](./fetch-initial-data.md#fetch-the-data-1) guide, the data can be forwarded to modules through a React context. +## TanStack Query -## React Query - -Lastly, as detailed in the [fetch page data](./fetch-page-data.md#setup-the-query-client) guide, the React Query cache should not be shared between the host and its modules. To do so, both the host application and the modules should instantiate their own `QueryClient` instance. +Lastly, as detailed in the [fetch page data](./fetch-page-data.md#setup-the-query-client) guide, the TanStack Query cache should not be shared between the host and its modules. To do so, both the host application and the modules should instantiate their own `QueryClient` instance. diff --git a/docs/guides/migrate-from-a-monolith.md b/docs/guides/migrate-from-a-monolith.md deleted file mode 100644 index da336fb43..000000000 --- a/docs/guides/migrate-from-a-monolith.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -order: 720 -label: Migrate from a monolith ---- - -# Migrate from a monolithic application - -Transforming an existing [monolithic application](https://en.wikipedia.org/wiki/Monolithic_application) into a distributed architecture is often more challenging than building a new federated application from scratch. - -However, it's also a **bad idea** to **start** a new application **with a distributed architecture** since teams typically lack sufficient understanding of the business domain at that stage. Therefore, for most applications, it makes sense to **begin as monolithic application** and transition to a distributed architecture later. - -With the introduction of [local modules](/reference/registration/registerLocalModules.md), Squide offers an alternative approach that lies between prior solutions. Instead of immediately embracing Team Topology's [stream-aligned teams](https://www.shortform.com/blog/stream-aligned-teams/) and striving for full team autonomy across the board, local modules allow teams to start with a [monorepo](https://en.wikipedia.org/wiki/Monorepo) setup and add independent local packages (modules) for each expected [value stream](https://en.wikipedia.org/wiki/Value_stream). - -Since adding/deleting local packages in a monorepo setup is pretty cheap, teams can freely reorganize their value streams along the way and won't **preemptively invest into a distributed** CI/CD **infrastructure** as local modules are part of the host application build. With independent **but local** value streams, teams will be well-positioned to transition toward a federated application once they can justify the cost. - -If your project is **already a monolithic application** with a [polyrepo setup](https://github.com/joelparkerhenderson/monorepo-vs-polyrepo#what-is-polyrepo) and you aim to migrate to a distributed architecture, we recommend a decoupling-first strategy using local modules and a monorepo setup. - -## Decoupling first strategy - -The primary challenge to migrate to a distributed architecture is coupling. Thus, for most applications, starting by decoupling the monolith into **composable value streams** could be the right strategy. It's a great way to get into the migration without the immediate need to update the CI/CD infrastructure or preemptively change developers' habits. - -We recommend the following steps: - -1. Transform the codebase into a monorepo setup. - -2. Create independent local packages (modules) for each identified value stream. - -3. Refactor the monolithic application code into the corresponding value stream local packages and ensure that each value stream [can be developed independently](develop-a-module-in-isolation.md) (e.g., without the need to start the entire application). - -4. Import and [register the local packages](/reference/registration/registerLocalModules.md) (modules) into the host application. - -5. Finally, transition from local modules to [remote modules](/reference/registration/registerRemoteModules.md) and update your CI/CD pipelines to enable independent deployment of modules. - -By following these steps, you can gradually decouple your monolithic application, create modular value streams, and prepare the foundation for a distributed architecture. diff --git a/docs/guides/migrate-to-firefly-v9.md b/docs/guides/migrate-to-firefly-v9.md new file mode 100644 index 000000000..79d09af2f --- /dev/null +++ b/docs/guides/migrate-to-firefly-v9.md @@ -0,0 +1,374 @@ +--- +order: 710 +label: Migrate to firefly v9 +--- + +# Migrate to firefly v9 + +This major version of `@squide/firefly` introduces [TanStack Query](https://tanstack.com/query/latest) as the official library for fetching the global data of a Squide's application and features a complete rewrite of the [AppRouter](../reference/routing/appRouter.md) component, which now uses a state machine to manage the application's bootstrapping flow. + +Prior to `v9`, Squide applications couldn't use TanStack Query to fetch global data, making it **challenging** for Workleap's applications to **keep** their **global data** in **sync** with the **server state**. With `v9`, applications can now leverage [custom wrappers](./fetch-global-data.md) of the [useQueries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) hook to fetch and keep their global data up-to-date with the server state. Additionally, the new [deferred registrations](../reference/registration/useDeferredRegistrations.md#register-or-update-deferred-registrations) update feature allows applications to even **keep** their conditional **navigation items in sync** with the **server state**. + +Finally, with `v9`, Squide's philosophy has evolved. We used to describe Squide as a shell for **federated** applications. Now, we refer to Squide as a shell for **modular** applications. After playing with Squide's [local module](../reference/registration/registerLocalModules.md) feature for a while, we discovered that Squide offers [significant value](../getting-started/default.md#why-squide) even for **non-federated applications**, which triggered this shift in philosophy. + +## Breaking changes + +### Removed + +- The `useAreModulesRegistered` hook has been removed, use the [useIsBootstrapping](../reference/routing/useIsBootstrapping.md) hook instead. +- The `useAreModulesReady` hook has been removed, use the [useIsBootstrapping](../reference/routing/useIsBootstrapping.md) hook instead. +- The `useIsMswStarted` hook has been removed, use the [useIsBootstrapping](../reference/routing/useIsBootstrapping.md) hook instead. +- The `completeModuleRegistrations` function as been removed use the [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hook instead. +- The `completeLocalModulesRegistrations` function has been removed use the [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hook instead. +- The `completeRemoteModuleRegistrations` function has been removed use the [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hook instead. +- The `useSession` hook has been removed, define your own React context instead. +- The `useIsAuthenticated` hook has been removed, define your own React context instead. +- The `sessionAccessor` option has been removed from the [FireflyRuntime](../reference/runtime/runtime-class.md) options, define your own React context instead. + +### Renamed + +- The `setMswAsStarted` function has been renamed to [setMswIsReady](../reference/msw/setMswAsReady.md). + +### Others + +- The `@squide/firefly` package now takes a peerDependency on `@tanstack/react-query`. +- The `@squide/firefly` package doesn't takes a peerDependency on `react-error-boundary` anymore. + +### Removed support for deferred routes + +[Deferred registration](../reference/registration/registerLocalModules.md#defer-the-registration-of-navigation-items) functions no longer support route registration; they are now **exclusively** used for **registering navigation items**. Since deferred registration functions can now be re-executed whenever the global data changes, registering routes in deferred registration functions no longer makes sense as updating the routes registry after the application has bootstrapped could lead to issues. + +This change is a significant improvement for Squide's internals, allowing us to eliminate quirks like: + +- Treating unknown routes as `protected`: When a user initially requested a deferred route, Squide couldn't determine if the route was `public` or `protected` because it wasn't registered yet. As a result, for that initial request, the route was considered `protected`, even if the deferred registration later registered it as `public`. + +- Mandatory wildcard `*` route registration: Previously, Squide's bootstrapping would fail if the application didn't include a wildcard route. + +Before: + +```tsx !#4-7 +export const register: ModuleRegisterFunction = runtime => { + return ({ featureFlags }) => { + if (featureFlags?.featureB) { + runtime.registerRoute({ + path: "/page", + element: + }); + + runtime.registerNavigationItem({ + $key: "page", + $label: "Page", + to: "/page" + }); + } + }; +} +``` + +Now: + +```tsx !#2-5 +export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + path: "/page", + element: + }); + + return ({ featureFlags }) => { + if (featureFlags?.featureB) { + runtime.registerNavigationItem({ + $key: "page", + $label: "Page", + to: "/page" + }); + } + }; +} +``` + +#### Conditional routes + +To handle direct access to a conditional route, each conditional route's endpoint should return a `403` status code if the user is not authorized to view the route. Those `403` errors should then be handled by the nearest error boundary. + +### Plugin's constructors now requires a runtime instance + +Prior to this release, plugin instances received the current runtime instance through a `_setRuntime` function. This approach caused issues because some plugins required a reference to the runtime at instantiation. To address this, plugins now receive the **runtime instance** directly as a **constructor** argument. + +Before: + +```tsx !#8-10 +export class MyPlugin extends Plugin { + readonly #runtime: Runtime; + + constructor() { + super(MyPlugin.name); + } + + _setRuntime(runtime: Runtime) { + this.#runtime = runtime; + } +} +``` + +Now: + +```tsx !#2 +export class MyPlugin extends Plugin { + constructor(runtime: Runtime) { + super(MyPlugin.name, runtime); + } +} +``` + +### Plugins now registers with a factory function + +Prior to this release, the [FireflyRuntime](../reference/runtime/runtime-class.md) accepted plugin instances as options. Now, `FireflyRuntime` accepts **factory functions** instead of plugin instances. This change allows plugins to receive the runtime instance as a constructor argument. + +Before: + +```tsx +const runtime = new FireflyRuntime({ + plugins: [new MyPlugin()] +}); +``` + +Now: + +```tsx +const runtime = new FireflyRuntime({ + plugins: [x => new MyPlugin(x)] +}); +``` + +### Rewrite of the `AppRouter` component + +This release features a full rewrite of the [AppRouter](../reference/routing/appRouter.md) component. The `AppRouter` component used to handle many concerns like global data fetching, deferred registrations, error handling and a loading state. Those concerns have been delegated to the consumer code, supported by the new [useIsBootstrapping](../reference/routing/useIsBootstrapping.md), [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md), [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) and [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hooks. + +Before: + +```tsx +export function App() { + const [featureFlags, setFeatureFlags] = useState(); + const [subscription, setSubscription] = useState(); + + const handleLoadPublicData = useCallback((signal: AbortSignal) => { + return fetchPublicData(setFeatureFlags, signal); + }, []); + + const handleLoadProtectedData = useCallback((signal: AbortController) => { + return fetchProtectedData(setSubscription, signal); + }, []); + + const handleCompleteRegistrations = useCallback(() => { + return completeModuleRegistrations(runtime, { + featureFlags, + subscription + }); + }, [runtime, featureFlags, subscription]); + + return ( + Loading...
        } + errorElement={} + waitForMsw + onLoadPublicData={handleLoadPublicData} + onLoadProtectedData={handleLoadProtectedData} + isPublicDataLoaded={!!featureFlags} + isPublicDataLoaded={!!subscription} + onCompleteRegistrations={handleCompleteRegistrations} + > + {(routes, providerProps) => ( + + )} + + ); +} +``` + +Now: + +```tsx +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); + const [subscription] = useProtectedDataQueries([getSubscriptionQuery]); + + const data: DeferredRegistrationData = useMemo(() => ({ + featureFlags, + subscription + }), [featureFlags, subscription]); + + useDeferredRegistrations(data); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: [ + { + element: , + children: registeredRoutes + } + ] + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +## New hooks and functions + +- A new [useIsBoostrapping](../reference/routing/useIsBootstrapping.md) hook is now available. +- A new [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hook is now available. +- A new [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md) hook is now available. +- A new [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hook is now available. +- A new [isGlobalDataQueriesError](../reference/tanstack-query/isGlobalDataQueriesError.md) function is now available. + +## Improvements + +- Deferred registration functions now always receive a `data` argument. +- Deferred registration functions now receives a new [operations](../reference/registration/registerLocalModules.md#use-the-deferred-registration-operation-argument) argument. +- Navigation items now include a [$canRender](../reference/runtime/runtime-class.md#conditionally-render-a-navigation-item) option, enabling modules to control whether a navigation item should be rendered. + +### New `$key` option for navigation items + +Navigation items now supports a new `$key` option. Previously, most navigation item React elements used a `key` property generated by concatenating the item's `level` and `index`, which goes against React's best practices: + +```tsx +
      • +``` + +It wasn't that much of a big deal since navigation items never changed once the application was bootstrapped. Now, with the deferred registration functions re-executing when the global data changes, the registered navigation items can be updated post-bootstrapping. The new `$key` option allows the navigation item to be configured with a unique key at registration. + +```tsx !#2 +runtime.registerNavigationItem({ + $key: "page-1", + $label: "Page 1", + to: "/page-1" +}); +``` + +The configured `$key` option is then passed as an argument to the [useRenderedNavigationItems](../reference/routing/useRenderedNavigationItems.md) rendering functions: + +```tsx !#1,5,13,15 +const renderItem: RenderItemFunction = (item, key) => { + const { label, linkProps, additionalProps } = item; + + return ( +
      • + + {label} + +
      • + ); +}; + +const renderSection: RenderSectionFunction = (elements, key) => { + return ( +
          + {elements} +
        + ); +}; + +const navigationElements = useRenderedNavigationItems(navigationItems, renderItem, renderSection); +``` + +## Migrate an host application + +The `v9` release introduces several breaking changes affecting the host application code. Follow these steps to migrate an existing host application: + +1. Add a dependency to `@tanstack/react-query`. [View example](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) +2. Transition to the new `AppRouter` component. [View example](#rewrite-of-the-approuter-component) + - `onLoadPublicData` + `isPublicDataLoaded` becomes [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md) + - `onLoadProtectedData` + `isProtectedDataLoaded` becomes [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) + - `onCompleteRegistrations` becomes [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) + - `fallbackElement` becomes [useIsBootstrapping](../reference/routing/useIsBootstrapping.md) + - `errorElement` is removed and somewhat replaced by a [root error boundary](#root-error-boundary) +3. Create a `TanStackSessionManager` class and the `SessionManagerContext`. Replace the session's deprecated hooks by creating the customs `useSession` and `useIsAuthenticated` hooks. [View example](./add-authentication.md#create-a-session-manager) +4. Remove the `sessionAccessor` option from the `FireflyRuntime` instance. Update the `BootstrappingRoute` component to create a `TanStackSessionManager` instance and share it down the component tree using a `SessionManagedContext` provider. [View example](./add-authentication.md#fetch-the-session) +5. Update the `AuthenticationBoundary` component to use the new `useIsAuthenticated` hook. [View example](./add-authentication.md#add-an-authentication-boundary) +6. Update the `AuthenticatedLayout` component to use the session manager instance to clear the session. Retrieve the session manager instance from the context defined in the `BootstrappingRoute` component using the `useSessionManager` hook. [View example](./add-authentication.md#define-an-authenticated-layout) +7. Update the `AuthenticatedLayout` component to use the new `$key` option of the navigation item. [View example](#new-key-option-for-navigation-items) +8. Convert all deferred routes into static routes. [View example](#removed-support-for-deferred-routes) +9. Add a `$key` option to the navigation item registrations. [View example](#new-key-option-for-navigation-items) + +### Root error boundary + +When transitioning to the new `AppRouter` component, make sure to nest the `RootErrorBoundary` component within the `AppRouter` component's render function. + +Before: + +```tsx !#6-7 +export const registerHost: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + element: , + children: [ + { + $name: "root-error-boundary", + errorElement: , + children: [ + ManagedRoutes + ] + } + ] + }); +}); +``` + +Now: + +```tsx !#12 +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +## Migrate a module + +The changes in `v9` have minimal impact on module code. To migrate an existing module, follow these steps: + +1. Convert all deferred routes into static routes. [View example](#removed-support-for-deferred-routes) +2. Add a `$key` option to the navigation item registrations. [View example](#new-key-option-for-navigation-items) diff --git a/docs/guides/override-a-react-context.md b/docs/guides/override-a-react-context.md index 4dee0d167..9bb3572ed 100644 --- a/docs/guides/override-a-react-context.md +++ b/docs/guides/override-a-react-context.md @@ -4,26 +4,32 @@ order: 780 # Override a React context -In a federated application using [Module Federation](https://module-federation.io/), it's typical to configure various global [React context](https://legacy.reactjs.org/docs/context.html) at the root of the host application. These contexts are usually consumed down the line by the layouts and pages of the remote modules. +In a modular application, it's typical to configure various global [React context](https://legacy.reactjs.org/docs/context.html) at the root of the host application. These contexts are then used by the layouts and pages of the modules. Let's explore a simple example using a `BackgroundColorContext`: ```tsx !#7 host/src/App.tsx import { AppRouter } from "@squide/firefly"; -import { BackgroundColorContext } from "@sample/shared"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; +import { BackgroundColorContext } from "@sample/shared"; export function App() { return ( - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={false} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }}
        ); @@ -56,7 +62,7 @@ export function ColoredPage() { } ``` -In the previous code samples, the host application provides a value for the `BackgroundColorContext`, and the `ColoredPage` component of the remote module utilizes this value to set its background color (in this example, the background color is set to `blue`). +In the previous code samples, the host application provides a value for the `BackgroundColorContext`, and the `ColoredPage` component of the remote module uses this value to set its background color (to `blue` for this example). ## Override the context for the remote module @@ -107,31 +113,41 @@ export const register: ModuleRegisterFunction = runtime => { ## Update a singleton dependency version +!!!warning +This section applies only to applications with [remote modules](../reference/registration/registerRemoteModules.md). +!!! + Let's consider a more specific use case where the host application declares a `ThemeContext` from Workleap's new design system, [Hopper](https://hopper.workleap.design/): ```tsx !#7 host/src/App.tsx import { AppRouter } from "@squide/firefly"; -import { ThemeContext } from "@hopper/components"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; +import { ThemeContext } from "@hopper/components"; export function App() { return ( - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={false} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }}
        ); } ``` -In this scenario, Hopper's components are used throughout the entire federated application, including the remote modules. Moreover, `@hopper/components` is defined as a [singleton](https://module-federation.io/configure/shared.html#singleton) shared dependency: +In this scenario, Hopper's components are used throughout the entire application, including the modules. Moreover, `@hopper/components` is defined as a [singleton](https://module-federation.io/configure/shared.html#singleton) shared dependency: ```js !#8-10 host/webpack.dev.js // @ts-check @@ -150,9 +166,9 @@ export default defineDevHostConfig(swcConfig, 8080, [], { Now, consider a situation where Hopper releases a new version of the package that includes breaking changes, without a "compatibility" package to ensure backward compatility with the previous version. -To update the host application without breaking the remote modules, the recommended approach is to temporary "break" the singleton shared dependency by loading two versions of the dependency in parallel (one for the host application and one for the remote modules that have not been updated yet). +To update the host application without breaking the modules, we recommend to temporary "break" the singleton shared dependency by loading two versions of the `@hopper/components` dependency in parallel (one for the host application and one for the modules that have not been updated yet). -As `@hopper/components` expose the `ThemeContext`, the context must be re-declared in each remote module until every part of the federated application has been updated to the latest version of Hopper: +As `@hopper/components` expose the `ThemeContext`, the context must be re-declared in each module until every part of the federated application has been updated to the latest version of `@hopper/components`: ```tsx !#6-12,17 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -176,4 +192,4 @@ export const register: ModuleRegisterFunction = runtime => { } ``` -Thankfully, [React Router](https://reactrouter.com/en/main) makes it very easy to declare contexts in a remote module. +Thankfully, [React Router](https://reactrouter.com/en/main) makes it very easy to declare contexts in a module. diff --git a/docs/guides/override-the-host-layout.md b/docs/guides/override-the-host-layout.md index ec2cdccd0..7cb89eb84 100644 --- a/docs/guides/override-the-host-layout.md +++ b/docs/guides/override-the-host-layout.md @@ -4,11 +4,11 @@ order: 880 # Override the host layout -The `RootLayout` component that as been defined in the [create an host application](../getting-started/create-host.md#navigation-items) starting guide serves as the default layout for the homepage as well as for every page registered by a module that are not nested under a parent route with either the [parentPath](../reference/runtime/runtime-class.md#register-nested-routes-under-an-existing-route) or the [parentName](../reference/runtime/runtime-class.md#register-a-named-route) option. +The `RootLayout` component defined in the [Create an host application](../getting-started/create-host.md#navigation-items) starting guide serves as the default layout for the homepage and all the [managed routes](../reference/routing/managedRoutes.md). -For most pages, this is the behavior expected by the author. However, for pages such as a login, the default `RootLayout` isn't suitable because the page is not bound to a user session (the user is not even authenticated yet). +For most routes, this behavior is what the author expects. However, as an application introduces [authentication](./add-authentication.md) and adds many session-related features to the default layout, this default layout may no longer be suitable for every route. For example, a login page doesn't require session-related features, as the user isn't authenticated yet. In such cases, the default layout isn't appropriate. -To accomodate pages that require a different layout, a mechanism is needed to move their route declaration at the root of the React Router [instance](https://reactrouter.com/en/main/routers/create-browser-router) before the `RootLayout` is declared. +To accomodate pages requiring a different layout, a mechanism is needed to move their route declaration to the root of the React Router [instance](https://reactrouter.com/en/main/routers/create-browser-router) before `RootLayout` is declared. ``` !#2 root @@ -18,19 +18,19 @@ root ├─────────── Homepage ``` -## Hoist a module pages +## Hoist a module routes Package managers supporting workspaces such as Yarn and NPM call this mechanism "hoisting", which means "raise (something) by means of ropes and pulleys". This is exactly what we are trying to achieve here. -Squide has a built-in [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) functionality capable of raising module routes marked as `hoist` at the root of the routes array, before the `RootLayout` declaration. Thus, an hoisted page will not be wrapped by the `RootLayout` (or the `AuthenticationBoundary`) and will have full control over its rendering. +Squide has a built-in [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) functionality capable of raising module routes marked as `hoist` at the root of the routes array, before the `RootLayout` declaration. Thus, an hoisted route will not be wrapped by the `RootLayout` component (or any authentication boundaries) and will have full control over its rendering. -To hoist module pages, add the [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) option to the route registration options and optionally use a different layout: +To hoist module routes, add the [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) option to the route registration options and optionally use a different layout: ```tsx !#9,14,24 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { LocalLayout } from "./LocalLayout.tsx"; import { LocalErrorBoundary } from "./LocalErrorBoundary.tsx"; -import { LoginPage } from "./LoginPage.tsx"; +import { Page } from "./Page.tsx"; export function register: ModuleRegisterFunction(runtime) { runtime.registerRoute({ @@ -38,13 +38,13 @@ export function register: ModuleRegisterFunction(runtime) { element: , children: [ { - // Custom error boundary ensuring errors from the login page doesn't prevent the other + // Custom error boundary ensuring errors from the route doesn't prevent the other // modules of the application from rendering. errorElement: , children: [ { index: true, - element: + element: } ] } @@ -56,11 +56,11 @@ export function register: ModuleRegisterFunction(runtime) { ``` !!!warning -By declaring a page as hoisted, other parts of the application will not be isolated anymore from this page's failures as the page will be rendered outside of the host application's root error boundary. To **avoid breaking the entire application** when an hoisted page encounters unhandled errors, it is highly recommended to declare a React Router's [errorElement](https://reactrouter.com/en/main/route/error-element) property for each hoisted page. +By declaring a route as hoisted, other parts of the application will not be isolated anymore from this route's failures as the route will most likely be rendered outside of the host application's root error boundary. To **avoid breaking the entire application** when an hoisted route encounters unhandled errors, it is highly recommended to declare a React Router's [errorElement](https://reactrouter.com/en/main/route/error-element) property for each hoisted routes. !!! !!!warning -By declaring a page as hoisted, the page will be rendered at the root of the router, therefore, most certainly outside the authenticated boundary of the application. If the hoisted page requires an authentication, make sure to **wrap the page with an authentication boundary** or to handle the authentication within the page. +By declaring a route as hoisted, the route will be rendered at the root of the router, therefore, most certainly outside the authenticated boundary of the application. If the hoisted route requires an authentication, make sure to **wrap the route with an authentication boundary** or to handle the authentication within the route's page. !!! ## Try it :rocket: diff --git a/docs/guides/setup-i18next.md b/docs/guides/setup-i18next.md index e5a47c9b8..693fb1cde 100644 --- a/docs/guides/setup-i18next.md +++ b/docs/guides/setup-i18next.md @@ -4,7 +4,7 @@ order: 820 # Setup i18next -Most of the applications that forms the Workleap platform are either already bilingual or will be in the future. To help feature teams with localized resources, Squide provides a native [plugin](../reference/i18next/i18nextPlugin.md) designed to adapt the [i18next](https://www.i18next.com/) library for federated applications. +Most Workleap's platform application are either already bilingual or will be in the future. To help feature teams deal with localized resources, Squide provides a native [plugin](../reference/i18next/i18nextPlugin.md) designed to adapt the [i18next](https://www.i18next.com/) library for federated applications. !!!warning The examples in this guide load all the resources from single localized resources files. For a real Workleap application, you probably want to spread the resources into multiple files and load the files with a i18next [backend plugin](https://www.i18next.com/overview/plugins-and-utils#backends). @@ -36,7 +36,7 @@ While you can use any package manager to develop an application with Squide, it Then, update the host application boostrapping code to register an instance of the [i18nextplugin](../reference/i18next/i18nextPlugin.md) with the [FireflyRuntime](../reference/runtime/runtime-class.md) instance: -```tsx !#16,19,22 host/src/bootstrap.tsx +```tsx !#13-22 host/src/bootstrap.tsx import { createRoot } from "react-dom/client"; import { ConsoleLogger, RuntimeContext, FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; import { App } from "./App.tsx"; @@ -48,17 +48,17 @@ const Remotes: RemoteDefinition[] = [ { url: name: "remote1" } ]; -// In this example: -// - The supported languages are "en-US" and "fr-CA" -// - The fallback language is "en-US" -// - The URL querystring parameter to detect the current language is "language" -const i18nextPlugin = new i18nextPlugin(["en-US", "fr-CA"], "en-US", "language"); - -// Always detect the user language early on. -i18nextPlugin.detectUserLanguage(); - const runtime = new FireflyRuntime({ - plugins: [i18nextPlugin] + plugins: [x => { + // In this example: + // - The supported languages are "en-US" and "fr-CA" + // - The fallback language is "en-US" + // - The URL querystring parameter to detect the current language is "language" + const i18nextPlugin = new i18nextPlugin(["en-US", "fr-CA"], "en-US", "language", undefined, x); + + // Always detect the user language early on. + i18nextPlugin.detectUserLanguage(); + }], loggers: [new ConsoleLogger()] }); @@ -99,7 +99,7 @@ Next, create the localized resource files for the `en-US` and `fr-CA` locales: ### Register an i18next instance -Then, update the [local module](../reference/registration/registerLocalModules.md) register function to create and register an instance of `i18next` with the `i18nextPlugin` plugin instance: +Then, update the host application local module's [register](../reference/registration/registerLocalModules.md) function to create and register an `i18next` instance with the retrieved `i18nextPlugin` instance. Due to how the internals of `i18next` works, each module (including the host application) must create its own instance of the third-party library. `i18nextPlugin` will handle synchronizing the language changes across all `i18next` instances: ```tsx !#12-14,16-23,26 host/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -138,7 +138,7 @@ export const registerHost: ModuleRegisterFunction = runtime => { }; ``` -In the previous code sample, notice that the `i18next` instance has been initialized with the current language of the `i18nextPlugin` instance by providing the `lng` option. If the user language has been detected during bootstrapping, the `i18next` instance will be initialized with the user language which has been deduced from either a `?language` querystring parameter or the user navigator language settings. Otherwise, the application instance will be initialized with the fallback language. +In the previous code sample, notice that the `i18next` instance has been initialized with the current language of the `i18nextPlugin` instance by providing the `lng` option. If the user language has been detected during bootstrapping, the `i18next` instance will then be initialized with the user language which has been deduced from either a `?language` querystring parameter or the user navigator language settings. Otherwise, the application instance will be initialized with the fallback language, which is `en-US` for this guide. ### Localize the home page resources @@ -161,7 +161,7 @@ export function HomePage() { ### Update the webpack configurations -Finally, update the webpack development and build configurations to activate the `i18next` feature: +Finally, update the webpack development and build configurations to activate the `i18next` feature. Enabling this feature will configure the `i18next` libraries as [shared dependencies](./add-a-shared-dependency.md): ```js !#7-9 host/webpack.dev.js // @ts-check @@ -249,7 +249,7 @@ Notice that this time, a standard `navigationItems` namespace has been added to ### Register an i18next instance -Then, update the [local module](../reference/registration/registerLocalModules.md) register function to create and register an instance of `i18next` with the `i18nextPlugin` plugin instance: +Then, update the remote module's [register](../reference/registration/registerLocalModules.md) function to create and register an instance of `i18next` with the `i18nextPlugin` plugin instance. Similarly to the [host application](#register-an-i18next-instance), due to how the internals of `i18next` works, this local module requires to register its own instance of the third-party library: ```tsx !#10,12-14,16-23,26 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -295,7 +295,7 @@ export const register: ModuleRegisterFunction = runtime => { ### Localize the navigation item labels -Then, localize the navigation items labels using the [I18nextNavigationItemLabel](../reference/i18next/I18nextNavigationItemLabel.md) component. Since for this example, the resources are in the `navigationItems` namespace, there's no need to specify a `namespace` property on the components as it will be inferred: +Then, localize the navigation items labels using the [I18nextNavigationItemLabel](../reference/i18next/I18nextNavigationItemLabel.md) component. Since this example resources are in the `navigationItems` namespace, there's no need to specify a `namespace` property on the components as it will be inferred: ```tsx !#37 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -342,7 +342,7 @@ export const register: ModuleRegisterFunction = runtime => { ### Localize the page resources -Then, update the `HomePage` component to use the newly created localized resource: +Then, update the `Page` component to use the newly created localized resource: ```tsx !#6,7,10 remote-module/src/Page.tsx import { useI18nextInstance } from "@squide/i18next"; @@ -361,7 +361,7 @@ export function Page() { ### Update the webpack configurations -Finally, update the webpack development and build configurations to activate the `i18next` feature: +Finally, update the webpack development and build configurations to activate the `i18next` feature. Enabling this feature will configure the `i18next` libraries as [shared dependencies](./add-a-shared-dependency.md): ```js !#7-9 remote-module/webpack.dev.js // @ts-check @@ -405,70 +405,98 @@ Follow the same steps as for a [remote module](#setup-a-remote-module). ## Integrate a backend language setting -For many applications, the displayed language is expected to be derived from an application specific user "preferred language" setting stored in a database on the backend. Therefore, the frontend remains unaware of this setting value until the user session is loaded. +For many applications, the displayed language is expected to be derived from an application specific user "preferred language" setting stored in a remote database. Therefore, the frontend remains unaware of this setting value until the user session is loaded. Hence, the strategy to select the displayed language should be as follow: -1. Utilize the language detected at bootstrapping for anonymous users (with the `detectUserLanguage` function). +1. Use the language detected at bootstrapping for anonymous users (with the [detectUserLanguage](../reference/i18next/i18nextPlugin.md#detect-the-user-language) function). 2. Upon user authentication and session loading, if a "preferred language" setting is available from the session data, update the displayed language to reflect this preference. -To implement this strategy, use the [useChangeLanguage](../reference/i18next/useChangeLanguage.md) hook and the [onLoadProtectedData](../reference/routing/appRouter.md#load-protected-data) handler of the [AppRouter](../reference/routing/appRouter.md) component: +This strategy can be implemented with the help of the [useChangeLanguage](../reference/i18next/useChangeLanguage.md) and [useProtectedDataQueries](../reference/tanstack-query/useProtectedDataQueries.md) hooks: -```tsx !#17,29,31-33,40-41 host/src/App.tsx -import { AppRouter } from "@squide/firefly"; -import { useChangeLanguage, useI18nextInstance } from "@squide/i18next"; -import { useCallback } from "react"; -import { useTranslation } from "react-i18next"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; +```tsx !#6-27,29,35 host/src/App.tsx +import { AppRouter, useProtectedDataQueries, useIsBootstrapping, useChangeLanguage } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { ApiError, isApiError, type Session } from "@sample/shared"; -async function fetchProtectedData(changeLanguage: (language: string) => void, setIsSessionLoaded: (isLoaded: boolean) => void, signal: AbortSignal) { - const response = await fetch("/api/session", { - signal - }); - - if (response.ok) { - const session = await response.json(); +function BootstrappingRoute() { + const [session] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const response = await fetch("/api/session"); - // When the session has been retrieved, change the displayed language to match - // the preferred language setting. - changeLanguage(session.preferredLanguage); + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } - setIsSessionLoaded(true); - } -} + const data = await response.json(); -export function App() { - const [isSessionLoaded, setIsSessionLoaded] = useState(false); + const result: Session = { + user: { + name: data.username, + } + }; - const i18nextInstance = useI18nextInstance("host"); - const { t } = useTranslation("App", { i18n: useI18nextInstance }); + return result; + } + } + ], error => isApiError(error) && error.status === 401); const changeLanguage = useChangeLanguage(); - const handleLoadProtectedData = useCallback((signal: AbortSignal) => { - return fetchProtectedData(changeLanguage, setIsSessionLoaded, signal); - }, [changeLanguage]); + useEffect(() => { + if (session) { + // When the session has been retrieved, update the language to match the user + // preferred language. + changeLanguage(session.user.preferredLanguage); + } + }, [session, changeLanguage]); + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function App() { return ( - {t("loadingMessage")}} - errorElement={
        {t("errorMessage")}
        } - waitForMsw={false} - onLoadProtectedData={handleLoadProtectedData} - isProtectedDataLoaded={isSessionLoaded} + - {(routes, providerProps) => ( - - )} + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } ``` +!!!info +The previous code sample assumes that your `@sample/shared` project includes the primitives created in the [Add authentication](./add-authentication.md) guide as well as the session Mock Server Worker request handlers. +!!! + ## Use the Trans component -The [Trans](https://react.i18next.com/latest/trans-component) component is valuable for scenarios that involve interpolation to render a localized resource. To use the `Trans` component with Squide, pair the component with an `i18next` instance retrieved from [useI18nextInstance](../reference/i18next/useI18nextInstance.md) hook: +The [Trans](https://react.i18next.com/latest/trans-component) component is useful for scenarios involving interpolation to render a localized resources. To use the `Trans` component with Squide, pair it with an `i18next` instance retrieved from [useI18nextInstance](../reference/i18next/useI18nextInstance.md) hook: ```tsx !#5,9,11 import { useI18nextInstance } from "@squide/i18next"; @@ -511,7 +539,7 @@ Start the development servers using the `dev` script. The homepage and the navig If you are experiencing issues with this guide: - Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each `i18next` instance that is being registered and another log everytime the language is changed: - - `[squide] Registered a new i18next instance with key "remote-module": ...` + - `[squide] Registered a new i18next instance with key "remote-module".` - `[squide] The language has been changed to "fr-CA".` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/guides/setup-msw.md b/docs/guides/setup-msw.md index 30702df3c..693752364 100644 --- a/docs/guides/setup-msw.md +++ b/docs/guides/setup-msw.md @@ -4,7 +4,7 @@ order: 1000 # Setup Mock Service Worker -To speed up frontend development and encourage an [API first](https://swagger.io/resources/articles/adopting-an-api-first-approach/) approach, Squide has built-in support for [Mock Service Worker](https://mswjs.io/) (MSW). MSW offers an API to host fake endpoints directly in the browser. This means that unlike alternative solutions, it doesn't require running an additional process to host fake endpoints. +To speed up frontend development and encourage an [API first](https://swagger.io/resources/articles/adopting-an-api-first-approach/) approach, Squide has built-in support for [Mock Service Worker](https://mswjs.io/) (MSW). MSW offers an API to host fake endpoints directly in the browser. This means that unlike alternative solutions, it doesn't require running an additional process. ## Setup the host application @@ -51,7 +51,7 @@ While you can use any package manager to develop an application with Squide, it Then, update the `dev` PNPM script to define with [cross-env](https://www.npmjs.com/package/cross-env) an `USE_MSW` environment variable that will [conditionally include MSW code](https://mswjs.io/docs/integrations/browser#conditionally-enable-mocking) into the application bundles: -```json package.json +```json host/package.json { "scripts": { "dev": "cross-env USE_MSW=true webpack serve --config webpack.dev.js" @@ -61,7 +61,7 @@ Then, update the `dev` PNPM script to define with [cross-env](https://www.npmjs. Then, update the development [webpack](https://webpack.js.org/) configuration file to include the `USE_MSW` environment variable into the application bundles: -```js !#14 webpack.dev.js +```js !#14 host/webpack.dev.js // @ts-check import { defineDevHostConfig } from "@squide/firefly-webpack-configs"; @@ -99,13 +99,15 @@ import { setupWorker } from "msw/browser"; export function startMsw(moduleRequestHandlers: RequestHandler[]) { const worker = setupWorker(...moduleRequestHandlers); - return worker.start(); + return worker.start({ + onUnhandledRequest: "bypass" + }); } ``` -Then, update the bootstrapping code to [start the service](https://mswjs.io/docs/integrations/browser#setup) and [mark MSW as started](../reference/msw/setMswAsStarted.md) if MSW is enabled: +Then, update the bootstrapping code to [start the service](https://mswjs.io/docs/integrations/browser#setup) and [set MSW as ready](../reference/msw/setMswAsReady.md) if MSW is enabled: -```tsx !#20-30 host/src/bootstrap.tsx +```tsx !#20-34 host/src/bootstrap.tsx import { createRoot } from "react-dom/client"; import { ConsoleLogger, RuntimeContext, FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; import { App } from "./App.tsx"; @@ -131,10 +133,14 @@ if (runtime.isMswEnabled) { const startMsw = (await import("../mocks/browser.ts")).startMsw; // Will start MSW with the modules request handlers. - startMsw(runtime.requestHandlers).then(() => { - // Indicate that MSW has been started and the routes can now be safely rendered. - setMswAsStarted(); - }); + startMsw(runtime.requestHandlers) + .then(() => { + // Indicate that MSW is ready and the routes can now be safely rendered. + setMswAsReady(); + }) + .catch((error: unknown) => { + consoleLogger.debug("[host-app] An error occured while starting MSW.", error); + }); } const root = createRoot(document.getElementById("root")!); @@ -146,24 +152,34 @@ root.render( ); ``` +!!!info +Be sure to `await` the `registerLocalModules` and `registerRemoteModules` functions; otherwise, MSW could be set as ready before all modules registered their request handlers. +!!! + ### Delay routes rendering until the service is started Finally, update the host application code to delay the rendering of the routes until MSW is started. This is done by setting the `waitForMsw` property of the [AppRouter](../reference/routing/appRouter.md) component to `true`: -```tsx !#9 host/src/App.tsx +```tsx !#6 host/src/App.tsx import { AppRouter } from "@squide/firefly"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; export function App() { return ( - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={!!process.env.USE_MSW} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }} ); } @@ -219,10 +235,6 @@ export const register: ModuleRegisterFunction = async runtime => } ``` -!!!info -Don't forget to mark the registration function as `async` since there's a dynamic import. -!!! - ## Setup a local module Follow the same steps as for a [remote module](#setup-a-remote-module). @@ -238,6 +250,7 @@ Update a page component code to fetch the `/api/character/1` fake API endpoint, If you are experiencing issues with this guide: - Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each request handlers registration that occurs and error messages if something went wrong: - - `[squide] The following MSW request handlers has been registered: ...` + - `[squide] The following MSW request handlers has been registered: [...]` + - `[squide] MSW is ready.` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/endpoints). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/guides/use-feature-flags.md b/docs/guides/use-feature-flags.md index eed134481..ee491b5e0 100644 --- a/docs/guides/use-feature-flags.md +++ b/docs/guides/use-feature-flags.md @@ -5,16 +5,16 @@ order: 840 # Use feature flags !!!warning -Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) and [Fetch initial data](./fetch-initial-data.md) guides. +Before going forward with this guide, make sure that you completed the [Setup Mock Service Worker](./setup-msw.md) and [Fetch global data](./fetch-global-data.md) guides. !!! -To continuously deliver value to our customers, Workleap has adopted a feature flags system that allows to activate or deactivate functionalities without requiring code deployment. While "in-page" feature flags are straightforward to implement for a Squide application, feature flags that conditionally register pages or navigation items requires a more advanced [deferred registration](../reference/registration/registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items) mechanism. +To continuously deliver value to our customers, Workleap has adopted a feature flag system that enables functionalities to be activated or deactivated without requiring a code deployment. While implementing "in-page" feature flags in a Squide application is straightforward, feature flags that conditionally register navigation items require a more advanced [deferred registration](../reference/registration/registerLocalModules.md#defer-the-registration-of-navigation-items) mechanism. ## Add an endpoint First, define a MSW request handler that returns the feature flags: -```ts mocks/handlers.ts +```ts host/mocks/handlers.ts import { HttpResponse, http, type HttpHandler } from "msw"; export const requestHandlers: HttpHandler[] = [ @@ -27,23 +27,12 @@ export const requestHandlers: HttpHandler[] = [ ]; ``` -Then, register the request handler using the module registration function: +Finally, register the request handler using the module registration function: -```tsx !#18,20 src/register.tsx +```tsx host/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import { Page } from "./Page.tsx"; export const register: ModuleRegisterFunction = async runtime => { - runtime.registerRoute({ - path: "/page", - element: - }); - - runtime.registerNavigationItem({ - $label: "Page", - to: "/page" - }); - if (runtime.isMswEnabled) { // Files that includes an import to the "msw" package are included dynamically to prevent adding // unused MSW stuff to the application bundles. @@ -56,7 +45,7 @@ export const register: ModuleRegisterFunction = async runtime => ### Create a shared context -Then, in a shared project, create a `FeatureFlagsContext`: +Now, in a shared project, create a `FeatureFlagsContext`: ```ts shared/src/featureFlagsContext.ts import { createContext, useContext } from "react"; @@ -79,59 +68,76 @@ Ensure that the shared project is configured as a [shared dependency](./add-a-sh ## Fetch the feature flags -Finally, open the host application code and update the `App` component to utilize the `AppRouter` component's `onLoadPublicData` handler to fetch the feature flags data: +Finally, open the host application code and update the `App` component to fetch the feature flags data with the [usePublicDataQueries](../reference/tanstack-query/usePublicDataQueries.md) hook: -```tsx !#24-26,29,31-32 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter } from "@squide/firefly"; +```tsx !#6-21,28 host/src/App.tsx +import { AppRouter, usePublicDataQueries, useIsBootstrapping } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; import { FeatureFlagsContext, type FeatureFlags } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; -async function fetchPublicData(setFeatureFlags: (featureFlags: FeatureFlags) => void, signal: AbortSignal) { - const response = await fetch("/api/feature-flags", { - signal - }); - - const data = await response.json(); +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([ + { + queryKey: ["/api/feature-flags"], + queryFn: async () => { + const response = await fetch("/api/feature-flags"); + const data = await response.json(); + + const flags: FeatureFlags = { + featureA: data.featureA, + featureB: data.featureB + }; + + return flags; + } + } + ]); - const featureFlags: FeatureFlags = { - featureA: data.featureA, - featureB: data.featureB - }; + if (useIsBootstrapping()) { + return
        Loading...
        ; + } - setFeatureFlags(featureFlags); + return ( + + + + ); } export function App() { - const [featureFlags, setFeatureFlags] = useState(); - - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFeatureFlags, signal); - }, []); - return ( - - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} -
        - + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + ); } ``` ## Conditionally render a page section -Now, let's use the `featureA` flag from `FeatureFlagsContext` to conditionally render a section of the `Page` component: +Now, let's use the `featureA` flag from `FeatureFlagsContext` to conditionally render a section of a new `Page` component. In this example, a section of the `Page` component will only be rendered if `featureA` is activated: -```tsx src/Page.tsx +```tsx remote/src/Page.tsx import { useFeatureFlags } from "@sample/shared"; export function Page() { @@ -146,21 +152,45 @@ export function Page() { } ``` -In the previous code sample, the section of the `Page` component will only be rendered if `featureA` is activated. +Then, register the `Page` component using the module registration function: + +```tsx remote/src/register.tsx +import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; +import { Page } from "./Page.tsx"; + +export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + path: "/page", + element: + }); + + runtime.registerNavigationItem({ + $key: "page", + $label: "Page", + to: "/page" + }); +} +``` + +!!!info +If you've already registered a `Page` component in a previous guide, use a different name for this component. +!!! + +## Conditionally register a navigation item -## Conditionally register a route +Conditionally registering navigation items based on a feature flag is more complex because Squide's default registration mechanism runs before the application has bootstrapped, meaning that the feature flags have not yet been fetched from the server. -Now, conditionally registering a route and it's navigation items based on a feature flag is more complex since the default registration mechanism is executed before the application has bootstrapped, meaning that the feature flags has not been fetched yet from the server. +To address this, Squide offers an alternate [deferred registration](../reference/registration/registerLocalModules.md#defer-the-registration-of-navigation-items) mechanism in two-phases: -To address this, Squide offers an alternate [deferred registration](../reference/registration/registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items) mechanism in two-phases: +1. The first phase allows modules to register their _static_ navigation items that are not dependent on initial data. -1. The first phase allows modules to register their routes and navigation items that are not dependent on initial data. +2. The second phase enables modules to register _deferred_ navigation items that are dependent on initial data. We refer to this second phase as **deferred registrations**. -2. The second phase enables modules to register routes and navigation items that are dependent on initial data. We refer to this second phase as **deferred registrations**. +To defer a registration to the second phase, a module's registration function can **return an anonymous function** matching the `DeferredRegistrationFunction` type: `(data, operation: "register" | "update") => Promise | void`. -To defer a registration to the second phase, a module registration function can **return an anonymous function**. Once the modules are registered and the [completeLocalModuleRegistrations](../reference/registration/completeRemoteModuleRegistrations.md) function is called, the deferred registration functions will be executed. +Once the modules are registered and the [useDeferredRegistrations](../reference/registration/useDeferredRegistrations.md) hook is rendered, the deferred registration functions will be executed with either `"register"` or `"update"` as the value for the `operation` argument, depending on whether this is the initial or subsequent execution of the functions. -First, let's update the module registration function to return an anonymous function that will receive the feature flags: +First, let's define a `DeferredRegistrationData` interface to a shared project, specifiying the initial data that module's deferred registration functions can expect: ```ts shared/src/deferredData.ts import { FeatureFlags } from "./featureFlagsContext.ts"; @@ -170,30 +200,25 @@ export interface DeferredRegistrationData { } ``` -```tsx !#15-28 src/register.tsx +Then, add `DeferredRegistrationData` to the `ModuleRegisterFunction` type definition and update the module `register` function to defer the registration of the `Page` component navigation item: + +```tsx !#5,12-21 src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import type { DeferredRegistrationData } from "@sample/shared"; import { Page } from "./Page.tsx"; -export const register: ModuleRegisterFunction = async runtime => { - if (runtime.isMswEnabled) { - // Files that includes an import to the "msw" package are included dynamically to prevent adding - // unused MSW stuff to the application bundles. - const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers; - - runtime.registerRequestHandlers(requestHandlers); - } +export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + path: "/page", + element: + }); // Return a deferred registration function. - return ({ featureFlags } = {}) => { - // Only register the "Page" route and navigation items if "featureB" is activated. + return ({ featureFlags }) => { + // Only register the "Page" navigation items if "featureB" is activated. if (featureFlags?.featureB) { - runtime.registerRoute({ - path: "/page", - element: - }); - runtime.registerNavigationItem({ + $key: "page", $label: "Page", to: "/page" }); @@ -202,64 +227,89 @@ export const register: ModuleRegisterFunction { + const response = await fetch("/api/feature-flags"); + const data = await response.json(); + + const flags: FeatureFlags = { + featureA: data.featureA, + featureB: data.featureB + }; + + return flags; + } + } + ]); -```tsx !#27-32,39 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter, useRuntime, completeModuleRegistrations } from "@squide/firefly"; -import { FeatureFlagsContext, type FeatureFlags } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; + // The useMemo is super important otherwise the hook will consider that the feature flags + // changed everytime the hook is rendered. + const data: DeferredRegistrationData = useMemo(() => ({ + featureFlags + }), [featureFlags]); -async function fetchPublicData(setFeatureFlags: (featureFlags: FeatureFlags) => void, signal: AbortSignal) { - const response = await fetch("/api/feature-flags"); - const data = await response.json(); + useDeferredRegistrations(data); - const featureFlags: FeatureFlags = { - featureA: data.featureA, - featureB: data.featureB - }; + if (useIsBootstrapping()) { + return
        Loading...
        ; + } - setFeatureFlags(featureFlags); + return ( + + + + ); } export function App() { - const [featureFlags, setFeatureFlags] = useState(); - - const runtime = useRuntime(); - - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFeatureFlags, signal); - }, []); - - const handleCompleteRegistrations = useCallback(() => { - // Provide the retrieved feature flags when completing the registration of the deferred registration. - return completeModuleRegistrations(runtime, { - featureFlags - }); - }, [runtime, featureFlags]); - return ( - - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} -
        - + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + ); } ``` +!!!info +A key feature of [TanStack Query](https://tanstack.com/query/latest) is its ability to keep the frontend state synchronized with the server state. To fully leverage this, whenever the data passed to `useDeferredRegistrations` changes, all deferred registration functions are re-executed. + +Remember to use [useMemo](https://react.dev/reference/react/useMemo) for your deferred registration data and to specify the `$key` option for your navigation items! +!!! + ## Try it :rocket: -Start the application using the `dev` and navigate to the `/page` page. The page should render with the conditonal section. Now, disable the `featureA` flag in the endpoint and refresh the page. You shouldn't see the conditonal section anymore. Finally, disable the `featureB` flag in the endpoint and refresh the page. The page shouldn't be available anymore. +Start the application using the `dev` and navigate to the `/page` page. The page should render with the conditonal section. Now, disable the `featureA` flag in the endpoint and refresh the page. You shouldn't see the conditonal section anymore. Finally, disable the `featureB` flag in the endpoint and refresh the page. The menu link labelled "Page" shouldn't be available anymore. If you are experiencing issues with this section of the guide: diff --git a/docs/guides/federated-tabs.md b/docs/guides/use-federated-tabs.md similarity index 80% rename from docs/guides/federated-tabs.md rename to docs/guides/use-federated-tabs.md index 8c085b556..b8e9d29f0 100644 --- a/docs/guides/federated-tabs.md +++ b/docs/guides/use-federated-tabs.md @@ -2,7 +2,7 @@ order: 860 --- -# Federated tabs +# Use federated tabs While it's typically recommended for a Squide application to maintain the boundary of a page within a single domain, there are situations where **enhancing** the **user experience** necessitates rendering a page with parts from **multiple domains**, or at the very least, simulating it 😊. @@ -18,7 +18,7 @@ For this guide, we'll take as an example a page for which the parts that are own ## Define a nested layout -To construct this page while adhering to Squide constraint of exclusively permitting route and navigation items exports from modules, let's begin by defining a React Router [nested layout](https://reactrouter.com/en/main/start/tutorial#nested-routes). This nested layout will be responsible for rendering all the tab headers and the content of the active tab: +To build this page while adhering to Squide's constraint of avoiding hard references to elements from other modules, let's start by defining a React Router [nested layout](https://reactrouter.com/en/main/start/tutorial#nested-routes). This nested layout will handle rendering all the tab headers and the content of the active tab: ```tsx !#9-11,15 remote-module-3/src/federated-tabs-layout.tsx import { Suspense } from "react"; @@ -43,7 +43,7 @@ export function FederatedTabsLayout() { } ``` -In the previous code sample, the `FederatedTabsLayout` is similar to the `RootLayout` introduced in previous guides. However, the key distinction is that this layout is nested under the `/federated-tabs` URL segment. By nesting the layout under a specific path, it will only render when the user navigates to one of the federated tab pages (e.g. `/federated-tabs/tab-1`, `/federated-tabs/tab-2`, `/federated-tabs/tab-3`). +In the previous code sample, the `FederatedTabsLayout` component is similar to the `RootLayout` component introduced in previous guides. However, the key distinction is that this layout will be bound to the `/federated-tabs` URL path. By nesting the layout under a specific path, it will only render when the user navigates to one of the federated tab pages (e.g. `/federated-tabs/tab-1`, `/federated-tabs/tab-2`, `/federated-tabs/tab-3`). To register the newly created layout as a nested layout, use the [registerRoute](../reference/runtime/runtime-class.md#register-routes) function: @@ -53,19 +53,20 @@ import { FederatedTabsLayout } from "./FederatedTabsLayout.tsx"; export const register: ModuleRegisterFunction = runtime => { runtime.registerRoute({ - // Register the layout as a nested layout under the "/federated-tabs" URL segment. + // Register the layout as a nested layout under the "/federated-tabs" URL path. path: "/federated-tabs", element: }); runtime.registerNavigationItem({ + $key: "federated-tabs", $label: "Federated tabs", to: "/federated-tabs" }); } ``` -With this nested layout in place, thanks to the React Router [Outlet](https://reactrouter.com/en/main/components/outlet) component, the content of the tabs can now reside in **distinct pages** (registered by different modules) while still delivering a **cohesive user experience**. Whenever a user navigates between the tabs, the URL will be updated, and the tab content will change, but the shared portion of the layout will remain consistent. +With this nested layout in place, thanks to the React Router [Outlet](https://reactrouter.com/en/main/components/outlet) component, the content of the tabs can now reside in **distinct routes** (registered by different modules) while still delivering a **cohesive user experience**. Whenever a user navigates between the tabs, the URL will be updated, and the tab content will change, but the shared portion of the layout will remain consistent. As a bonus, each individual tab will have its own dedicated URL! :partying_face: @@ -75,7 +76,7 @@ It is recommended to define the shared layouts in a standalone package as it's d ## Create the tab routes -Next, let's add the actual tab pages to the modules. To do so, we'll use the [parentPath](../reference/runtime/runtime-class.md#register-nested-routes-under-an-existing-route) option of the [registerRoute](../reference/runtime/runtime-class.md#register-routes) function to register the routes under the `FederatedTabsLayout`: +Next, let's add the actual tabs to the modules. To do so, we'll use the [parentPath](../reference/runtime/runtime-class.md#register-nested-routes-under-an-existing-route) option of the [registerRoute](../reference/runtime/runtime-class.md#register-routes) function to register the routes under the `FederatedTabsLayout` component: ```tsx !#7,10 remote-module-1/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; @@ -152,13 +153,13 @@ Now that the tabs has been registered, ensure that all four modules (including ` ## Decouple the navigation items -Althought it's functional, the modules are currently coupled by hardcoded URLs within the `FederatedTabsLayout`. +Althought it's functional, the modules are currently coupled by hardcoded URLs within the `FederatedTabsLayout` component. -To decouple the navigation items, similar to what is done for regular federated pages, we'll utilize the [registerNavigationItem](../reference/runtime/runtime-class.md#register-navigation-items) function. In this case, we'll also use the [menuId](../reference/runtime/runtime-class.md#register-navigation-items-for-a-specific-menu) option. Defining the `menuId` option will enable the `FederatedTabsLayout` to retrieve navigation items exclusively for the federated tab component. +To decouple the navigation items, similar to what is done for regular federated routes, we'll use the [registerNavigationItem](../reference/runtime/runtime-class.md#register-navigation-items) function. In this case, we'll specify a [menuId](../reference/runtime/runtime-class.md#register-navigation-items-for-a-specific-menu) option. Defining the `menuId` option will instruct the `FederatedTabsLayout` component to exclusively retrieve the navigation items that belongs to this layout. First, let's register the navigation items with the `menuId` option. For this example the `menuId` will be `/federated-tabs` (it can be anything): -```tsx !#19 remote-module-1/src/register.tsx +```tsx !#20 remote-module-1/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Tab1 } from "./Tab1.tsx"; @@ -172,6 +173,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "tab-1", $label: "Tab 1", to: "/federated-tabs" }, { @@ -182,7 +184,7 @@ export const register: ModuleRegisterFunction = runtime => { } ``` -```tsx !#20 remote-module-2/src/register.tsx +```tsx !#21 remote-module-2/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Tab2 } from "./Tab2.tsx"; @@ -197,6 +199,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "tab-2", $label: "Tab 2", to: "/federated-tabs/tab-2" }, { @@ -207,7 +210,7 @@ export const register: ModuleRegisterFunction = runtime => { } ``` -```tsx !#20 local-module/src/register.tsx +```tsx !#21 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Tab3 } from "./Tab3.tsx"; @@ -222,6 +225,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "tab-3", $label: "Tab 3", to: "/federated-tabs/tab-3" }, { @@ -232,7 +236,7 @@ export const register: ModuleRegisterFunction = runtime => { } ``` -Then, update the `FederatedTabsLayout` to render the registered navigation items instead of the hardcoded URLs: +Then, update the `FederatedTabsLayout` component to render the registered navigation items instead of the hardcoded URLs: ```tsx !#32 remote-module-3/src/federated-tabs-layout.tsx import { @@ -245,11 +249,11 @@ import { import { Suspense } from "react"; import { Link, Outlet } from "react-router-dom"; -const renderItem: RenderItemFunction = (item, index, level) => { +const renderItem: RenderItemFunction = (item, key) => { const { label, linkProps } = item as NavigationLinkRenderProps; return ( -
      • +
      • {label} @@ -289,7 +293,7 @@ Similarly to how the display order of regular navigation items can be configured To force `Tab 3` to be positioned first, we'll give him a priority of `999`: -```tsx !#15 local-module/src/register.tsx +```tsx !#16 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { Tab3 } from "./Tab3.tsx"; @@ -302,6 +306,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "tab-3", $label: "Tab 3", // Highest priority goes first. $priority: 999, @@ -321,7 +326,7 @@ To ensure everything is still working correctly, start the development servers u If you are experiencing issues with this guide: - Open the [DevTools](https://developer.chrome.com/docs/devtools/) console. You'll find a log entry for each registration that occurs and error messages if something went wrong: - - `[squide] The following route has been registered as a children of the "/federated-tabs" route. Newly registered item: ...` - - `[squide] The following navigation item has been registered to the "/federated-tabs" menu for a total of 1 item. Newly registered item: ...` + - `[squide] The following route has been registered as a children of the "/federated-tabs" route.` + - `[squide] The following static navigation item has been registered to the "/federated-tabs" menu for a total of 1 item.` - Refer to a working example on [GitHub](https://github.com/gsoft-inc/wl-squide/tree/main/samples/basic). - Refer to the [troubleshooting](../troubleshooting.md) page. diff --git a/docs/reference/default.md b/docs/reference/default.md index 7a0aeacc1..e36c57292 100644 --- a/docs/reference/default.md +++ b/docs/reference/default.md @@ -17,30 +17,27 @@ toc: ### Runtime - [FireflyRuntime class](./runtime/runtime-class.md) -- [RuntimeContext](./runtime/runtime-context.md) +- [RuntimeContext](./runtime/runtimeContext.md) - [useRuntime](./runtime/useRuntime.md) - [useRuntimeMode](./runtime/useRuntimeMode.md) - [useRoutes](./runtime/useRoutes.md) - [useNavigationItems](./runtime/useNavigationItems.md) - [useLogger](./runtime/useLogger.md) - [usePlugin](./runtime/usePlugin.md) -- [useSession](./runtime/useSession.md) ### Registration - [registerLocalModules](./registration/registerLocalModules.md) - [registerRemoteModules](./registration/registerRemoteModules.md) -- [completeModuleRegistrations](./registration/completeModuleRegistrations.md) -- [completeLocalModuleRegistrations](./registration/completeLocalModuleRegistrations.md) -- [completeRemoteModuleRegistrations](./registration/completeRemoteModuleRegistrations.md) -- [useAreModulesRegistered](./registration/useAreModulesRegistered.md) -- [useAreModulesReady](./registration/useAreModulesReady.md) +- [useDeferredRegistrations](./registration/useDeferredRegistrations.md) +- [mergeDeferredRegistrations](./registration/mergeDeferredRegistrations.md) ### Routing - [AppRouter](./routing/AppRouter.md) -- [ManagedRoutes](./routing/ManagedRoutes.md) +- [ManagedRoutes](./routing/managedRoutes.md) - [useRenderedNavigationItems](./routing/useRenderedNavigationItems.md) +- [useIsBoostrapping](./routing/useIsBootstrapping.md) - [useRouteMatch](./routing/useRouteMatch.md) - [useIsRouteProtected](./routing/useIsRouteProtected.md) - [resolveRouteSegments](./routing/resolveRouteSegments.md) @@ -57,10 +54,6 @@ toc: - [useEventBusDispatcher](./messaging/useEventBusDispatcher.md) - [useEventBusListener](./messaging/useEventBusListener.md) -### Session - -- [useIsAuthenticated](./session/useIsAuthenticated.md) - ### Plugins - [Plugin](./plugins/plugin.md) @@ -72,10 +65,15 @@ toc: - [defineBuildHostConfig](./webpack/defineBuildHostConfig.md) - [defineBuildRemoteModuleConfig](./webpack/defineBuildRemoteModuleConfig.md) +### TanStack Query + +- [usePublicDataQueries](./tanstack-query/usePublicDataQueries.md) +- [useProtectedDataQueries](./tanstack-query/useProtectedDataQueries.md) +- [isGlobalDataQueriesError](./tanstack-query/isGlobalDataQueriesError.md) + ### Mock Service Worker -- [useIsMswReady](./msw/useIsMswReady.md) -- [setMswAsStarted](./msw/setMswAsStarted.md) +- [setMswAsReady](./msw/setMswAsReady.md) ### i18next diff --git a/docs/reference/fakes/LocalStorageSessionManager.md b/docs/reference/fakes/LocalStorageSessionManager.md index ba1886ec4..be731b5e4 100644 --- a/docs/reference/fakes/LocalStorageSessionManager.md +++ b/docs/reference/fakes/LocalStorageSessionManager.md @@ -47,48 +47,3 @@ const session = sessionManager.getSession(); sessionManager.clearSession(); ``` -### Integrate with a runtime instance - -```ts !#8 host/src/session.ts -import type { SessionAccessorFunction } from "@squide/firefly"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { Session } from "@sample/share"; - -export const sessionManager = new LocalStorageSessionManager(); - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; -``` - -```tsx !#4,6-8 host/src/bootstrap.tsx -import { createRoot } from "react"; -import { FireflyRuntime, RuntimeContext } from "@squide/firefly"; -import { App } from "./App"; -import { sessionAccessor } from "./session"; - -const runtime = new FireflyRuntime({ - sessionAccessor -}); - -const root = createRoot(document.getElementById("root")); - -root.render( - - - -); -``` - -```tsx !#4 remote-module/src/UserProfile.tsx -import { useSession } from "@squide/firefly"; - -export function UserProfile() { - const session = useSession(); - - return ( - {session.userName} - ); -} -``` - diff --git a/docs/reference/fakes/readonlySessionLocalStorage.md b/docs/reference/fakes/ReadonlySessionLocalStorage.md similarity index 100% rename from docs/reference/fakes/readonlySessionLocalStorage.md rename to docs/reference/fakes/ReadonlySessionLocalStorage.md diff --git a/docs/reference/fakes/index.yaml b/docs/reference/fakes/index.yaml index f613fbf99..d89a6ce54 100644 --- a/docs/reference/fakes/index.yaml +++ b/docs/reference/fakes/index.yaml @@ -1 +1 @@ -order: -30 +order: -40 diff --git a/docs/reference/i18next/i18nextPlugin.md b/docs/reference/i18next/i18nextPlugin.md index e65ae122c..9a8a3c1bf 100644 --- a/docs/reference/i18next/i18nextPlugin.md +++ b/docs/reference/i18next/i18nextPlugin.md @@ -6,12 +6,12 @@ toc: # i18nextPlugin -A plugin to faciliate the integration of [i18next](https://www.i18next.com/) in a federated application. +A plugin to faciliate the integration of [i18next](https://www.i18next.com/) in a modular application. ## Reference ```ts -const plugin = new i18nextPlugin(supportedLanguages: [], fallbackLanguage, queryStringKey, options?: { detection?: {} }) +const plugin = new i18nextPlugin(supportedLanguages: [], fallbackLanguage, queryStringKey, options?: { detection? }) ``` ### Parameters diff --git a/docs/reference/i18next/index.yaml b/docs/reference/i18next/index.yaml index ccef837f2..44dadaf0e 100644 --- a/docs/reference/i18next/index.yaml +++ b/docs/reference/i18next/index.yaml @@ -1,2 +1,2 @@ -order: -20 +order: -30 label: "i18next" diff --git a/docs/reference/i18next/useChangeLanguage.md b/docs/reference/i18next/useChangeLanguage.md index 092263b00..fd4472074 100644 --- a/docs/reference/i18next/useChangeLanguage.md +++ b/docs/reference/i18next/useChangeLanguage.md @@ -20,7 +20,7 @@ None ### Returns -A function to change the current language of an `i18nextPlugin` instance. +A function to change the current language of an `i18nextPlugin` instance: `(newLanguage) => void`. ## Usage diff --git a/docs/reference/logging/index.yaml b/docs/reference/logging/index.yaml index fac3f4d28..32e7a83e6 100644 --- a/docs/reference/logging/index.yaml +++ b/docs/reference/logging/index.yaml @@ -1 +1 @@ -order: 50 +order: 40 diff --git a/docs/reference/messaging/EventBus.md b/docs/reference/messaging/EventBus.md index c5a7dd064..455b42f78 100644 --- a/docs/reference/messaging/EventBus.md +++ b/docs/reference/messaging/EventBus.md @@ -18,6 +18,12 @@ const eventBus = new EventBus(options?: { logger? }) - `options`: An optional object literal of options: - `logger`: An optional logger to facilitate debugging. +### Methods + +- `addListener(eventName, callback, options?)`: Register the `callback` event listener for `eventName`. +- `removeListener(eventName, callback, options?)`: Remove the `callback` event listener for `eventName`. +- `dispatch(eventName, payload?)`: Dispatch an event to the listeners of `eventName`. + ## Usage ### Create an event bus instance diff --git a/docs/reference/messaging/index.yaml b/docs/reference/messaging/index.yaml index 32e7a83e6..abb084c44 100644 --- a/docs/reference/messaging/index.yaml +++ b/docs/reference/messaging/index.yaml @@ -1 +1 @@ -order: 40 +order: 30 diff --git a/docs/reference/messaging/useEventBusDispatcher.md b/docs/reference/messaging/useEventBusDispatcher.md index b1684624d..b53ecd379 100644 --- a/docs/reference/messaging/useEventBusDispatcher.md +++ b/docs/reference/messaging/useEventBusDispatcher.md @@ -19,7 +19,7 @@ None ### Returns -A dispatch function. +A dispatch function: `(eventName: string, payload?: {}) => void`. ## Usage diff --git a/docs/reference/msw/index.yaml b/docs/reference/msw/index.yaml index 2ed6ceab4..cf92a684d 100644 --- a/docs/reference/msw/index.yaml +++ b/docs/reference/msw/index.yaml @@ -1,2 +1,2 @@ -order: -10 +order: -20 label: "Mock Service Worker" diff --git a/docs/reference/msw/setMswAsReady.md b/docs/reference/msw/setMswAsReady.md new file mode 100644 index 000000000..50b46d82a --- /dev/null +++ b/docs/reference/msw/setMswAsReady.md @@ -0,0 +1,25 @@ +# setMswAsReady + +Indicates to the [AppRouter](../routing/appRouter.md) that [Mock Service Worker](https://mswjs.io/) is ready and the application can safely be rendered. + +## Reference + +```ts +setMswAsReady() +``` + +### Parameters + +None + +### Returns + +Nothing + +## Usage + +```ts +import { setMswAsReady } from "@squide/firefly"; + +setMswAsReady(); +``` diff --git a/docs/reference/msw/setMswAsStarted.md b/docs/reference/msw/setMswAsStarted.md deleted file mode 100644 index 8ab127e61..000000000 --- a/docs/reference/msw/setMswAsStarted.md +++ /dev/null @@ -1,29 +0,0 @@ -# setMswAsStarted - -Indicates to the [useIsMswStarted](./useIsMswReady.md) hook that [Mock Service Worker](https://mswjs.io/) (MSW) is started and the application can safely be rendered. - -!!!info -This hook should be used in pair with either the [useIsMswReady](useIsMswReady.md) hook or the [AppRouter](../routing/appRouter.md) component. -!!! - -## Reference - -```ts -setMswAsStarted() -``` - -### Parameters - -None - -### Returns - -Nothing - -## Usage - -```ts -import { setMswAsStarted } from "@squide/firefly"; - -setMswAsStarted(); -``` diff --git a/docs/reference/msw/useIsMswReady.md b/docs/reference/msw/useIsMswReady.md deleted file mode 100644 index 02059fde4..000000000 --- a/docs/reference/msw/useIsMswReady.md +++ /dev/null @@ -1,31 +0,0 @@ -# useIsMswReady - -Force the application to re-render once [Mock Service Worker](https://mswjs.io/) (MSW) is started. Without this hook, the page is rendered before all the request handlers are registered to MSW which could results in 404 errors. - -!!!info -If your application is using the [AppRouter](../routing/appRouter.md) component, you shouldn't use this hook. -!!! - -## Reference - -```ts -const isMswReady = useIsMswReady(enabled) -``` - -### Parameters - -- `enabled`: Whether or not MSW is currently enabled for the application. This is especially useful to ensure the application is not waiting for MSW when in production. - -### Returns - -A boolean indicating if MSW is started. - -## Usage - -```ts -import { useIsMswStarted } from "@squide/firefly"; - -const isMswStarted = useIsMswStarted(process.env.USE_MSW); -``` - -[!ref Also take a look at the `setIsMswAsStarted` function](./setMswAsStarted.md) diff --git a/docs/reference/plugins/index.yaml b/docs/reference/plugins/index.yaml index f71550444..9a7d4cb3c 100644 --- a/docs/reference/plugins/index.yaml +++ b/docs/reference/plugins/index.yaml @@ -1,2 +1,2 @@ -order: 10 +order: 0 label: "Plugins" diff --git a/docs/reference/plugins/plugin.md b/docs/reference/plugins/plugin.md index c7d5e9fd1..33a5f593a 100644 --- a/docs/reference/plugins/plugin.md +++ b/docs/reference/plugins/plugin.md @@ -7,23 +7,24 @@ toc: An abstract base class to define a plugin. +## Protected members + +- `_runtime`: Access the plugin `Runtime` instance. + +## Getters + +- `name`: Return the name of the plugin. + ## Usage ### Define a plugin -```ts !#3 my-plugin/src/myPlugin.ts -import { Plugin, type FireflyRuntime } from "@squide/firefly"; +```ts my-plugin/src/myPlugin.ts +import { Plugin, type Runtime } from "@squide/firefly"; export class MyPlugin extends Plugin { - #runtime: FireflyRuntime; - - constructor() { - super(MyPlugin.name); - } - - // An optional method that can be implemented to get an hold on the current runtime instance. - _setRuntime(runtime: FireflyRuntime) { - this.#runtime = runtime; + constructor(runtime: Runtime) { + super(MyPlugin.name, runtime); } } ``` @@ -35,10 +36,26 @@ import { FireflyRuntime } from "@squide/firefly"; import { MyPlugin } from "@sample/my-plugin"; const runtime = new FireflyRuntime({ - plugins: [new MyPlugin()] + plugins: [x => new MyPlugin(x)] }); ``` +### Use a plugin runtime instance + +```ts !#9 my-plugin/src/myPlugin.ts +import { Plugin, type Runtime } from "@squide/firefly"; + +export class MyPlugin extends Plugin { + constructor(runtime: Runtime) { + super(MyPlugin.name, runtime); + } + + sayHello() { + this._runtime.logger.debug("Hello!"); + } +} +``` + ### Retrieve a plugin from a runtime instance ```ts @@ -52,11 +69,11 @@ const myPlugin = runtime.getPlugin(MyPlugin.name) as MyPlugin; We recommend pairing a plugin definition with a custom function to retrieve the plugin from a runtime instance. ```ts !#9-11 my-plugin/src/myPlugin.ts -import { Plugin, type FireflyRuntime } from "@squide/firefly"; +import { Plugin, type Runtime } from "@squide/firefly"; -export class MyPlugin extends FireflyRuntime { - constructor() { - super(MyPlugin.name); +export class MyPlugin extends Plugin { + constructor(runtime: Runtime) { + super(MyPlugin.name, runtime); } } diff --git a/docs/reference/registration/completeLocalModuleRegistrations.md b/docs/reference/registration/completeLocalModuleRegistrations.md deleted file mode 100644 index e61bc6692..000000000 --- a/docs/reference/registration/completeLocalModuleRegistrations.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -toc: - depth: 2-3 -order: 70 ---- - -# completeLocalModuleRegistrations - -Completes the registration process for modules that have been registred using [registerLocalModules](./registerLocalModules.md) by executing the registered **deferred registration** functions. - -!!!info -This function should only be used by applications that support [deferred registrations](./registerLocalModules.md#defer-the-registration-of-routes-or-navigation-items). -!!! - -## Reference - -```ts -completeLocalModuleRegistrations(runtime, data?) -``` - -### Parameters - -- `runtime`: A `FireflyRuntime` instance. -- `data`: An optional object with data to forward to the deferred registration functions. - -### Returns - -A `Promise` object with an array of `LocalModuleRegistrationError` if any error happens during the completion of the local modules registration process. - -- `LocalModuleRegistrationError`: - - `error`: The original error object. - -## Usage - -### Complete local module registrations - -```tsx !#11,14 host/src/bootstrap.tsx -import { completeLocalModuleRegistrations, registerLocalModules, FireflyRuntime } from "@squide/firefly"; -import { register } from "@sample/local-module"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -await registerLocalModules([register], runtime); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -// Complete the local module registrations with the feature flags data. -await completeLocalModuleRegistrations(runtime, { featureFlags }); -``` - -```tsx !#19-32 local-module/src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import type { DeferredRegistrationData } from "@sample/shared"; -import { AboutPage } from "./AboutPage.tsx"; -import { FeatureAPage } from "./FeatureAPage.tsx"; - -export const register: ModuleRegisterFunction = async runtime => { - runtime.registerRoute({ - path: "/about", - element: - }); - - runtime.registerNavigationItem({ - $label: "About", - to: "/about" - }); - - // Once the feature flags has been loaded by the host application, by completing the module registrations process, - // the deferred registration function will be called with the feature flags data. - return ({ featureFlags } = {}) => { - // Only register the "feature-a" route and navigation item if the feature is active. - if (featureFlags.featureA) { - runtime.registerRoute({ - path: "/feature-a", - element: - }); - - runtime.registerNavigationItem({ - $label: "Feature A", - to: "/feature-a" - }); - } - }; -} -``` - -### Handle the completion errors - -```tsx !#13-15 host/src/bootstrap.tsx -import { completeLocalModuleRegistrations, registerLocalModules, FireflyRuntime } from "@squide/firefly"; -import { register } from "@sample/local-module"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -await registerLocalModules([register], runtime, { context }); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -await (completeLocalModuleRegistrations(runtime, { featureFlags })).forEach(x => { - console.log(x); -}); -``` diff --git a/docs/reference/registration/completeModuleRegistrations.md b/docs/reference/registration/completeModuleRegistrations.md deleted file mode 100644 index c92001a3f..000000000 --- a/docs/reference/registration/completeModuleRegistrations.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -toc: - depth: 2-3 -order: 80 ---- - -# completeModuleRegistrations - -Completes the registration process for modules that have been registred using [registerLocalModules](./registerLocalModules.md) and [registerRemoteModules](./registerRemoteModules.md) by executing the registered **deferred registration** functions. - -!!!info -This function should only be used by applications that support [deferred registrations](./registerLocalModules.md#defer-the-registration-of-routes-or-navigation-items). -!!! - -## Reference - -```ts -completeModuleRegistrations(runtime, data?) -``` - -### Parameters - -- `runtime`: A `FireflyRuntime` instance. -- `data`: An optional object with data to forward to the deferred registration functions. - -### Returns - -- A `Promise` object with the following properties: - - `localModuleErrors`: An array of [LocalModuleRegistrationError](./completeLocalModuleRegistrations.md#returns) if any error happens during the completion of the local modules registration process. - - `remoteModuleErrors`: An array of [RemoteModuleRegistrationError](./completeRemoteModuleRegistrations.md#returns) if any error happens during the completion of the remote modules registration process. - -## Usage - -### Complete module registrations - -```tsx !#11-12,19 host/src/bootstrap.tsx -import { registerLocalModules, FireflyRuntime, completeModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { register } from "@sample/local-module"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerLocalModules([register], runtime); -await registerRemoteModules(Remotes, runtime); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -// Complete the local module and remote module registrations with the feature flags data. -await completeModuleRegistrations(runtime, { featureFlags }); -``` - -```tsx !#19-32 remote-module/src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import type { DeferredRegistrationData } from "@sample/shared"; -import { AboutPage } from "./AboutPage.tsx"; -import { FeatureAPage } from "./FeatureAPage.tsx"; - -export const register: ModuleRegisterFunction = async runtime => { - runtime.registerRoute({ - path: "/about", - element: - }); - - runtime.registerNavigationItem({ - $label: "About", - to: "/about" - }); - - // Once the feature flags has been loaded by the host application, by completing the module registrations process, - // the deferred registration function will be called with the feature flags data. - return ({ featureFlags } = {}) => { - // Only register the "feature-a" route and navigation item if the feature is active. - if (featureFlags.featureA) { - runtime.registerRoute({ - path: "/feature-a", - element: - }); - - runtime.registerNavigationItem({ - $label: "Feature A", - to: "/feature-a" - }); - } - }; -} -``` - -### Handle the completion errors - -```tsx !#18-26 host/src/bootstrap.tsx -import { registerLocalModules, FireflyRuntime, completeModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { register } from "@sample/local-module"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerLocalModules([register], runtime); -await registerRemoteModules(Remotes, runtime); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -const errors = await completeModuleRegistrations(runtime, { featureFlags }); - -errors.localModuleErrors.forEach(x => { - console.log(x); -}); - -errors.remoteModuleErrors.forEach(x => { - console.log(x); -}); -``` diff --git a/docs/reference/registration/completeRemoteModuleRegistrations.md b/docs/reference/registration/completeRemoteModuleRegistrations.md deleted file mode 100644 index bdfcfa6ed..000000000 --- a/docs/reference/registration/completeRemoteModuleRegistrations.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -toc: - depth: 2-3 -order: 60 ---- - -# completeRemoteModuleRegistrations - -Completes the registration process for modules that have been registred using [registerRemoteModules](./registerRemoteModules.md) by executing the registered **deferred registration** functions. - -!!!info -This function should only be used by applications that support [deferred registrations](./registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items). -!!! - -## Reference - -```ts -completeRemoteModuleRegistrations(runtime, data?) -``` - -### Parameters - -- `runtime`: A `FireflyRuntime` instance. -- `data`: An optional object with data to forward to the deferred registration functions. - -### Returns - -A `Promise` object with an array of `RemoteModuleRegistrationError` if any error happens during the completion of the remote modules registration process. - -- `RemoteModuleRegistrationError`: - - `remoteName`: The name of the remote module that failed to load. - - `moduleName`: The name of the [module](./registerRemoteModules.md#name) that Squide attempted to recover. - - `error`: The original error object. - -## Usage - -### Complete remote module registrations - -```tsx !#14,17 host/src/bootstrap.tsx -import { FireflyRuntime, completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerRemoteModules(Remotes, runtime); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -// Complete the remote module registrations with the feature flags data. -await completeRemoteModuleRegistrations(runtime, { featureFlags }); -``` - -```tsx !#19-32 remote-module/src/register.tsx -import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; -import type { DeferredRegistrationData } from "@sample/shared"; -import { AboutPage } from "./AboutPage.tsx"; -import { FeatureAPage } from "./FeatureAPage.tsx"; - -export const register: ModuleRegisterFunction = async runtime => { - runtime.registerRoute({ - path: "/about", - element: - }); - - runtime.registerNavigationItem({ - $label: "About", - to: "/about" - }); - - // Once the feature flags has been loaded by the host application, by completing the module registrations process, - // the deferred registration function will be called with the feature flags data. - return ({ featureFlags } = {}) => { - // Only register the "feature-a" route and navigation item if the feature is active. - if (featureFlags.featureA) { - runtime.registerRoute({ - path: "/feature-a", - element: - }); - - runtime.registerNavigationItem({ - $label: "Feature A", - to: "/feature-a" - }); - } - }; -} -``` - -### Handle the completion errors - -```tsx !#16-18 host/src/bootstrap.tsx -import { FireflyRuntime, completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { fetchFeatureFlags } from "@sample/shared"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerRemoteModules(Remotes, runtime); - -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); - -await (completeRemoteModuleRegistrations(runtime, { featureFlags })).forEach(x => { - console.log(x); -}); -``` - diff --git a/docs/reference/registration/mergeDeferredRegistrations.md b/docs/reference/registration/mergeDeferredRegistrations.md index ea7624608..449354ec1 100644 --- a/docs/reference/registration/mergeDeferredRegistrations.md +++ b/docs/reference/registration/mergeDeferredRegistrations.md @@ -6,7 +6,7 @@ order: -100 # mergeDeferredRegistrations -Utility function that takes an array of [deferred registration](./registerLocalModules.md#defer-the-registration-of-routes-or-navigation-items) functions and returns a single function wrapping and merging all the provided deferred registration functions. +Utility function that takes an array of [deferred registration](./registerLocalModules.md#defer-the-registration-of-navigation-items) functions and returns a single function wrapping and merging all the provided deferred registration functions. If the provided array contains `undefined` values, they will safely be ignored. @@ -18,7 +18,7 @@ mergeDeferredRegistrations(candidates: []); ### Parameters -- `candidates`: An array of [deferred registration](./registerLocalModules.md#defer-the-registration-of-routes-or-navigation-items) functions, `undefined` values will safely be ignored. +- `candidates`: An array of [deferred registration](./registerLocalModules.md#defer-the-registration-of-navigation-items) functions. ### Returns @@ -30,9 +30,9 @@ A function or `undefined`: ## Usage -```tsx shell/src/register.tsx +```tsx host/src/register.tsx import { mergeDeferredRegistrations, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; -import { registerLayouts } from "@sample/layouts"; +import { registerLayouts } from "./registerLayouts.tsx"; import { registerAppShell } from "./registerAppShell.tsx"; function registerRoutes(runtime: FireflyRuntime) { diff --git a/docs/reference/registration/registerLocalModules.md b/docs/reference/registration/registerLocalModules.md index ca55727f3..650b9641b 100644 --- a/docs/reference/registration/registerLocalModules.md +++ b/docs/reference/registration/registerLocalModules.md @@ -6,9 +6,9 @@ order: 100 # registerLocalModules -Register one or many local module(s). During the registration process, the specified registration function will be invoked with a `FireflyRuntime` instance and an optional `context` object. To **defer the registration** of specific routes or navigation items, a registration function can return an anonymous function. +Register one or many local module(s). During the registration process, the specified registration function will be invoked with a `FireflyRuntime` instance and an optional `context` object. To **defer the registration** of specific navigation items, a registration function can return an anonymous function. -> A local module is a regular module that is part of the **host application build** and is bundled at build time, as opposed to remote module which is loaded at runtime from a remote server. Local modules are particularly valuable when undergoing a **migration** from a monolithic application to a federated application or when **launching a new product** with an evolving business domain. +> A local module is a regular module that is part of the **host application build** and is bundled at build time, as opposed to remote module which is loaded at runtime from a remote server. Local modules are particularly valuable when **launching a new product** with an evolving business domain or when undergoing a **migration** from a monolithic application to a federated application. ## Reference @@ -27,8 +27,9 @@ registerLocalModules(registerFunctions: [], runtime, options?: { context? }) A `Promise` object with an array of `LocalModuleRegistrationError` if any error happens during the registration. -- `LocalModuleRegistrationError`: - - `error`: The original error object. +#### `LocalModuleRegistrationError` + +- `error`: The original `Error` object. ## Usage @@ -43,78 +44,141 @@ const runtime = new FireflyRuntime(); await registerLocalModules([register], runtime); ``` -```tsx !#5-8,10-13 local-module/src/register.tsx +```tsx !#5-8,10-14 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { AboutPage } from "./AboutPage.tsx"; -export const register: ModuleRegisterFunction = async runtime => { +export const register: ModuleRegisterFunction = runtime => { runtime.registerRoute({ path: "/about", element: }); runtime.registerNavigationItem({ + $key: "about", $label: "About", to: "/about" }); } ``` -### Defer the registration of routes or navigation items +### Defer the registration of navigation items + +Sometimes, data must be fetched to determine which navigation items should be registered by a given module. To address this, Squide offers a **two-phase registration mechanism**: -Sometimes, data must be fetched to determine which routes or navigation items should be registered by a given module. To address this, Squide offers a **two-phase registration mechanism**: +1. The first phase allows modules to register their navigation items that are **not dependent on initial data** (in addition to their routes and MSW request handlers when fake endpoints are available). -1. The first phase allows modules to register their routes and navigation items that are not dependent on initial data (in addition to their MSW request handlers when fake endpoints are available). +2. The second phase enables modules to register navigation items that are dependent on initial data. Such a use case would be determining whether a navigation item should be registered based on a feature flag. We refer to this second phase as **deferred registrations**. -2. The second phase enables modules to register routes and navigation items that are dependent on initial data. Such a use case would be determining whether a route should be registered based on a feature flag. We refer to this second phase as **deferred registrations**. +To defer a registration to the second phase, a module registration function can **return an anonymous function** matching the `DeferredRegistrationFunction` type: `(data, operation: "register" | "update") => Promise | void`. -To defer a registration to the second phase, a module registration function can **return an anonymous function**. Once the modules are registered and the [completeLocalModuleRegistrations](./completeLocalModuleRegistrations.md) function is called, the deferred registration functions will be executed. +Once the modules are registered, the deferred registration functions will be executed with the deferred data and `"register"` as the value for the `operation` argument. Afterward, whenever the deferred data changes, the deferred registration functions will be re-executed with the updated deferred data and `"update"` as the value for the `operation` argument. -```tsx !#11,14 host/src/bootstrap.tsx -import { completeLocalModuleRegistrations, registerLocalModules, FireflyRuntime } from "@squide/firefly"; +```tsx !#8 host/src/bootstrap.tsx +import { FireflyRuntime, registerLocalModules, RuntimeContext } from "@squide/firefly"; +import { createRoot } from "react"; import { register } from "@sample/local-module"; -import { fetchFeatureFlags } from "@sample/shared"; +import { App } from "./App.tsx"; const runtime = new FireflyRuntime(); await registerLocalModules([register], runtime); -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); +const root = createRoot(document.getElementById("root")!); + +root.render( + + + +); +``` + +```tsx !#12-16 host/src/AppRouter.tsx +import { usePublicDataQueries, useDeferredRegistrations, useIsBootstrapping, AppRouter as FireflyAppRouter } from "@squide/firefly"; +import { useMemo } from "react"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import type { DeferredRegistrationData } from "@sample/shared"; +import { getFeatureFlagsQuery } from "./getFeatureFlagsQuery.ts"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); -// Complete the module registrations with the feature flags data. -await completeLocalModuleRegistrations(runtime, { featureFlags }); + // The useMemo is super important otherwise the hook will consider that the feature flags + // changed everytime the hook is rendered. + const data: DeferredRegistrationData = useMemo(() => ({ + featureFlags + }), [featureFlags]); + + useDeferredRegistrations(data); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function AppRouter() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} ``` -```tsx !#19-32 local-module/src/register.tsx +Routes are always registered, but navigation items can be conditionally registered using a deferred registration function. + +```tsx !#21-24,28-37 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import type { DeferredRegistrationData } from "@sample/shared"; import { AboutPage } from "./AboutPage.tsx"; import { FeatureAPage } from "./FeatureAPage.tsx"; -export const register: ModuleRegisterFunction = async runtime => { +export const register: ModuleRegisterFunction = runtime => { runtime.registerRoute({ path: "/about", element: }); runtime.registerNavigationItem({ + $key: "about", $label: "About", to: "/about" }); + // Routes are always registered. If a route may not be available for a group of users, conditionally register + // its navigation item with a deferred registration. + // To manage direct hits to a conditional route, render an error boundary whenever the route's endpoint returns a 401 status code. + runtime.registerRoute({ + path: "/feature-a", + element: + }); + // Once the feature flags has been loaded by the host application, by completing the module registrations process, // the deferred registration function will be called with the feature flags data. - return ({ featureFlags } = {}) => { + return ({ featureFlags }) => { // Only register the "feature-a" route and navigation item if the feature is active. if (featureFlags.featureA) { - runtime.registerRoute({ - path: "/feature-a", - element: - }); - runtime.registerNavigationItem({ + $key: "feature-a", $label: "Feature A", to: "/feature-a" }); @@ -123,9 +187,52 @@ export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + path: "/about", + element: + }); + + runtime.registerNavigationItem({ + $key: "about", + $label: "About", + to: "/about" + }); + + // Routes are always registered. If a route may not be available for a group of users, conditionally register + // its navigation item with a deferred registration. + // To manage direct hits to a conditional route, render an error boundary whenever the route's endpoint returns a 401 status code. + runtime.registerRoute({ + path: "/feature-a", + element: + }); + + // Once the feature flags has been loaded by the host application, by completing the module registrations process, + // the deferred registration function will be called with the feature flags data. + return ({ featureFlags }, operation) => { + // Only register the "feature-a" route and navigation item if the feature is active. + if (featureFlags.featureA) { + runtime.registerNavigationItem({ + $key: "feature-a", + $label: operation === "register" ? "Feature A" : "Feature A updated", + to: "/feature-a" + }); + } + }; +} +``` -### Handle the registration errors +### Handle registration errors ```tsx !#6-8 host/src/bootstrap.tsx import { registerLocalModules, FireflyRuntime } from "@squide/firefly"; @@ -134,6 +241,6 @@ import { register } from "@sample/local-module"; const runtime = new FireflyRuntime(); (await registerLocalModules([register], runtime)).forEach(x => { - console.log(x); + console.error(x); }); ``` diff --git a/docs/reference/registration/registerRemoteModules.md b/docs/reference/registration/registerRemoteModules.md index 66a7756f2..dd0eda037 100644 --- a/docs/reference/registration/registerRemoteModules.md +++ b/docs/reference/registration/registerRemoteModules.md @@ -6,7 +6,7 @@ order: 90 # registerRemoteModules -Register one or many remote module(s). During the registration process, the module `register` function will be invoked with a `FireflyRuntime` instance and an optional `context` object. To **defer the registration** of specific routes or navigation items, a registration function can return an anonymous function. +Register one or many remote module(s). During the registration process, the module `register` function will be invoked with a `FireflyRuntime` instance and an optional `context` object. To **defer the registration** of navigation items, a registration function can return an anonymous function. > A remote module is a module that is not part of the current build but is **loaded at runtime** from a remote server. @@ -18,7 +18,7 @@ registerRemoteModules(remotes: [], runtime, options?: { context? }) ### Parameters -- `remotes`: An array of `RemoteDefinition` (view the [Remote definition](#remote-definition) section). +- `remotes`: An array of [RemoteDefinition](#remote-definition). - `runtime`: A `FireflyRuntime` instance. - `options`: An optional object literal of options: - `context`: An optional context object that will be pass to the registration function. @@ -27,17 +27,20 @@ registerRemoteModules(remotes: [], runtime, options?: { context? }) A `Promise` object with an array of `RemoteModuleRegistrationError` if any error happens during the registration. -- `RemoteModuleRegistrationError`: - - `remoteName`: The name of the remote module that failed to load. - - `moduleName`: The name of the [module](#name) that Squide attempted to recover. - - `error`: The original error object. +#### `RemoteModuleRegistrationError` + +- `remoteName`: The name of the remote module that failed to load. +- `moduleName`: The name of the [module](#name) that Squide attempted to recover. +- `error`: The original `Error` object. ## Usage ### Register a remote module -```tsx !#5-7,9 host/src/bootstrap.tsx -import { FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; +```tsx !#7-9,11 host/src/bootstrap.tsx +import { FireflyRuntime, registerRemoteModules, RuntimeContext, type RemoteDefinition } from "@squide/firefly"; +import { createRoot } from "react"; +import { App } from "./App.tsx"; const runtime = new FireflyRuntime(); @@ -46,38 +49,51 @@ const Remotes: RemoteDefinition = [ ]; await registerRemoteModules(Remotes, runtime); + +const root = createRoot(document.getElementById("root")!); + +root.render( + + + +); ``` -```tsx !#5-8,10-13 remote-module/src/register.tsx +```tsx !#5-8,10-14 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import { AboutPage } from "./AboutPage.tsx"; -export const register: ModuleRegisterFunction = async runtime => { +export const register: ModuleRegisterFunction = runtime => { runtime.registerRoute({ path: "/about", element: }); runtime.registerNavigationItem({ + $key: "about", $label: "About", to: "/about" }); } ``` -### Defer the registration of routes or navigation items +### Defer the registration of navigation items -Sometimes, data must be fetched to determine which routes or navigation items should be registered by a given module. To address this, Squide offers a **two-phase registration mechanism**: +Sometimes, data must be fetched to determine which navigation items should be registered by a given module. To address this, Squide offers a **two-phase registration mechanism**: -1. The first phase allows modules to register their routes and navigation items that are not dependent on initial data (in addition to their MSW request handlers when fake endpoints are available). +1. The first phase allows modules to register navigation items that are not dependent on initial data (in addition to their routes and MSW request handlers when fake endpoints are available). -2. The second phase enables modules to register routes and navigation items that are dependent on initial data. Such a use case would be determining whether a route should be registered based on a feature flag. We refer to this second phase as **deferred registrations**. +2. The second phase enables modules to register navigation items that are dependent on initial data. Such a use case would be determining whether a navigation item should be registered based on a feature flag. We refer to this second phase as **deferred registrations**. -To defer a registration to the second phase, a module registration function can **return an anonymous function**. Once the modules are registered and the [completeRemoteModuleRegistrations](./completeRemoteModuleRegistrations.md) function is called, the deferred registration functions will be executed. +To defer a registration to the second phase, a module registration function can **return an anonymous function** matching the `DeferredRegistrationFunction` type: `(data, operation: "register" | "update") => Promise | void`. -```tsx !#14,17 host/src/bootstrap.tsx -import { FireflyRuntime, completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { fetchFeatureFlags } from "@sample/shared"; +Once the modules are registered, the deferred registration functions will be executed with the deferred data and `"register"` as the value for the `operation` argument. Afterward, whenever the deferred data changes, the deferred registration functions will be re-executed with the updated deferred data and `"update"` as the value for the `operation` argument. + +```tsx !#12 host/src/bootstrap.tsx +import { FireflyRuntime, registerRemoteModules, RuntimeContext, type RemoteDefinition } from "@squide/firefly"; +import { createRoot } from "react"; +import { register } from "@sample/local-module"; +import { App } from "./App.tsx"; const runtime = new FireflyRuntime(); @@ -87,42 +103,101 @@ const Remotes: RemoteDefinition = [ await registerRemoteModules(Remotes, runtime); -// Don't fetch data in the bootstrapping code for a real application. This is done here -// strictly for demonstration purpose. -const featureFlags = await fetchFeatureFlags(); +const root = createRoot(document.getElementById("root")!); -// Complete the module registrations with the feature flags data. -await completeRemoteModuleRegistrations(runtime, { featureFlags }); +root.render( + + + +); ``` -```tsx !#19-32 remote-module/src/register.tsx +```tsx !#12-16 host/src/AppRouter.tsx +import { usePublicDataQueries, useDeferredRegistrations, useIsBootstrapping, AppRouter as FireflyAppRouter } from "@squide/firefly"; +import { useMemo } from "react"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import type { DeferredRegistrationData } from "@sample/shared"; +import { getFeatureFlagsQuery } from "./getFeatureFlagsQuery.ts"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); + + // The useMemo is super important otherwise the hook will consider that the feature flags + // changed everytime the hook is rendered. + const data: DeferredRegistrationData = useMemo(() => ({ + featureFlags + }), [featureFlags]); + + useDeferredRegistrations(data); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function AppRouter() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +Routes are always registered, but navigation items can be conditionally registered using a deferred registration function. + +```tsx !#20-23,28-37 local-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; import type { DeferredRegistrationData } from "@sample/shared"; import { AboutPage } from "./AboutPage.tsx"; import { FeatureAPage } from "./FeatureAPage.tsx"; -export const register: ModuleRegisterFunction = async runtime => { +export const register: ModuleRegisterFunction = runtime => { runtime.registerRoute({ path: "/about", element: }); runtime.registerNavigationItem({ + $key: "about", $label: "About", to: "/about" }); + // Routes are always registered. If a route may not be available for a group of users, conditionally register + // its navigation item with a deferred registration. + // To manage direct hits to a conditional route, render an error boundary whenever the route's endpoint returns a 401 status code. + runtime.registerRoute({ + path: "/feature-a", + element: + }); + // Once the feature flags has been loaded by the host application, by completing the module registrations process, // the deferred registration function will be called with the feature flags data. - return ({ featureFlags } = {}) => { + return ({ featureFlags }) => { // Only register the "feature-a" route and navigation item if the feature is active. if (featureFlags.featureA) { - runtime.registerRoute({ - path: "/feature-a", - element: - }); - runtime.registerNavigationItem({ + $key: "feature-a", $label: "Feature A", to: "/feature-a" }); @@ -131,9 +206,52 @@ export const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + path: "/about", + element: + }); + + runtime.registerNavigationItem({ + $key: "about", + $label: "About", + to: "/about" + }); + + // Routes are always registered. If a route may not be available for a group of users, conditionally register + // its navigation item with a deferred registration. + // To manage direct hits to a conditional route, render an error boundary whenever the route's endpoint returns a 401 status code. + runtime.registerRoute({ + path: "/feature-a", + element: + }); + + // Once the feature flags has been loaded by the host application, by completing the module registrations process, + // the deferred registration function will be called with the feature flags data. + return ({ featureFlags }, operation) => { + // Only register the "feature-a" route and navigation item if the feature is active. + if (featureFlags.featureA) { + runtime.registerNavigationItem({ + $key: "feature-a", + $label: operation === "register" ? "Feature A" : "Feature A updated", + to: "/feature-a" + }); + } + }; +} +``` -### Handle the registration errors +### Handle registration errors ```tsx !#9-11 host/src/bootstrap.tsx import { FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; @@ -145,7 +263,7 @@ const Remotes: RemoteDefinition = [ ]; (await registerRemoteModules(Remotes, runtime)).forEach(x => { - console.log(x); + console.error(x); }); ``` diff --git a/docs/reference/registration/useAreModulesReady.md b/docs/reference/registration/useAreModulesReady.md deleted file mode 100644 index e7cedec2a..000000000 --- a/docs/reference/registration/useAreModulesReady.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -toc: - depth: 2-3 ---- - -# useAreModulesReady - -Force the application to re-render once the registration process has been completed for all the modules. Without this hook, the page is rendered with an empty router as it happens before the remote modules registered their routes and navigation items. - -!!!info -If your application is using the [AppRouter](../routing/appRouter.md) component, you shouldn't use this hook. -!!! - -!!!info -If your application supports [deferred registrations](./registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items), make sure to pair this hook with the [useAreModulesRegistered](./useAreModulesRegistered.md) hook. -!!! - -## Reference - -```ts -const areModulesReady = useAreModulesReady() -``` - -### Returns - -A boolean indicating if the registration process is completed. - -## Usage - -```tsx !#11 host/src/bootstrap.tsx -import { createRoot } from "react"; -import { FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { App } from "./App.tsx"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerRemoteModules(Remotes, runtime); - -const root = createRoot(document.getElementById("root")!); - -root.render( - - - -); -``` - -```tsx !#9,17-19 host/src/App.tsx -import { useMemo } from "react"; -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import { useAreModulesReady, useRoutes } from "@squide/firefly"; - -export function App() { - // Re-render the application once all the modules are registered. - // Otherwise, the remotes routes won't be added to the router as the router will be - // rendered before the remote modules registered their routes. - const areModulesReady = useAreModulesReady(); - - const routes = useRoutes(); - - const router = useMemo(() => { - return createBrowserRouter(routes); - }, [routes]); - - if (!areModulesReady) { - return
        Loading...
        ; - } - - return ( - Loading...} - /> - ); -} -``` diff --git a/docs/reference/registration/useAreModulesRegistered.md b/docs/reference/registration/useAreModulesRegistered.md deleted file mode 100644 index 730546011..000000000 --- a/docs/reference/registration/useAreModulesRegistered.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -toc: - depth: 2-3 -order: 50 ---- - -# useAreModulesRegistered - -Force the application to re-render once all the modules are registered (but not ready). - -!!!info -If your application is using the [AppRouter](../routing/appRouter.md) component, you shouldn't use this hook. -!!! - -!!!info -This hook should only be used by applications that support [deferred registrations](./registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items) and should be pair with the [useAreModulesReady](./useAreModulesReady.md) hook. -!!! - -## Reference - -```ts -const areModulesRegistered = useAreModulesRegistered() -``` - -### Returns - -A boolean indicating if the modules are registered. - -## Usage - -```tsx !#12-13 host/src/bootstrap.tsx -import { createRoot } from "react"; -import { registerLocalModules, FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly"; -import { register } from "@sample/local-module"; -import { App } from "./App.tsx"; - -const runtime = new FireflyRuntime(); - -const Remotes: RemoteDefinition = [ - { name: "remote1" } -]; - -await registerLocalModules([register], runtime, { context }); -await registerRemoteModules(Remotes, runtime); - -const root = createRoot(document.getElementById("root")!); - -root.render( - - - -); -``` - -```tsx !#10,17-29 host/src/App.tsx -import { useMemo, useEffect } from "react"; -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import { completeModuleRegistrations, useAreModulesRegistered, useAreModulesReady, useRoutes, useRuntime } from "@squide/firefly"; -import { fetchFeatureFlags, type FeatureFlags } from "@sample/shared"; - -export function App() { - const runtime = useRuntime(); - - // Re-render the application once all the modules are registered. - const areModulesRegistered = useAreModulesRegistered(); - - // Re-render the application once all the modules are registered. - // Otherwise, the remotes routes won't be added to the router as the router will be - // rendered before the remote modules registered their routes. - const areModulesReady = useAreModulesReady(); - - useEffect(() => { - // Once the modules are registered, fetch the feature flags data. - // The feature flags data cannot be fetched before the modules are registered because in development, - // it might be one of the modules that register the MSW request handlers for the feature flags data. - if (areModulesRegistered) { - fetchFeatureFlags() - .then(({ data }: { data?: FeatureFlags }) => { - // Execute the deferred registration functions with the feature flags data to complete - // the registration process. - completeModuleRegistrations(runtime, { featureFlags: data }); - }); - } - }, [runtime, areModulesRegistered]); - - const routes = useRoutes(); - - const router = useMemo(() => { - return createBrowserRouter(routes); - }, [routes]); - - if (!areModulesReady) { - return
        Loading...
        ; - } - - return ( - Loading...} - /> - ); -} -``` diff --git a/docs/reference/registration/useDeferredRegistrations.md b/docs/reference/registration/useDeferredRegistrations.md new file mode 100644 index 000000000..7f2ea8205 --- /dev/null +++ b/docs/reference/registration/useDeferredRegistrations.md @@ -0,0 +1,132 @@ +--- +toc: + depth: 2-3 +--- + +# useDeferredRegistrations + +Register the modules [deferred registration](./registerLocalModules.md#defer-the-registration-of-navigation-items) functions when the global data is initially fetched or update the deferred registration functions whenever the global data change. + +!!!info +This hook should always be used in combination with [deferred registration](./registerLocalModules.md#defer-the-registration-of-navigation-items) functions and with either the [usePublicDataQueries](../tanstack-query/usePublicDataQueries.md) hook or the [useProtectedDataQueries](../tanstack-query/useProtectedDataQueries.md) hook (can be both). +!!! + +## Reference + +```ts +useDeferredRegistrations(data: {}, options?: { onError? }); +``` + +### Parameters + +- `data`: An object literal of data that will be passed to the deferred registration functions. +- `options`: An optional object literal of options: + - `onError`: An optional function receiving an `DeferredRegistrationsErrorsObject` object as an argument. + +#### `DeferredRegistrationsErrorsObject` + +- `localModuleErrors`: An array of errors that occured during the deferred registrations of local modules. + - `error`: The original `Error` object. +- `remoteModuleErrors`: An array of errors that occured during the deferred registrations of remote modules. + - `remoteName`: The name of the remote module that failed to load. + - `moduleName`: The name of the [module](./registerRemoteModules.md#name) that Squide attempted to recover. + - `error`: The original `Error` object. + +### Returns + +Nothing + +## Usage + +### Register or update deferred registrations + +```tsx !#17-22 host/src/AppRouter.tsx +import { usePublicDataQueries, useProtectedDataQueries, useDeferredRegistrations, useIsBootstrapping, AppRouter as FireflyAppRouter } from "@squide/firefly"; +import { useMemo } from "react"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { DeferredRegistrationData } from "@sample/shared"; +import { getFeatureFlagsQuery } from "./getFeatureFlagsQuery.ts"; +import { getSessionQuery } from "./getSessionQuery.ts"; +import { isApiError } from "./isApiError.ts"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); + + const [session] = useProtectedDataQueries( + [getSessionQuery], + error => isApiError(error) && error.status === 401 + ); + + const data: DeferredRegistrationData = useMemo(() => ({ + featureFlags, + session + }), [featureFlags, session]); + + useDeferredRegistrations(data); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function AppRouter() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +### Handle registration errors + +```tsx !#10-18,21 host/src/AppRouter.tsx +import { useDeferredRegistrations, type DeferredRegistrationsErrorCallback } from "@squide/firefly"; +import type { DeferredRegistrationData } from "@sample/shared"; +import { useMemo } from "react"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); + + const data: DeferredRegistrationData = useMemo(() => ({ featureFlags }), [featureFlags]); + + const handleErrors: DeferredRegistrationsErrorCallback = errors => { + errors.localModuleErrors.forEach(x => { + console.error(x); + }); + + errors.remoteModuleErrors.forEach(x => { + console.error(x); + }); + }; + + useDeferredRegistrations(data, { + onError: handleErrors + }); + + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} +``` diff --git a/docs/reference/routing/appRouter.md b/docs/reference/routing/appRouter.md index cb04101bb..9fece5682 100644 --- a/docs/reference/routing/appRouter.md +++ b/docs/reference/routing/appRouter.md @@ -1,293 +1,287 @@ --- -order: 100 +order: 110 toc: depth: 2-3 --- # AppRouter -A component that sets up and orchestrate Squide federated primitives with a [React Router](https://reactrouter.com/en/main) instance. +A component that sets up Squide's primitives with a [React Router](https://reactrouter.com/en/main) instance. + +!!!warning +The `AppRouter` component is required for any Squide application. +!!! ## Reference ```tsx - - {(routes: [], routerProviderOptoons: {}) => ( ... )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => ( ... )} ``` ### Properties -- `fallbackElement`: A React element to render while the application is being bootstrapped. -- `errorElement`: A React element to render when there's an unmanaged error during the bootstrapping of the application. -- `waitForMsw`: Whether or not the application bootstrapping sequence should wait for MSW to be started before loading the data and rendering the active route. -- `onLoadPublicData`: An optional handler to load the initial public data after the **modules are registered** and **MSW is started** (if enabled). This handler is called the first time a user navigate to a [public route](../runtime/runtime-class.md#register-a-public-route). - - `signal`: An [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) to cancel the previous HTTP request when the `onLoadPublicData` handler is called twice due to the `AppRouter` being re-rendered. -- `onLoadProtectedData`: An optional handler to load the initial protected data after the **modules are registered** and **MSW is started** (if enabled). This handler is called the first time a user navigate to a protected route (any route that has no `$visibility: public` hint). - - `signal`: An [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) to cancel the previous HTTP request when the `onLoadPublicData` handler is called twice due to the `AppRouter` being re-rendered. -- `isPublicDataLoaded`: Whether or not the initial public data has been loaded. -- `isProtectedDataLoaded`: Whether or not the initial protected data has been loaded. -- `onCompleteRegistrations`: An optional handler to complete the [deferred registrations](../registration/registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items). -- `children`: A render function to define a React Router [RouterProvider](https://reactrouter.com/en/main/routers/router-provider) component with the registered routes. +- `waitForMsw`: A `boolean` value indicating whether or not Squide should delay the rendering of the requested page until the [Mock Service Worker](https://mswjs.io/) request handlers are registered. +- `waitForPublicData`: An optional `boolean` value indicating whether or not Squide should delay the rendering of the requested page until the **public** data is ready. The default value is `false`. +- `waitForProtectedData`: An optional `boolean` value indicating whether or not Squide should delay the rendering of the requested page until the **protected** data is ready. The default value is `false`. +- `children`: A render function defining a [RouterProvider](https://reactrouter.com/en/main/routers/router-provider) component with `rootRoute`, `registeredRoutes` and `routerProviderProps`. ## Usage ### Define a router provider -```tsx !#11-13 host/src/App.tsx +The `rootRoute` component provided as an argument to the `AppRouter` rendering function must always be rendered as a parent of the `registeredRoutes`. + +```tsx !#8-16 host/src/App.tsx import { AppRouter } from "@squide/firefly"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; export function App() { - return ( - Loading...} - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} -
        - ); + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }} + } ``` ### Define a loading component -```tsx host/src/Loading.tsx -export function Loading() { - return ( -
        Loading...
        - ); -} -``` +A `BootstrappingRoute` component is introduced in the following example because the [useIsBootstrapping](../routing/useIsBootstrapping.md) hook must be rendered as a child of `rootRoute`. -```tsx !#8 host/src/App.tsx -import { AppRouter } from "@squide/firefly"; -import { Loading } from "./Loading.tsx"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; +```tsx !#5-7,23 host/src/App.tsx +import { useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; + +function BootstrappingRoute() { + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} export function App() { return ( - } - errorElement={
        An error occured!
        } - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } ``` -### Define an error component -An error component receives the current `error` as a prop. +### Define a root error boundary + +A React Router [errorElement](https://reactrouter.com/en/main/route/error-element) retrieves the current error using the [useRouteError](https://reactrouter.com/en/main/hooks/use-route-error) hook. + +The root error boundary should always wrap the `registeredRoutes` and, when application, the `BootstrapingRoute` component. + +```tsx host/src/RootErrorBoundary.tsx +import { useRouteError } from "react-router-dom"; + +export function RootErrorBoundary() { + const error = useRouteError(); -```tsx host/src/ErrorBoundary.tsx -export function ErrorBoundary({ error }: { error?: Error }) { return (

        Unmanaged error

        -

        An unmanaged error occurred while bootstrapping the application.

        -

        {error?.message}

        -

        {error?.stack}

        +

        An unmanaged error occurred and the application is broken, try refreshing your browser.

        ); } ``` -```tsx !#10 host/src/App.tsx +```tsx !#16 host/src/App.tsx import { AppRouter } from "@squide/firefly"; -import { Loading } from "./Loading.tsx"; -import { ErrorBoundary } from "./ErrorBoundary.tsx"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; +import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; export function App() { return ( - } - errorElement={} - waitForMsw={true} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } ``` -### Load public data +### Delay rendering until MSW is ready -The handler must return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), and the consumer application must handle the loaded public data, as the `AppRouter` component will ignore any data resolved by the returned `Promise` object. - -The `isPublicDataLoaded` property should also be provided to indicate whether or not the initial public data loading is completed. - -```tsx !#10,23,25-27,34-35 host/src/App.tsx -import { useState, useCallback } from "react"; +```tsx !#6 host/src/App.tsx import { AppRouter } from "@squide/firefly"; -import { Loading } from "./Loading.tsx"; -import { ErrorBoundary } from "./ErrorBoundary.tsx"; -import type { FeatureFlags } from "@sample/shared"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; -async function fetchPublicData(setFeatureFlags: (featureFlags: FeatureFlags) => void, signal: AbortSignal) { - const response = await fetch("/api/feature-flags", { - signal - }); - - if (response.ok) { - const data = await response.json(); - - setFeatureFlags(data); - } -} - export function App() { - // The loaded data is kept in memory by this state hook of the consumer application and - // will be used at a later time. - const [featureFlags, setFeatureFlags] = useState(); - - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFeatureFlags, signal); - }, []); - return ( - } - errorElement={} - waitForMsw={true} - onLoadPublicData={handleLoadPublicData} - isPublicDataLoaded={!!featureFlags} - > - {(routes, providerProps) => ( - - )} + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + + ); + }} ); } ``` -!!!warning -Don't forget to forward the [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) to the HTTP client initiating the public data GET request. -!!! - -### Load protected data +### Delay rendering until the public data is ready -The handler must return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), and the consumer application must handle the loaded protected data, as the `AppRouter` component will ignore any data resolved by the returned `Promise` object. +A `BootstrappingRoute` component is introduced in the following example because the [usePublicDataQueries](../tanstack-query/usePublicDataQueries.md) hook must be rendered as a child of `rootRoute`. -The `isProtectedDataLoaded` property should also be provided to indicate whether or not the initial protected data loading is completed. +```tsx !#7,24 host/src/App.tsx +import { useIsBootstrapping, usePublicDataQueries, AppRouter } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { FeatureFlagsContext } from "@sample/shared"; +import { getFeatureFlagsQuery } from "./getFeatureFlagsQuery.ts"; -```tsx !#10,28,30-32,39-40 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter } from "@squide/firefly"; -import { Loading } from "./Loading.tsx"; -import { ErrorBoundary } from "./ErrorBoundary.tsx"; -import type { Session } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([getFeatureFlagsQuery]); -async function fetchProtectedData(setSession: (session: Session) => void, signal: AbortSignal) { - const response = await fetch("/api/session"), { - signal - }); - - if (response.ok) { - const data = await response.json(); - - setSession({ - user: { - id: data.userId, - name: data.username - } - }); + if (useIsBootstrapping()) { + return
        Loading...
        ; } + + return ( + + + + ); } export function App() { - // The loaded data is kept in memory by this state hook of the consumer application and - // will be used at a later time. - const [session, setSession] = useState(); - - const handleLoadProtectedData = useCallback((signal: AbortSignal) => { - return fetchProtectedData(setSession, signal); - }, []); - return ( - } - errorElement={} - waitForMsw={true} - onLoadProtectedData={handleLoadProtectedData} - isProtectedDataLoaded={!!session} + - {(routes, providerProps) => ( - - )} + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } ``` -!!!warning -Don't forget to forward the [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal) to the HTTP client initiating the public data GET request. -!!! +### Delay rendering until the protected data is ready -### Complete deferred registrations +A `BootstrappingRoute` component is introduced in the following example because the [useProtectedDataQueries](../tanstack-query/useProtectedDataQueries.md) hook must be rendered as a child of `rootRoute`. -For more information about deferred registrations, refer to the [registerRemoteModules](../registration/registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items) and [completeModuleRegistrations](../registration/completeModuleRegistrations.md) documentation. +```tsx !#7-10,27 host/src/App.tsx +import { useIsBootstrapping, useProtectedDataQueries, AppRouter } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; +import { SessionContext, isApiError } from "@sample/shared"; +import { getSessionQuery } from "./getSessionQuery.ts"; -```tsx !#31-33,43 host/src/App.tsx -import { useState, useCallback } from "react"; -import { AppRouter, completeModuleRegistrations } from "@squide/firefly"; -import { Loading } from "./Loading.tsx"; -import { ErrorBoundary } from "./ErrorBoundary.tsx"; -import type { FeatureFlags } from "@sample/shared"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; +function BootstrappingRoute() { + const [session] = useProtectedDataQueries( + [getSessionQuery], + error => isApiError(error) && error.status === 401 + ); -async function fetchPublicData(setFeatureFlags: (featureFlags: FeatureFlags) => void, signal: AbortSignal) { - const response = await fetch("/api/feature-flags", { - signal - }); - - if (response.ok) { - const data = await response.json(); - - setFeatureFlags(data); + if (useIsBootstrapping()) { + return
        Loading...
        ; } + + return ( + + + + ); } export function App() { - // The loaded data is kept in memory by this state hook of the consumer application and - // will be used to complete the deferred registrations. - const [featureFlags, setFeatureFlags] = useState(); - - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFeatureFlags, signal); - }, []); - - const handleCompleteRegistrations = useCallback(() => { - // The consumer application takes care of providing the public data to the deferred registrations. - return completeModuleRegistrations(runtime, { - featureFlags - }); - }, [runtime, featureFlags]); - return ( - } - errorElement={} - waitForMsw={true} - onLoadPublicData={handleLoadPublicData} - isPublicDataLoaded={!!featureFlags} - onCompleteRegistrations={handleCompleteRegistrations} + - {(routes, providerProps) => ( - - )} + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} ); } diff --git a/docs/reference/routing/isNavigationLink.md b/docs/reference/routing/isNavigationLink.md index c3aa30fab..b959159c2 100644 --- a/docs/reference/routing/isNavigationLink.md +++ b/docs/reference/routing/isNavigationLink.md @@ -6,7 +6,7 @@ toc: # isNavigationLink -Indicate whether or not a navigation item should be rendered as a link. This utility is particularly handy when rendering a menu [with nested items](../runtime/runtime-class.md#register-nested-navigation-items). +Indicate whether or not a navigation item is a `NavigationLink`. This utility is particularly handy when rendering a menu [with nested items](../runtime/runtime-class.md#register-nested-navigation-items). ## Reference @@ -20,7 +20,7 @@ const isLink = isNavigationLink(item) ### Returns -A boolean value indicating whether or not the navigation item should be rendered as a link. +A `boolean` value indicating whether or not the navigation item should be rendered as a link. ## Usage diff --git a/docs/reference/routing/ManagedRoutes.md b/docs/reference/routing/managedRoutes.md similarity index 99% rename from docs/reference/routing/ManagedRoutes.md rename to docs/reference/routing/managedRoutes.md index ae29e4a4e..189e52f7c 100644 --- a/docs/reference/routing/ManagedRoutes.md +++ b/docs/reference/routing/managedRoutes.md @@ -1,5 +1,5 @@ --- -order: 90 +order: 100 toc: depth: 2-3 --- diff --git a/docs/reference/routing/useIsBootstrapping.md b/docs/reference/routing/useIsBootstrapping.md new file mode 100644 index 000000000..859f2c6c5 --- /dev/null +++ b/docs/reference/routing/useIsBootstrapping.md @@ -0,0 +1,65 @@ +--- +order: 90 +toc: + depth: 2-3 +--- + +# useIsBootstrapping + +Indicate whether the application is currently being bootstrapped, such as registering modules, handling deferred registrations, preparing [Mock Service Worker](https://mswjs.io/), fetching global data, etc. + +## Reference + +```ts +const isBootstrapping = useIsBootstrapping(); +``` + +### Parameters + +None + +### Returns + +A `boolean` value indicating whether or not the application is bootstrapping. + +## Usage + +A `BootstrappingRoute` component is introduced in the following example because this hook must be rendered as a child of `rootRoute`. + +```tsx !#5 host/src/App.tsx +import { useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; + +function BootstrappingRoute() { + if (useIsBootstrapping()) { + return
        Loading...
        ; + } + + return ; +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` diff --git a/docs/reference/routing/useRenderedNavigationItems.md b/docs/reference/routing/useRenderedNavigationItems.md index 991337d8d..488c499fa 100644 --- a/docs/reference/routing/useRenderedNavigationItems.md +++ b/docs/reference/routing/useRenderedNavigationItems.md @@ -8,22 +8,42 @@ toc: Recursively parse a navigation items structure to transform the items into React Elements. -> The `useNavigationItems` hook returns the navigation items tree structure as is, meaning the consumer has to recursively parse the structure to transform the items into actual React Elements. +> The [useNavigationItems](../runtime/useNavigationItems.md) hook returns the navigation items tree structure as is, meaning the consumer has to recursively parse the structure to transform the items into actual React Elements. > > As it's a non-trivial process, Squide provides this utility hook. ## Reference ```ts -const elements = useRenderedNavigationItems(navigationItems: [], renderItem: () => {}, renderSection: () => {}) +const elements = useRenderedNavigationItems( + navigationItems: [], + renderItem: (item, key, index, level) => {}, + renderSection: (elements, key, index, level) => {}) ``` ### Parameters -- `navigationItems`: An array of `NavigationItem` to render. -- `renderItem`: A function to render a single link from a navigation item +- `navigationItems`: An array of `NavigationLink | NavigationSection` to render. +- `renderItem`: A function to render a link from a navigation item - `renderSection`: A function to render a section from a collection of items. +#### `NavigationLink` + +Accept any properties of a React Router [Link](https://reactrouter.com/en/main/components/link) component with the addition of: + +- `$key`: An optional key identifying the link. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The link label. Could either by a `string` or a `ReactNode`. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the link should be rendered. +- `$additionalProps`: An optional object literal of additional props to apply to the link component. + +#### `NavigationSection` + +- `$key`: An optional key identifying the section. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The section label. Could either by a `string` or a `ReactNode`. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the section should be rendered. +- `$additionalProps`: An optional object literal of additional props to apply to the section component. +- `children`: The section items. + ### Returns An array of `ReactElement`. @@ -32,6 +52,12 @@ An array of `ReactElement`. ### Render nested items +!!!info +We recommend always providing a `$key` property for a navigation item, as it ensures the menus doesn't flicker when [deferred registrations](../registration/registerLocalModules.md#defer-the-registration-of-navigation-items) are updated. Be sure to use a unique key. + +When no `$key` property is provided, a default key value is computed based on the `index` and `level` properties. While this works in most cases, the default key cannot guarantee that the menu won't flicker during updates. +!!! + ```tsx !#38-40,42-48,52 host/src/RootLayout.tsx import type { ReactNode } from "react"; import { Link, Outlet } from "react-router-dom"; @@ -45,13 +71,13 @@ import { type NavigationSectionRenderProps } from "@squide/react-router"; -type RenderLinkItemFunction = (item: NavigationLinkRenderProps, index: number, level: number) => ReactNode; +type RenderLinkItemFunction = (item: NavigationLinkRenderProps, key: string) => ReactNode; -type RenderSectionItemFunction = (item: NavigationSectionRenderProps, index: number, level: number) => ReactNode; +type RenderSectionItemFunction = (item: NavigationSectionRenderProps, key: string) => ReactNode; -const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps }, index, level) => { +const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps }, key) => { return ( -
      • +
      • {label} @@ -59,9 +85,9 @@ const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalPr ); }; -const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, level) => { +const renderSectionItem: RenderSectionItemFunction = ({ label, section }, key) => { return ( -
      • +
      • {label}
        ({section}) @@ -70,13 +96,13 @@ const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, ); }; -const renderItem: RenderItemFunction = (item, index, level) => { - return isNavigationLink(item) ? renderLinkItem(item, index, level) : renderSectionItem(item, index, level); +const renderItem: RenderItemFunction = (item, key) => { + return isNavigationLink(item) ? renderLinkItem(item, key) : renderSectionItem(item, key); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
          +
            {elements}
          ); @@ -113,13 +139,13 @@ import { type NavigationSectionRenderProps } from "@squide/react-router"; -type RenderLinkItemFunction = (item: NavigationLinkRenderProps, index: number, level: number, userId: string) => ReactNode; +type RenderLinkItemFunction = (item: NavigationLinkRenderProps, key: string, userId: string) => ReactNode; -type RenderSectionItemFunction = (item: NavigationSectionRenderProps, index: number, level: number) => ReactNode; +type RenderSectionItemFunction = (item: NavigationSectionRenderProps, key: string) => ReactNode; -const renderLinkItem: RenderLinkItemFunction = ({ label, { to, ...linkProps}, additionalProps }, index, level, userId) => { +const renderLinkItem: RenderLinkItemFunction = ({ label, { to, ...linkProps}, additionalProps }, key, userId) => { return ( -
        • +
        • {label} @@ -127,9 +153,9 @@ const renderLinkItem: RenderLinkItemFunction = ({ label, { to, ...linkProps}, ad ); }; -const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, level) => { +const renderSectionItem: RenderSectionItemFunction = ({ label, section }, key) => { return ( -
        • +
        • {label}
          ({section}) @@ -139,16 +165,16 @@ const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, }; function renderItem(userId: string) { - const fct: RenderItemFunction = (item, index, level) => { - return isNavigationLink(item) ? renderLinkItem(item, index, level, userId) : renderSectionItem(item, index, level); + const fct: RenderItemFunction = (item, key) => { + return isNavigationLink(item) ? renderLinkItem(item, key, userId) : renderSectionItem(item, key); }; return fct; } -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
            +
              {elements}
            ); @@ -169,11 +195,12 @@ export function UserProfileLayout() { } ``` -```tsx !#6 remote-module/src/register.tsx +```tsx !#7 remote-module/src/register.tsx import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly"; export const register: ModuleRegisterFunction = (runtime) => { runtime.registerNavigationItem({ + $key: "user-profile", $label: "User profile", to: "/user-profile/:userId" }, { diff --git a/docs/reference/routing/useRouteMatch.md b/docs/reference/routing/useRouteMatch.md index 885ab598d..32ea1e505 100644 --- a/docs/reference/routing/useRouteMatch.md +++ b/docs/reference/routing/useRouteMatch.md @@ -6,12 +6,12 @@ toc: # useRouteMatch -Execute [React Router's matching algorithm](https://reactrouter.com/en/main/utils/match-routes) against the registered routes and a given `location` to determine if any route match the location. +Execute [React Router's matching algorithm](https://reactrouter.com/en/main/utils/match-routes) against Squide's routes registry and a given `location` to determine if any route match the location. ## Reference ```ts -const match = useRouteMatch(locationArg) +const match = useRouteMatch(locationArg, options?: { throwWhenThereIsNoMatch? }) ``` ### Parameters diff --git a/docs/reference/runtime/runtime-class.md b/docs/reference/runtime/runtime-class.md index f92cae0e6..704ad268d 100644 --- a/docs/reference/runtime/runtime-class.md +++ b/docs/reference/runtime/runtime-class.md @@ -11,17 +11,34 @@ A runtime instance give modules access to functionalities such as routing, navig ## Reference ```ts -const runtime = new FireflyRuntime(options?: { loggers?: [], plugins?: [], sessionAccessor?: () => {} }) +const runtime = new FireflyRuntime(options?: { mode?, useMsw?, loggers?, plugins? }) ``` ### Parameters - `options`: An optional object literal of options: - - `mode`: An optional mode to optimize Squide for `production`. Values are `"development"` (default) and `"production"`. - - `useMsw`: An optional boolean value indicating whether or not to create the runtime with MSW support. + - `mode`: An optional mode to optimize Squide for production. Values are `"development"` (default) and `"production"`. + - `useMsw`: An optional `boolean` value indicating whether or not to create the runtime with [Mock Service Work](https://mswjs.io/) (MSW) support. - `loggers`: An optional array of `Logger` instances. - - `plugins`: An optional array of custom plugin instances. - - `sessionAccessor`: An optional function returning the current session. + - `plugins`: An optional array of `Plugin` factory functions. + +### Methods + +- `registerRoute(route, options?)`: Register a route. +- `registerNavigationItem(navigationItem, options?)`: Register a navigation item. +- `getNavigationItems(menuId?)`: Retrieve the registered navigation items. +- `registerRequestHandlers(handlers)`: Register the MSW request handlers. +- `getPlugin(name)`: Retrieve the registered plugin by the specified `name`. + +### Getters + +- `mode`: Retrieve the runtime mode. +- `routes`: Retrieve the registered routes. +- `requestHandlers`: Retrieve the registered MSW request handlers. +- `plugins`: Retrieve the registered plugins. +- `logger`: Retrieve the runtime logger. +- `eventBus`: Retrieve the runtime event bus. +- `isMswEnabled`: Indicate whether or not MSW is enabled. ## Usage @@ -29,16 +46,9 @@ const runtime = new FireflyRuntime(options?: { loggers?: [], plugins?: [], sessi ```ts import { ConsoleLogger, FireflyRuntime } from "@squide/firefly"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import { type AppSession } from "@sample/shared"; - -const sessionManager = new LocalStorageSessionManager(); const runtime = new FireflyRuntime({ - loggers: [new ConsoleLogger()], - sessionAccessor: () => { - return sessionManager.getSession(); - }; + loggers: [new ConsoleLogger()] }); ``` @@ -70,14 +80,14 @@ if (runtime.isMswEnabled) { ### Register routes ```ts -runtime.registerRoute(route, options?: {}) +runtime.registerRoute(route, options?: { hoist?, parentPath?, parentName? }) ``` - `route`: accept any properties of a React Router [Route](https://reactrouter.com/en/main/components/route) component with the addition of: - `$name`: An optional name for the route. - `$visibility`: An optional visibility indicator for the route. Accepted values are `"public"` or `"protected"`. - `options`: An optional object literal of options: - - `hoist`: An optional boolean value to register the route at the root of the router. The default value is `false`. + - `hoist`: An optional `boolean` value to register the route at the root of the router. The default value is `false`. - `parentPath`: An optional path of a parent route to register this new route under. - `parentName`: An optional name of a parent route to register this new route under. @@ -93,7 +103,7 @@ runtime.registerRoute({ ### Register an hoisted route -Unlike a regular page, a hoisted page is added at the root of the router, outside of the host application's root layout, root error boundary and even root authentication boundary. This means that a hoisted page has full control over its rendering. To mark a route as hoisted, provide an `hoist` property to the route options. +Unlike a regular route, a hoisted route is added at the root of the router, outside of the host application's root layout, root error boundary and even root authentication boundary. This means that a hoisted route has full control over its rendering. To mark a route as hoisted, provide an `hoist` property to the route options. ```tsx !#7 import { Page } from "./Page.tsx"; @@ -107,10 +117,10 @@ runtime.registerRoute({ ``` !!!warning -By declaring a page as hoisted, other parts of the application will not be isolated anymore from this page's failures and the page will not be protected anymore by the application authenticated boundary. +By declaring a route as hoisted, other parts of the application will not be isolated anymore from this route's failures and the route will not be protected anymore by the application authenticated boundary. -- To **avoid breaking the entire application** when an hoisted page encounters unhandled errors, it is highly recommended to declare a React Router's [errorElement](https://reactrouter.com/en/main/route/error-element) property for each hoisted page. -- If the hoisted page requires an authentication, make sure to **wrap the page with an authentication boundary** or to handle the authentication within the page. +- To **avoid breaking** the entire **application** when an hoisted route encounters unhandled errors, it is highly recommended to declare a React Router's [errorElement](https://reactrouter.com/en/main/route/error-element) property for each hoisted route. +- If the hoisted route requires an authentication, make sure to **wrap** the route **with** an **authentication boundary** or to handle the authentication within the route. !!! ### Register a route with a different layout @@ -122,7 +132,7 @@ import { RemoteErrorBoundary } from "./RemoteErrorBoundary.tsx"; runtime.registerRoute({ path: "/page-1", - // Will render the page inside the "RemoteLayout" rather than the "RootLayout". + // Will render the route inside the "RemoteLayout" rather than the "RootLayout". // For more information about React Router's nested routes, view https://reactrouter.com/en/main/start/tutorial#nested-routes. element: , children: [ @@ -145,7 +155,7 @@ runtime.registerRoute({ ### Register a public route -When registering a route, a hint can be provided, indicating if the route is intended to be displayed as a `public` or `protected` route. This is especially useful when dealing with code that conditionally fetch data for protected routes (e.g. a session). +When registering a route, a hint can be provided, indicating if the route is intended to be displayed as a `"public"` or `"protected"` route. This is especially useful when dealing with code that conditionally fetch data for protected routes (e.g. a session). ```tsx !#4,8 import { Page } from "./Page.tsx"; @@ -220,7 +230,7 @@ runtime.registerRoute({ ### Register nested routes under an existing route -React router [nested routes](https://reactrouter.com/en/main/start/tutorial#nested-routes) enable applications to render nested layouts at various points within the router tree. This is quite helpful for federated applications as it enables composable and decoupled UI. +React router [nested routes](https://reactrouter.com/en/main/start/tutorial#nested-routes) enable applications to render nested layouts at various points within the router tree. This is quite helpful for modular applications as it enables composable and decoupled UI. To fully harness the power of nested routes, the `registerRoute` function allows a route to be registered **under any** previously **registered route**, even if that route was registered by another module. The only requirement is that the **parent route** must have been registered with the `registerRoute` function. @@ -233,7 +243,7 @@ runtime.registerRoute({ path: "/layout/page-1", element: }, { - parentPath: "/layout" // Register the page under an existing route having "/layout" as its "path". + parentPath: "/layout" // Register the route under an existing route having "/layout" as its "path". }); ``` @@ -246,19 +256,19 @@ runtime.registerRoute({ path: "/page-1", element: }, { - parentName: "error-boundary" // Register the page under an existing route having "error-boundary" as its "name". + parentName: "error-boundary" // Register the route under an existing route having "error-boundary" as its "name". }); ``` -[!ref text="Learn more about using nested routes for federated tabs"](../../guides/federated-tabs.md) +[!ref text="Learn more about using nested routes for federated tabs"](../../guides/use-federated-tabs.md) !!!info -Likewise any other React Router routes, the `path` property of a page rendered under an existing parent route must be an absolute path. For example, if a parent route `path` is `/layout`, the `path` property of a page rendered under that parent route and responding to the `/page-1` url, should be `/layout/page-1`. +Likewise any other React Router routes, the `path` property of a route rendered under an existing parent route must be an absolute path. For example, if a parent route `path` is `/layout`, the `path` property of a route rendered under that parent route and responding to the `/page-1` url, should be `/layout/page-1`. !!! ### Retrieve routes -A federated application routes are accessible from a `FireflyRuntime` instance, but keep in mind that the preferred way to retrieve the routes is with the [useRoutes](./useRoutes) hook. +The registered routes are accessible from a `FireflyRuntime` instance, but keep in mind that the preferred way to retrieve the routes is with the [useRoutes](./useRoutes) hook. ```tsx const routes = runtime.routes; @@ -267,7 +277,7 @@ const routes = runtime.routes; ### Register navigation items ```ts -runtime.registerNavigationItem(item, options?: {}) +runtime.registerNavigationItem(item, options?: { menuId? }) ``` - `item`: `NavigationSection | NavigationLink`. @@ -276,19 +286,32 @@ runtime.registerNavigationItem(item, options?: {}) A Squide navigation item can either be a `NavigationLink` or a `NavigationSection`. Both types can be intertwined to create a multi-level menu hierarchy. A `NavigationSection` item is used to setup a new level while a `NavigationLink` define a link. -- `NavigationSection` accept the following properties: - - `$label`: The section text. - - `$priority`: An order priority affecting the position of the item in the menu (higher first) - - `$additionalProps`: Additional properties to be forwarded to the section renderer. - - `children`: The section content. -- `NavigationLink` accept any properties of a React Router [Link](https://reactrouter.com/en/main/components/link) component with the addition of: - - `$label`: The link text. - - `$priority`: An order priority affecting the position of the item in the menu (higher first) - - `$additionalProps`: Additional properties to be forwarded to the link renderer. +#### `NavigationLink` + +Accept any properties of a React Router [Link](https://reactrouter.com/en/main/components/link) component with the addition of: +- `$key`: An optional key identifying the link. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The link text. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the link should be rendered. +- `$priority`: An order priority affecting the position of the item in the menu (higher first) +- `$additionalProps`: Additional properties to be forwarded to the link renderer. + +#### `NavigationSection` + +- `$key`: An optional key identifying the section. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The section text. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the section should be rendered. +- `$priority`: An order priority affecting the position of the item in the menu (higher first) +- `$additionalProps`: Additional properties to be forwarded to the section renderer. +- `children`: The section content. + +!!!info +We recommend always providing a `$key` property for a navigation item, as it ensures the menus doesn't flicker when [deferred registrations](../registration/registerLocalModules.md#defer-the-registration-of-navigation-items) are updated. Be sure to use a unique key. +!!! ```ts // Register a new navigation item from a local or remote module. runtime.registerNavigationItem({ + $key: "page-1", $label: "Page 1", to: "/page-1" }); @@ -307,24 +330,29 @@ runtime.registerNavigationItem({ // --- Nested Link // Link runtime.registerNavigationItem({ + $ley: "section", $label: "Section", children: [ { - label: "Nested Section", + $key: "nested-section", + $label: "Nested Section", children: [ { + $key: "nested-nested-link", $label: "Nested Nested Link", to: "#" } ] }, { + $key: "nested-link", $label: "Nested Link", to: "#" } ] }, { + $key: "link", $label: "Link", to: "#" }); @@ -339,14 +367,16 @@ A `$priority` property can be added to a navigation item to affect it's position - If an item have a priority `> 0`, the item will be positioned before any other items with a lower priority (or without an explicit priority value). - If an item have a priority `< 0`, the item will be positioned after any other items with a higher priority (or without an explicit priority value). -```ts !#3,11 +```ts !#4,13 runtime.registerNavigationItem({ + $key: "about", $label: "About", $priority: 10, to: "/about" }); runtime.registerNavigationItem({ + $key: "home", $label: "Home", // Because the "Home" navigation item has an higher priority, it will be rendered // before the "About" navigation item. @@ -357,8 +387,9 @@ runtime.registerNavigationItem({ ### Use dynamic segments -```ts !#3 +```ts !#4 runtime.registerNavigationItem({ + $key: "user-profile", $label: "User profile", to: "/user-profile/:userId" }); @@ -368,10 +399,11 @@ runtime.registerNavigationItem({ ### Use a React element as navigation item label -```tsx !#4-7 +```tsx !#5-8 import { QuestionMarkIcon } from "@sample/icons"; runtime.registerNavigationItem({ + $key: "about", $label: ( About @@ -382,8 +414,9 @@ runtime.registerNavigationItem({ ### Style a navigation item -```ts !#3-5 +```ts !#4-6 runtime.registerNavigationItem({ + $key: "about", $label: "About", style: { backgroundColor: "#000" @@ -394,32 +427,50 @@ runtime.registerNavigationItem({ ### Open a navigation link in a new tab -```ts !#3 +```ts !#4 runtime.registerNavigationItem({ + $key: "about", $label: "About", target: "_blank", to: "/about" }); ``` +### Conditionally render a navigation item + +```ts !#4-6 +runtime.registerNavigationItem({ + $key: "about", + $label: "About", + $canRender: (index: number) => { + return index % 2 == 0; + }, + to: "/about" +}); +``` + +> It's the responsibility of the code rendering the menu to execute the navigation items `$canRender` function and conditionally render the items based on the return value. + ### Render additional props on a navigation item -```ts !#3-5 +```ts !#4-6 runtime.registerNavigationItem({ - $label: "About", - $additionalProps: { - highlight: true - }, - to: "/about" - }); + $key: "about", + $label: "About", + $additionalProps: { + highlight: true + }, + to: "/about" +}); ``` ### Register navigation items for a specific menu By default, every navigation item registered with the `registerNavigationItem` function is registered as part of the `root` navigation menu. To register a navigation item for a different navigation menu, specify a `menuId` property when registering the items. -```tsx !#5 +```tsx !#6 runtime.registerNavigationItem({ + $key: "page-1", $label: "Page 1", to: "/layout/page-1" }, { @@ -429,7 +480,7 @@ runtime.registerNavigationItem({ ### Retrieve navigation items -A federated application navigation items are accessible from a `FireflyRuntime` instance, but keep in mind that the preferred way to retrieve the navigation items is with the [useNavigationItems](./useNavigationItems) hook. +The registered navigation items are accessible from a `FireflyRuntime` instance, but keep in mind that the preferred way to retrieve the navigation items is with the [useNavigationItems](./useNavigationItems) hook. By default, the `getNavigationItems` will return the navigation items for the `root` menu: @@ -481,12 +532,14 @@ runtime.eventBus.dispatch("write-to-host", "Hello host!"); ### Register a plugin +The plugin factory function receives the `Runtime` instance as parameter. + ```ts !#5 import { FireflyRuntime } from "@squide/firefly"; import { MyPlugin } from "@sample/my-plugin"; const runtime = new FireflyRuntime({ - plugins: [new MyPlugin()] + plugins: [x => new MyPlugin(x)] }); ``` @@ -502,12 +555,3 @@ const plugin = runtime.getPlugin(MyPlugin.name) as MyPlugin; ``` [!ref Learn more about plugins](../plugins/plugin.md) - -### Retrieve the current session - -```ts -import type { AppSession } from "@sample/shared"; - -// If no sessionAccessor has been provided, an error is thrown. -const session = runtime.getSession() as AppSession; -``` diff --git a/docs/reference/runtime/runtime-context.md b/docs/reference/runtime/runtimeContext.md similarity index 100% rename from docs/reference/runtime/runtime-context.md rename to docs/reference/runtime/runtimeContext.md diff --git a/docs/reference/runtime/useNavigationItems.md b/docs/reference/runtime/useNavigationItems.md index ea5c452f8..9f8c98379 100644 --- a/docs/reference/runtime/useNavigationItems.md +++ b/docs/reference/runtime/useNavigationItems.md @@ -11,7 +11,7 @@ Retrieve the registered navigation items from the `FireflyRuntime` instance. ## Reference ```ts -const navigationItems = useNavigationItems() +const navigationItems = useNavigationItems(options?: { menuId? }) ``` ### Parameters @@ -21,7 +21,23 @@ const navigationItems = useNavigationItems() ### Returns -An array of `NavigationItem`. +An array of `NavigationLink | NavigationSection`. + +#### `NavigationLink` + +Accept any properties of a React Router [Link](https://reactrouter.com/en/main/components/link) component with the addition of: +- `$key`: An optional key identifying the link. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The link label. Could either by a `string` or a `ReactNode`. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the link should be rendered. +- `$additionalProps`: An optional object literal of additional props to apply to the link component. + +#### `NavigationSection` + +- `$key`: An optional key identifying the section. Usually used as the React element [key](https://legacy.reactjs.org/docs/lists-and-keys.html#keys) property. +- `$label`: The section label. Could either by a `string` or a `ReactNode`. +- `$canRender`: An optional function accepting an object and returning a `boolean` indicating whether or not the section should be rendered. +- `$additionalProps`: An optional object literal of additional props to apply to the section component. +- `children`: The section items. ## Usage diff --git a/docs/reference/runtime/useRuntime.md b/docs/reference/runtime/useRuntime.md index 6d2d39da8..307ed9536 100644 --- a/docs/reference/runtime/useRuntime.md +++ b/docs/reference/runtime/useRuntime.md @@ -9,7 +9,7 @@ toc: Retrieve a `FireflyRuntime` instance. !!!info -When possible, prefer [useRoutes](./useRoutes.md), [useNavigationItems](./useNavigationItems.md), [useLogger](./useLogger.md), [useSession](./useSession.md) to `useRuntime`. +Consider using [useRoutes](./useRoutes.md), [useNavigationItems](./useNavigationItems.md), [useLogger](./useLogger.md) instead of `useRuntime`. !!! ## Reference diff --git a/docs/reference/runtime/useSession.md b/docs/reference/runtime/useSession.md deleted file mode 100644 index dbe374f08..000000000 --- a/docs/reference/runtime/useSession.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -toc: - depth: 2-3 ---- - -# useSession - -Retrieve the current session from the `FireflyRuntime` instance. - -## Reference - -```ts -const session = useSession() -``` - -### Parameters - -None - -### Returns - -A custom session object. - -## Usage - -```ts -import { useSession } from "@squide/firefly"; -import type { AppSession } from "@sample/shared"; - -const session = useSession() as AppSession; - -const userName = session.userName; -``` diff --git a/docs/reference/session/index.yaml b/docs/reference/session/index.yaml deleted file mode 100644 index abb084c44..000000000 --- a/docs/reference/session/index.yaml +++ /dev/null @@ -1 +0,0 @@ -order: 30 diff --git a/docs/reference/session/useIsAuthenticated.md b/docs/reference/session/useIsAuthenticated.md deleted file mode 100644 index 6cee0b9a3..000000000 --- a/docs/reference/session/useIsAuthenticated.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -toc: - depth: 2-3 ---- - -# useIsAuthenticated - -Indicate whether or not the user is authenticated. - -> If the [sessionAccessor](/reference/runtime/runtime-class.md) function return a non `null` / `undefined` value, a user is considered as authenticated. - -## Reference - -```ts -const isAuthenticated = useIsAuthenticated() -``` - -### Parameters - -None - -### Returns - -A boolean value. - -## Usage - -```ts -import { useIsAuthenticated } from "@squide/firefly"; - -const isAuthentication = useIsAuthenticated(); -``` diff --git a/docs/reference/tanstack-query/index.yaml b/docs/reference/tanstack-query/index.yaml new file mode 100644 index 000000000..3f9f037cf --- /dev/null +++ b/docs/reference/tanstack-query/index.yaml @@ -0,0 +1,2 @@ +order: -15 +label: TanStack Query diff --git a/docs/reference/tanstack-query/isGlobalDataQueriesError.md b/docs/reference/tanstack-query/isGlobalDataQueriesError.md new file mode 100644 index 000000000..64675e2c2 --- /dev/null +++ b/docs/reference/tanstack-query/isGlobalDataQueriesError.md @@ -0,0 +1,73 @@ +--- +order: 80 +toc: + depth: 2-3 +--- + +# isGlobalDataQueriesError + +Indicates whether or not an error is an instance of [GlobalDataQueriesError](#globaldataquerieserror). + +!!!info +`GlobalDataQueriesError` errors are thrown by either the [usePublicDataQueries](./usePublicDataQueries.md) hook or the [useProtectedDataQueries](./useProtectedDataQueries.md) hook and should usually be handled by an error boundary. +!!! + +## Reference + +```ts +const result = isGlobalDataQueriesError(error); +``` + +### Parameters + +- `error`: An `Error` instance. + +### Returns + +A `boolean` value indicating whether or not the error is an instance of [GlobalDataQueriesError](#globaldataquerieserror). + +## Usage + +### Handle within an error boundary + +```tsx +import { isGlobalDataQueriesError } from "@squide/firefly"; +import { useLocation, useRouteError } from "react-router-dom"; + +export function ErrorBoundary() { + const error = useRouteError() as Error; + const location = useLocation(); + + useEffect(() => { + if (isGlobalDataQueriesError(error)) { + // ... + } + }, [location.pathname, error]); + + return ( +
            +

            Unmanaged error

            +

            An unmanaged error occurred and the application is broken, try refreshing your browser.

            +
            + ); +} +``` + +### Handle with a try/catch + +```ts +import { isGlobalDataQueriesError } from "@squide/firefly"; + +try { + // ... +} catch (error: unknown) { + if (isGlobalDataQueriesError(error)) { + // ... + } +} +``` + +## GlobalDataQueriesError + +- `message`: The error message. +- `errors`: An array of `Error` instances. diff --git a/docs/reference/tanstack-query/useProtectedDataQueries.md b/docs/reference/tanstack-query/useProtectedDataQueries.md new file mode 100644 index 000000000..4009d3dec --- /dev/null +++ b/docs/reference/tanstack-query/useProtectedDataQueries.md @@ -0,0 +1,384 @@ +--- +order: 90 +toc: + depth: 2-3 +--- + +# useProtectedDataQueries + +Execute the specified [Tanstack queries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) when the modules are ready, the **active route** is **protected** and, when applicable, [Mock Service Worker](https://mswjs.io/) is ready. + +!!!warning +Use this hook to **fetch** protected global data during the **bootstrapping phase** of your application. Avoid using it in product feature components. +!!! + +## Reference + +```ts +const results = useProtectedDataQueries(queries: [], isUnauthorizedError: (error) => boolean) +``` + +### Parameters + +- `queries`: An array of [QueriesOptions](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries). +- `isUnauthorizedError`: A function that returns a `boolean` value indicating whether or not the provided error is a `401` status code. + +### Returns + +An array of query response data. The order returned is the same as the input order. + +### Throws + +If an unmanaged error occur while performing any of the fetch requests, a [GlobalDataQueriesError](./isGlobalDataQueriesError.md#globaldataquerieserror) is thrown. + +## Usage + +### Define queries + +A `BootstrappingRoute` component is introduced in the following example because this hook must be rendered as a child of `rootRoute`. + +```tsx !#6-41,43-45,60,70 host/src/App.tsx +import { useProtectedDataQueries, useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { ApiError, SessionContext, SubscriptionContext, type Session, type Subscription } from "@sample/shared"; + +function BootstrappingRoute() { + const [session, subscription] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const response = await fetch("/api/session"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + const result: Session = { + user: { + id: data.userId, + name: data.username, + preferredLanguage: data.preferredLanguage + } + }; + + return result; + } + }, + { + queryKey: ["/api/subscription"], + queryFn: async () => { + const response = await fetch("/api/subscription"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + return (await response.json()) as Subscription; + } + } + ], error => isApiError(error) && error.status === 401); + + if (useIsBootstrapping()) { + return
            Loading...
            ; + } + + return ( + + + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +```ts shared/src/apiError.ts +export class ApiError extends Error { + readonly #status: number; + readonly #statusText: string; + readonly #stack?: string; + + constructor(status: number, statusText: string, innerStack?: string) { + super(`${status} ${statusText}`); + + this.#status = status; + this.#statusText = statusText; + this.#stack = innerStack; + } + + get status() { + return this.#status; + } + + get statusText() { + return this.#statusText; + } + + get stack() { + return this.#stack; + } +} + +export function isApiError(error?: unknown): error is ApiError { + return error !== undefined && error !== null && error instanceof ApiError; +} +``` + +#### `waitForProtectedData` & `useIsBootstrapping` + +To ensure the `AppRouter` component wait for the protected data to be ready before rendering the requested route, set the [waitForProtectedData](../routing/appRouter.md#delay-rendering-until-the-protected-data-is-ready) property to `true`. + +Combine this hook with the [useIsBootstrapping](../routing/useIsBootstrapping.md) hook to display a loader until the protected data is fetched and the application is ready. + +### Handle fetch errors + +This hook throws [GlobalDataQueriesError](./isGlobalDataQueriesError.md#globaldataquerieserror) instances, which are typically **unmanaged** and should be handled by an error boundary. To assert that an error is an instance of `GlobalDataQueriesError`, use the [isGlobalDataQueriesError](./isGlobalDataQueriesError.md) function. + +```tsx !#10 host/src/RootErrorBoundary.tsx +import { useLogger, isGlobalDataQueriesError } from "@squide/firefly"; +import { useLocation, useRouteError } from "react-router-dom"; + +export function RootErrorBoundary() { + const error = useRouteError() as Error; + const location = useLocation(); + const logger = useLogger(); + + useEffect(() => { + if (isGlobalDataQueriesError(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error.message, error.errors); + } + }, [location.pathname, error, logger]); + + return ( +
            +

            Unmanaged error

            +

            An unmanaged error occurred and the application is broken, try refreshing your browser.

            +
            + ); +} +``` + +```tsx !#58 host/src/App.tsx +import { useProtectedDataQueries, useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { ApiError, SessionContext, type Session } from "@sample/shared"; +import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; + +function BootstrappingRoute() { + const [session] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const response = await fetch("/api/session"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + const result: Session = { + user: { + id: data.userId, + name: data.username, + preferredLanguage: data.preferredLanguage + } + }; + + return result; + } + } + ], error => isApiError(error) && error.status === 401); + + if (useIsBootstrapping()) { + return
            Loading...
            ; + } + + return ( + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + errorElement: + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +### Handle 401 response + +Unauthorized requests are a special case that shouldn't be handled by an error boundary, as this would cause an **infinite loop** with the application's authentication boundary. + +To handle this, when the server returns a `401` status code, the `useProtectedDataQueries` hook instructs Squide to immediately render the page, triggering the authentication boundary, that will eventually redirect the user to a login page. + +Since Squide manages this process behind the scenes, you only need to register an `AuthenticationBoundary` component and provide an `isUnauthorizedError` handler to the `useProtectedDataQueries` hook. + +```tsx host/src/AuthenticationBoundary.tsx +import { useContext } from "react"; +import { Outlet, Navigate } from "react-router-dom"; +import { SessionContext } from "@sample/shared"; + +export function AuthenticationBoundary() { + const session = useContext(SessionContext); + + if (session) { + return ; + } + + return ; +} +``` + +!!!info +The `registerHost` function is registered as a [local module](../registration/registerLocalModules.md) of the host application. +!!! + +```tsx !#8 host/src/registerHost.tsx +import { ManagedRoutes, type ModuleRegisterFunction, type FireflyRuntime } from "@squide/firefly"; +import { AuthenticationBoundary } from "./AuthenticationBoundary.tsx"; + +export function registerHost() { + const register: ModuleRegisterFunction = runtime => { + runtime.registerRoute({ + // Pathless route to declare an authenticated boundary. + element: , + children: [ + ManagedRoutes + ] + }, { + hoist: true + }); + }; + + return register; +} +``` + +```tsx !#29 host/src/App.tsx +import { useProtectedDataQueries, useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { ApiError, SessionContext, type Session } from "@sample/shared"; + +function BootstrappingRoute() { + const [session] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const response = await fetch("/api/session"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + const data = await response.json(); + + const result: Session = { + user: { + id: data.userId, + name: data.username, + preferredLanguage: data.preferredLanguage + } + }; + + return result; + } + } + ], error => isApiError(error) && error.status === 401); + + if (useIsBootstrapping()) { + return
            Loading...
            ; + } + + return ( + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + + diff --git a/docs/reference/tanstack-query/usePublicDataQueries.md b/docs/reference/tanstack-query/usePublicDataQueries.md new file mode 100644 index 000000000..a3d0a3484 --- /dev/null +++ b/docs/reference/tanstack-query/usePublicDataQueries.md @@ -0,0 +1,223 @@ +--- +order: 100 +toc: + depth: 2-3 +--- + +# usePublicDataQueries + +Execute the specified [Tanstack queries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) once the modules are ready and, if applicable, [Mock Service Worker](https://mswjs.io/) is also ready. + +!!!warning +Use this hook to **fetch** public global data during the **bootstrapping phase** of your application. Avoid using it in product feature components. +!!! + +## Reference + +```ts +const results = usePublicDataQueries(queries: []) +``` + +### Parameters + +- `queries`: An array of [QueriesOptions](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries). + +### Returns + +An array of query response data. The order returned is the same as the input order. + +### Throws + +If an unmanaged error occur while performing any of the fetch requests, a [GlobalDataQueriesError](./isGlobalDataQueriesError.md#globaldataquerieserror) is thrown. + +## Usage + +### Define queries + +A `BootstrappingRoute` component is introduced in the following example because this hook must be rendered as a child of `rootRoute`. + +```tsx !#6-19,21-23,36,46 host/src/App.tsx +import { usePublicDataQueries, useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { ApiError, FeatureFlagsContext, type FeatureFlags } from "@sample/shared"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([ + { + queryKey: ["/api/feature-flags"], + queryFn: async () => { + const response = await fetch("/api/feature-flags"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + return (await response.json()) as FeatureFlags; + } + } + ]); + + if (useIsBootstrapping()) { + return
            Loading...
            ; + } + + return ( + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` + +```ts shared/src/apiError.ts +export class ApiError extends Error { + readonly #status: number; + readonly #statusText: string; + readonly #stack?: string; + + constructor(status: number, statusText: string, innerStack?: string) { + super(`${status} ${statusText}`); + + this.#status = status; + this.#statusText = statusText; + this.#stack = innerStack; + } + + get status() { + return this.#status; + } + + get statusText() { + return this.#statusText; + } + + get stack() { + return this.#stack; + } +} +``` + +#### `waitForPublicData` & `useIsBootstrapping` + +To ensure the `AppRouter` component wait for the public data to be ready before rendering the requested route, set the [waitForPublicData](../routing/appRouter.md#delay-rendering-until-the-public-data-is-ready) property to `true`. + +Combine this hook with the [useIsBootstrapping](../routing/useIsBootstrapping.md) hook to display a loader until the public data is fetched and the application is ready. + +### Handle fetch errors + +This hook throws [GlobalDataQueriesError](./isGlobalDataQueriesError.md#globaldataquerieserror) instances, which are typically **unmanaged** and should be handled by an error boundary. To assert that an error is an instance of `GlobalDataQueriesError`, use the [isGlobalDataQueriesError](./isGlobalDataQueriesError.md) function. + +```tsx !#10 host/src/RootErrorBoundary.tsx +import { useLogger, isGlobalDataQueriesError } from "@squide/firefly"; +import { useLocation, useRouteError } from "react-router-dom"; + +export function RootErrorBoundary() { + const error = useRouteError() as Error; + const location = useLocation(); + const logger = useLogger(); + + useEffect(() => { + if (isGlobalDataQueriesError(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error.message, error.errors); + } + }, [location.pathname, error, logger]); + + return ( +
            +

            Unmanaged error

            +

            An unmanaged error occurred and the application is broken, try refreshing your browser.

            +
            + ); +} +``` + +```tsx !#48 host/src/App.tsx +import { usePublicDataQueries, useIsBootstrapping, AppRouter } from "@squide/firefly"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { ApiError, FeatureFlagsContext, type FeatureFlags } from "@sample/shared"; +import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; + +function BootstrappingRoute() { + const [featureFlags] = usePublicDataQueries([ + { + queryKey: ["/api/feature-flags"], + queryFn: async () => { + const response = await fetch("/api/feature-flags"); + + if (!response.ok) { + throw new ApiError(response.status, response.statusText); + } + + return (await response.json()) as FeatureFlags; + } + } + ]); + + if (useIsBootstrapping()) { + return
            Loading...
            ; + } + + return ( + + + + ); +} + +export function App() { + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + errorElement: + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} +``` diff --git a/docs/reference/webpack/index.yaml b/docs/reference/webpack/index.yaml index 4557f02a7..e4c5d355f 100644 --- a/docs/reference/webpack/index.yaml +++ b/docs/reference/webpack/index.yaml @@ -1,2 +1,2 @@ -order: 0 +order: -10 label: "webpack" diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index e6c9bb823..95cddd8de 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -19,7 +19,7 @@ const runtime = new FireflyRuntime({ ## React context values are undefined -If you are encountering undefined values when providing a React context from the host application and consuming the context in modules, it is likely due to two possible reasons: either you have two instances of React, or you have multiple instances of that React context. +If your application utilize [remote modules](./reference/registration/registerRemoteModules.md) and you are encountering `undefined` values when providing a React context from the host application and consuming the context in modules, it is likely due to two possible reasons: either you have two instances of React, or you have multiple instances of that React context. To resolve this issue: @@ -31,4 +31,66 @@ To resolve this issue: If the issue persists, update your host application and remote module's webpack build configuration with the `optimize: false` option. Afterward, build the bundles and serve them. Open a web browser, access the DevTools, switch to the Network tab (ensure that JS files are listed), navigate to the application's homepage, and inspect the downloaded bundle files. The problematic React context definition should appear only once; otherwise, you may have multiple instances of the React context. -For additional information on shared dependency versioning, please refer to the [add a shared dependency guide](./guides/add-a-shared-dependency.md) and https://github.com/patricklafrance/wmf-versioning. +For additional information on shared dependency versioning, please refer to the [add a shared dependency guide](./guides/add-a-shared-dependency.md). + +## Console logs + +To faciliate the debugging of a Squide application bootstrapping flow, a lot of information is logged into the console when in development. We recommend using these logs if you suspect that **something** is **wrong** with the **bootstrapping** process of your **application**. + +### Modules registration + +#### Local modules + +- `[squide] Found 4 local modules to register.` +- `[squide] 1/4 Registering local module.` +- `[squide] 1/4 Local module registration completed.` + +#### Remote modules + +- `[squide] Found 1 remote module to register.` +- `[squide] 1/1 Loading module "register" of remote "remote1".` +- `[squide] 1/1 Registering module "register" of remote "remote1".` +- `[squide] 1/1 The registration of the remote "remote1" is completed.` + +#### Deferred registrations + +- `[squide] 1/1 Registering the deferred registrations for module "register" of remote "remote1".` +- `[squide] 1/1 Registered the deferred registrations for module "register" of remote "remote1".` +- `[squide] 3/3 Updating local module deferred registration.` +- `[squide] 3/3 Updated local module deferred registration.` + +#### Ready + +- `[squide] Modules are ready.` + +### Routes registration + +- `[squide] The following route registration is pending until "managed-routes-placeholder" is registered.` +- `[squide] The following route has been registered as a children of the "managed-routes-placeholder" route.` +- `[squide] The following route has been registered.` + +### Navigation items registration + +- `[squide] The following static navigation item has been registered to the "/federated-tabs" menu for a total of 2 static items.` +- `[squide] The following deferred navigation item has been registered to the "root" menu for a total of 4 deferred items.` + +### Mock Service Worker registration + +- `[squide] The following MSW request handlers has been registered: [...]` +- `[squide] MSW is ready.` + +### AppRouter logs + +- `[squide] AppRouter state updated: {...}` +- `[squide] The following action has been dispatched to the AppRouter reducer: {...}` + +### i18n logs + +- `[squide] Registered a new i18next instance with key "shell": {...}` +- `[squide] The language has been changed to "fr-CA".` +- `[squide] Detected "fr-CA" as user language.` + +### Module federation logs + +- `[squide] Module Federation shared scope is available: {...}` + diff --git a/knip.ts b/knip.ts index 0f195016b..d93ac61cb 100644 --- a/knip.ts +++ b/knip.ts @@ -21,47 +21,47 @@ function defineWorkspace({ ignore, ...config }: KnipWorkspaceConfig, transformer return transformedConfig; } -function ignoreWebpackConfigsLoaders({ ignoreMiniCssExtractPlugin = false }: { ignoreMiniCssExtractPlugin?: boolean } = {}): KnipTransformer { - return ({ ignoreDependencies, ...config }) => ({ - ...config, - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - "@svgr/webpack", - "swc-loader", - "css-loader", - "postcss-loader", - "style-loader", - !ignoreMiniCssExtractPlugin && "mini-css-extract-plugin" - ].filter(Boolean) as string[] - }); -} +// function ignoreWebpackConfigsLoaders({ ignoreMiniCssExtractPlugin = false }: { ignoreMiniCssExtractPlugin?: boolean } = {}): KnipTransformer { +// return ({ ignoreDependencies, ...config }) => ({ +// ...config, +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// "@svgr/webpack", +// "swc-loader", +// "css-loader", +// "postcss-loader", +// "style-loader", +// !ignoreMiniCssExtractPlugin && "mini-css-extract-plugin" +// ].filter(Boolean) as string[] +// }); +// } -const ignoreBrowserslist: KnipTransformer = ({ ignoreDependencies, ...config }) => { - return { - ...config, - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - // Browserlist isn't supported by plugins. - "@workleap/browserslist-config" - ] - }; -}; +// const ignoreBrowserslist: KnipTransformer = ({ ignoreDependencies, ...config }) => { +// return { +// ...config, +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// // Browserlist isn't supported by plugins. +// "@workleap/browserslist-config" +// ] +// }; +// }; -const configureMsw: KnipTransformer = ({ entry, ignore, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/mocks/browser.ts", - "src/mocks/handlers.ts" - ], - ignore: [ - ...(ignore as string[] ?? []), - // MSW isn't supported by plugins. - "public/mockServiceWorker.js" - ] - }; -}; +// const configureMsw: KnipTransformer = ({ entry, ignore, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/mocks/browser.ts", +// "src/mocks/handlers.ts" +// ], +// ignore: [ +// ...(ignore as string[] ?? []), +// // MSW isn't supported by plugins. +// "public/mockServiceWorker.js" +// ] +// }; +// }; const configurePackage: KnipTransformer = config => { return { @@ -73,141 +73,141 @@ const configurePackage: KnipTransformer = config => { }; }; -const configureSampleHost: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/index.ts" - ], - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - // Browserlist isn't supported by plugins. - "@workleap/browserslist-config", - // It's an optional dependency of @workleap/webpack-configs. - "webpack-dev-server" - ], - eslint: true, - webpack: { - config: ["webpack.*.js"] - } - }; -}; +// const configureSampleHost: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/index.ts" +// ], +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// // Browserlist isn't supported by plugins. +// "@workleap/browserslist-config", +// // It's an optional dependency of @workleap/webpack-configs. +// "webpack-dev-server" +// ], +// eslint: true, +// webpack: { +// config: ["webpack.*.js"] +// } +// }; +// }; -const configureSampleLocalModule: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/register.tsx", - // Isolated environment. - "src/dev/index.tsx" - ], - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - // It's an optional dependency of @workleap/webpack-configs. - "webpack-dev-server" - ], - eslint: true, - tsup: { - config: ["tsup.*.ts"] - }, - webpack: { - config: ["webpack.config.js", "webpack.*.js"] - } - }; -}; +// const configureSampleLocalModule: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/register.tsx", +// // Isolated environment. +// "src/dev/index.tsx" +// ], +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// // It's an optional dependency of @workleap/webpack-configs. +// "webpack-dev-server" +// ], +// eslint: true, +// tsup: { +// config: ["tsup.*.ts"] +// }, +// webpack: { +// config: ["webpack.config.js", "webpack.*.js"] +// } +// }; +// }; -const configureSampleRemoteModule: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/register.tsx", - // Isolated environment. - "src/dev/index.tsx" - ], - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - // It's an optional dependency of @workleap/webpack-configs. - "webpack-dev-server" - ], - eslint: true, - webpack: { - config: ["webpack.*.js"] - } - }; -}; +// const configureSampleRemoteModule: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/register.tsx", +// // Isolated environment. +// "src/dev/index.tsx" +// ], +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// // It's an optional dependency of @workleap/webpack-configs. +// "webpack-dev-server" +// ], +// eslint: true, +// webpack: { +// config: ["webpack.*.js"] +// } +// }; +// }; -const configureSampleLibrary: KnipTransformer = ({ entry, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/index.ts" - ], - eslint: true, - tsup: { - config: ["tsup.*.ts"] - } - }; -}; +// const configureSampleLibrary: KnipTransformer = ({ entry, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/index.ts" +// ], +// eslint: true, +// tsup: { +// config: ["tsup.*.ts"] +// } +// }; +// }; -const configureTemplateHost: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/index.ts" - ], - ignoreDependencies: [ - ...(ignoreDependencies as string[] ?? []), - // Browserlist isn't supported by plugins. - "@workleap/browserslist-config" - ], - eslint: true, - webpack: { - config: ["webpack.*.js"] - } - }; -}; +// const configureTemplateHost: KnipTransformer = ({ entry, ignoreDependencies, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/index.ts" +// ], +// ignoreDependencies: [ +// ...(ignoreDependencies as string[] ?? []), +// // Browserlist isn't supported by plugins. +// "@workleap/browserslist-config" +// ], +// eslint: true, +// webpack: { +// config: ["webpack.*.js"] +// } +// }; +// }; -const configureTemplateLocalModule: KnipTransformer = ({ entry, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/register.tsx" - ], - eslint: true, - tsup: { - config: ["tsup.*.ts"] - } - }; -}; +// const configureTemplateLocalModule: KnipTransformer = ({ entry, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/register.tsx" +// ], +// eslint: true, +// tsup: { +// config: ["tsup.*.ts"] +// } +// }; +// }; -const configureTemplateRemoteModule: KnipTransformer = ({ entry, ...config }) => { - return { - ...config, - entry: [ - ...(entry as string[] ?? []), - "src/register.tsx" - ], - eslint: true, - webpack: { - config: ["webpack.*.js"] - } - }; -}; +// const configureTemplateRemoteModule: KnipTransformer = ({ entry, ...config }) => { +// return { +// ...config, +// entry: [ +// ...(entry as string[] ?? []), +// "src/register.tsx" +// ], +// eslint: true, +// webpack: { +// config: ["webpack.*.js"] +// } +// }; +// }; const rootConfig: KnipWorkspaceConfig = defineWorkspace({ - ignoreBinaries: [ - // This binaries is called "build-endpoints-isolated" for the samples. - "build-isolated" - ], + // ignoreBinaries: [ + // // This binaries is called "build-endpoints-isolated" for the samples. + // "build-isolated" + // ], ignoreDependencies: [ // Azure Devops pipeline aren't supported by plugins. - "netlify-cli", + // "netlify-cli", // Installed once for all the workspace's projects "ts-node" ] @@ -225,83 +225,88 @@ const mswConfig: KnipWorkspaceConfig = defineWorkspace({ configurePackage ]); -const sampleHost: KnipWorkspaceConfig = defineWorkspace({}, [ - configureSampleHost, - ignoreWebpackConfigsLoaders(), - ignoreBrowserslist, - configureMsw -]); +// const sampleHost: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureSampleHost, +// ignoreWebpackConfigsLoaders(), +// ignoreBrowserslist, +// configureMsw +// ]); -const sampleLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ - configureSampleLocalModule, - ignoreWebpackConfigsLoaders(), - ignoreBrowserslist, - configureMsw -]); +// const sampleLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureSampleLocalModule, +// ignoreWebpackConfigsLoaders(), +// ignoreBrowserslist, +// configureMsw +// ]); -const sampleRemoteModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ - configureSampleRemoteModule, - ignoreWebpackConfigsLoaders(), - ignoreBrowserslist, - configureMsw -]); +// const sampleRemoteModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureSampleRemoteModule, +// ignoreWebpackConfigsLoaders(), +// ignoreBrowserslist, +// configureMsw +// ]); -const sampleLibraryConfig: KnipWorkspaceConfig = defineWorkspace({}, [ - configureSampleLibrary, - configureMsw -]); +// const sampleLibraryConfig: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureSampleLibrary, +// configureMsw +// ]); -const sampleBasicLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({ - ignoreDependencies: [ - // It seems like because it's used with a non-standard nodemon filename, knip can't detect the usage - // of the webpack CLI. - "webpack-cli" - ] -}, [ - configureSampleLocalModule, - ignoreWebpackConfigsLoaders({ ignoreMiniCssExtractPlugin: true }), - ignoreBrowserslist, - configureMsw -]); +// const sampleBasicLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({ +// ignoreDependencies: [ +// // It seems like because it's used with a non-standard nodemon filename, knip can't detect the usage +// // of the webpack CLI. +// "webpack-cli" +// ] +// }, [ +// configureSampleLocalModule, +// ignoreWebpackConfigsLoaders({ ignoreMiniCssExtractPlugin: true }), +// ignoreBrowserslist, +// configureMsw +// ]); -const templateHost: KnipWorkspaceConfig = defineWorkspace({}, [ - configureTemplateHost, - ignoreWebpackConfigsLoaders(), - ignoreBrowserslist -]); +// const templateHost: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureTemplateHost, +// ignoreWebpackConfigsLoaders(), +// ignoreBrowserslist +// ]); -const templateLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ - configureTemplateLocalModule -]); +// const templateLocalModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureTemplateLocalModule +// ]); -const templateRemoteModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ - configureTemplateRemoteModule, - ignoreWebpackConfigsLoaders(), - ignoreBrowserslist -]); +// const templateRemoteModuleConfig: KnipWorkspaceConfig = defineWorkspace({}, [ +// configureTemplateRemoteModule, +// ignoreWebpackConfigsLoaders(), +// ignoreBrowserslist +// ]); const config: KnipConfig = { workspaces: { ".": rootConfig, "packages/*": packagesConfig, - "packages/msw": mswConfig, - "samples/basic/host": sampleHost, - "samples/basic/local-module": sampleBasicLocalModuleConfig, - "samples/basic/another-remote-module": sampleRemoteModuleConfig, - "samples/basic/remote-module": sampleRemoteModuleConfig, - "samples/basic/shared": sampleLibraryConfig, - "samples/basic/shell": sampleLibraryConfig, - "samples/endpoints/host": sampleHost, - "samples/endpoints/local-module": sampleLocalModuleConfig, - "samples/endpoints/remote-module": sampleRemoteModuleConfig, - "samples/endpoints/shared": sampleLibraryConfig, - "samples/endpoints/shell": sampleLibraryConfig, - "samples/endpoints/i18next": sampleLibraryConfig, - "samples/endpoints/layouts": sampleLibraryConfig, - "templates/getting-started/apps/host": templateHost, - "templates/getting-started/apps/local-module": templateLocalModuleConfig, - "templates/getting-started/apps/remote-module": templateRemoteModuleConfig + "packages/msw": mswConfig + // "samples/basic/host": sampleHost, + // "samples/basic/local-module": sampleBasicLocalModuleConfig, + // "samples/basic/another-remote-module": sampleRemoteModuleConfig, + // "samples/basic/remote-module": sampleRemoteModuleConfig, + // "samples/basic/shared": sampleLibraryConfig, + // "samples/basic/shell": sampleLibraryConfig, + // "samples/endpoints/host": sampleHost, + // "samples/endpoints/local-module": sampleLocalModuleConfig, + // "samples/endpoints/remote-module": sampleRemoteModuleConfig, + // "samples/endpoints/shared": sampleLibraryConfig, + // "samples/endpoints/shell": sampleLibraryConfig, + // "samples/endpoints/i18next": sampleLibraryConfig, + // "samples/endpoints/layouts": sampleLibraryConfig, + // "templates/getting-started/apps/host": templateHost, + // "templates/getting-started/apps/local-module": templateLocalModuleConfig, + // "templates/getting-started/apps/remote-module": templateRemoteModuleConfig }, + // Temporary ignoring + ignoreWorkspaces: [ + "samples/**", + "templates/**" + ], exclude: [ // It cause issues with config like Jest "projects". "unresolved" diff --git a/package.json b/package.json index 6031d50ad..c03a1890f 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,14 @@ "dev": "turbo run dev --filter=./packages/*", "build": "turbo run build --filter=./packages/*", "ci-build": "turbo run build --filter=./packages/* --cache-dir=node_modules/.cache/turbo", - "pretest": "turbo run build", + "pretest": "turbo run build --filter=./packages/*", "test": "jest", - "prelint": "turbo run build", + "prelint": "turbo run --filter=!@getting-started/* build", "lint": "pnpm run \"/^lint:.*/\"", "lint:eslint": "eslint . --max-warnings=-0 --cache --cache-location node_modules/.cache/eslint", "lint:knip": "knip --cache --cache-location node_modules/.cache/knip", - "lint:installed-check": "installed-check", - "lint:types": "pnpm -r --parallel --include-workspace-root exec tsc", + "lint:installed-check": "installed-check --engine-check --version-check", + "lint:types": "pnpm -r --parallel --include-workspace-root --filter=!@getting-started/* exec tsc", "changeset": "changeset", "publish-pkg": "changeset publish", "clean": "pnpm -r --parallel --include-workspace-root exec pnpm dlx rimraf dist .turbo .netlify node_modules/.cache", @@ -34,28 +34,29 @@ "deploy-endpoints": "cross-env NETLIFY=true turbo run deploy --filter=./samples/endpoints/*", "deploy-endpoints-isolated": "cross-env NETLIFY=true turbo run deploy-isolated --filter=./samples/endpoints/*", "dev-docs": "retype start", - "list-outdated-deps": "pnpm outdated -r --format list !eslint !useless-lib", - "update-outdated-deps": "pnpm update -r --latest !eslint !useless-lib" + "list-outdated-deps": "pnpm outdated -r --format list !eslint !useless-lib !turbo", + "update-outdated-deps": "pnpm update -r --latest !eslint !useless-lib !turbo" }, "devDependencies": { "@changesets/changelog-github": "0.5.0", - "@changesets/cli": "2.27.1", - "@types/node": "20.12.7", - "@typescript-eslint/parser": "7.8.0", + "@changesets/cli": "2.27.7", + "@types/node": "20.14.11", + "@typescript-eslint/parser": "7.16.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/typescript-configs": "3.0.2", "cross-env": "7.0.3", "eslint": "8.57.0", "installed-check": "9.3.0", "jest": "29.7.0", - "knip": "5.12.3", + "knip": "5.26.0", "retypeapp": "3.5.0", "ts-node": "10.9.2", "turbo": "1.13.3", - "typescript": "5.4.5" + "typescript": "5.5.3" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.0.0", + "pnpm": ">=9" }, "packageManager": "pnpm@9.5.0+sha512.140036830124618d624a2187b50d04289d5a087f326c9edfc0ccd733d76c4f52c3a313d4fc148794a2a9d81553016004e6742e8cf850670268a7387fc220c903" } diff --git a/packages/core/package.json b/packages/core/package.json index bc771c3b8..be607b780 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,10 +35,10 @@ "react-dom": "*" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/tsup-configs": "3.0.6", @@ -46,8 +46,8 @@ "eslint": "8.57.0", "jest": "29.7.0", "react": "18.3.1", - "tsup": "8.0.2", - "typescript": "5.4.5" + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "eventemitter3": "5.0.1" diff --git a/packages/core/src/federation/mergeDeferredRegistrations.ts b/packages/core/src/federation/mergeDeferredRegistrations.ts index baadc4e91..96eccde85 100644 --- a/packages/core/src/federation/mergeDeferredRegistrations.ts +++ b/packages/core/src/federation/mergeDeferredRegistrations.ts @@ -12,9 +12,9 @@ export function mergeDeferredRegistrations(candidates: (DeferredRegistrat return deferredRegistrations[0]; } - const mergeFunction: DeferredRegistrationFunction = async data => { + const mergeFunction: DeferredRegistrationFunction = async (data, state) => { for (const x of deferredRegistrations) { - await x(data); + await x(data, state); } }; diff --git a/packages/core/src/federation/moduleRegistrationStatus.ts b/packages/core/src/federation/moduleRegistrationStatus.ts deleted file mode 100644 index bcef8c7b3..000000000 --- a/packages/core/src/federation/moduleRegistrationStatus.ts +++ /dev/null @@ -1 +0,0 @@ -export type ModuleRegistrationStatus = "none" | "in-progress" | "registered" | "in-completion" | "ready"; diff --git a/packages/core/src/federation/moduleRegistry.ts b/packages/core/src/federation/moduleRegistry.ts new file mode 100644 index 000000000..6c62b2b3a --- /dev/null +++ b/packages/core/src/federation/moduleRegistry.ts @@ -0,0 +1,28 @@ +import type { Runtime } from "../runtime/runtime.ts"; + +export type ModuleRegistrationStatus = "none" | "registering-modules" | "modules-registered" | "registering-deferred-registration" | "ready"; + +export interface RegisterModulesOptions { + context?: TContext; +} + +export type ModuleRegistrationStatusChangedListener = () => void; + +export interface ModuleRegistrationError { + // The registration error. + error: unknown; +} + +export abstract class ModuleRegistry { + abstract registerModules(modules: unknown, runtime: TRuntime, options?: RegisterModulesOptions): Promise; + + abstract registerDeferredRegistrations(data: TData, runtime: TRuntime): Promise; + + abstract updateDeferredRegistrations(data: TData, runtime: TRuntime): Promise; + + abstract registerStatusChangedListener(callback: ModuleRegistrationStatusChangedListener): void; + + abstract removeStatusChangedListener(callback: ModuleRegistrationStatusChangedListener): void; + + abstract get registrationStatus(): ModuleRegistrationStatus; +} diff --git a/packages/core/src/federation/registerLocalModules.ts b/packages/core/src/federation/registerLocalModules.ts index 4eefba81e..6952e3967 100644 --- a/packages/core/src/federation/registerLocalModules.ts +++ b/packages/core/src/federation/registerLocalModules.ts @@ -1,6 +1,6 @@ import type { Runtime } from "../runtime/runtime.ts"; import { isFunction } from "../shared/assertions.ts"; -import type { ModuleRegistrationStatus } from "./moduleRegistrationStatus.ts"; +import type { ModuleRegistrationError, ModuleRegistrationStatus, ModuleRegistrationStatusChangedListener, ModuleRegistry, RegisterModulesOptions } from "./moduleRegistry.ts"; import { registerModule, type DeferredRegistrationFunction, type ModuleRegisterFunction } from "./registerModule.ts"; interface DeferredRegistration { @@ -8,49 +8,38 @@ interface DeferredRegistration { fct: DeferredRegistrationFunction; } -export interface RegisterLocalModulesOptions { - context?: TContext; -} - -export type LocalModuleRegistrationStatusChangedListener = () => void; - -export interface LocalModuleRegistrationError { - // The registration error. - error: unknown; -} - -export class LocalModuleRegistry { +export class LocalModuleRegistry implements ModuleRegistry { #registrationStatus: ModuleRegistrationStatus = "none"; - #deferredRegistrations: DeferredRegistration[] = []; - readonly #statusChangedListeners = new Set(); + readonly #deferredRegistrations: DeferredRegistration[] = []; + readonly #statusChangedListeners = new Set(); - async registerModules(registerFunctions: ModuleRegisterFunction[], runtime: TRuntime, { context }: RegisterLocalModulesOptions = {}) { - const errors: LocalModuleRegistrationError[] = []; + async registerModules, TContext = unknown, TData = unknown>(registrationFunctions: ModuleRegisterFunction[], runtime: TRuntime, { context }: RegisterModulesOptions = {}) { + const errors: ModuleRegistrationError[] = []; if (this.#registrationStatus !== "none") { throw new Error("[squide] The registerLocalModules function can only be called once."); } - runtime.logger.debug(`[squide] Found ${registerFunctions.length} local module${registerFunctions.length !== 1 ? "s" : ""} to register.`); + runtime.logger.debug(`[squide] Found ${registrationFunctions.length} local module${registrationFunctions.length !== 1 ? "s" : ""} to register.`); - this.#setRegistrationStatus("in-progress"); + this.#setRegistrationStatus("registering-modules"); - await Promise.allSettled(registerFunctions.map(async (x, index) => { - runtime.logger.debug(`[squide] ${index + 1}/${registerFunctions.length} Registering local module.`); + await Promise.allSettled(registrationFunctions.map(async (x, index) => { + runtime.logger.debug(`[squide] ${index + 1}/${registrationFunctions.length} Registering local module.`); try { const optionalDeferredRegistration = await registerModule(x as ModuleRegisterFunction, runtime, context); if (isFunction(optionalDeferredRegistration)) { this.#deferredRegistrations.push({ - index: `${index + 1}/${registerFunctions.length}`, + index: `${index + 1}/${registrationFunctions.length}`, fct: optionalDeferredRegistration as DeferredRegistrationFunction }); } } catch (error: unknown) { runtime.logger.error( - `[squide] ${index + 1}/${registerFunctions.length} An error occured while registering a local module.`, + `[squide] ${index + 1}/${registrationFunctions.length} An error occured while registering a local module.`, error ); @@ -59,40 +48,40 @@ export class LocalModuleRegistry { }); } - runtime.logger.debug(`[squide] ${index + 1}/${registerFunctions.length} Local module registration completed.`); + runtime.logger.debug(`[squide] ${index + 1}/${registrationFunctions.length} Local module registration completed.`); })); - this.#setRegistrationStatus(this.#deferredRegistrations.length > 0 ? "registered" : "ready"); + this.#setRegistrationStatus(this.#deferredRegistrations.length > 0 ? "modules-registered" : "ready"); return errors; } - async completeModuleRegistrations(runtime: TRuntime, data?: TData) { - const errors: LocalModuleRegistrationError[] = []; + async registerDeferredRegistrations(data: TData, runtime: TRuntime) { + const errors: ModuleRegistrationError[] = []; - if (this.#registrationStatus === "none" || this.#registrationStatus === "in-progress") { - throw new Error("[squide] The completeLocalModuleRegistration function can only be called once the registerLocalModules function terminated."); + if (this.#registrationStatus === "none" || this.#registrationStatus === "registering-modules") { + throw new Error("[squide] The registerDeferredRegistrations function can only be called once the local modules are registered."); } - if (this.#registrationStatus !== "registered" && this.#deferredRegistrations.length > 0) { - throw new Error("[squide] The completeLocalModuleRegistration function can only be called once."); + if (this.#registrationStatus !== "modules-registered" && this.#deferredRegistrations.length > 0) { + throw new Error("[squide] The registerDeferredRegistrations function can only be called once."); } if (this.#registrationStatus === "ready") { // No deferred registrations were returned by the local modules, skip the completion process. - return Promise.resolve(errors); + return errors; } - this.#setRegistrationStatus("in-completion"); + this.#setRegistrationStatus("registering-deferred-registration"); await Promise.allSettled(this.#deferredRegistrations.map(async ({ index, fct: deferredRegister }) => { - runtime.logger.debug(`[squide] ${index} Completing local module deferred registration.`, "Data:", data); + runtime.logger.debug(`[squide] ${index} Registering local module deferred registration.`, "Data:", data); try { - await deferredRegister(data); + await deferredRegister(data, "register"); } catch (error: unknown) { runtime.logger.error( - `[squide] ${index} An error occured while completing the registration of a local module.`, + `[squide] ${index} An error occured while registering the deferred registrations of a local module.`, error ); @@ -101,7 +90,7 @@ export class LocalModuleRegistry { }); } - runtime.logger.debug(`[squide] ${index} Completed local module deferred registration.`); + runtime.logger.debug(`[squide] ${index} Registered local module deferred registration.`); })); this.#setRegistrationStatus("ready"); @@ -109,11 +98,40 @@ export class LocalModuleRegistry { return errors; } - registerStatusChangedListener(callback: LocalModuleRegistrationStatusChangedListener) { + async updateDeferredRegistrations(data: TData, runtime: TRuntime) { + const errors: ModuleRegistrationError[] = []; + + if (this.#registrationStatus !== "ready") { + throw new Error("[squide] The updateDeferredRegistrations function can only be called once the local modules are ready."); + } + + await Promise.allSettled(this.#deferredRegistrations.map(async ({ index, fct: deferredRegister }) => { + runtime.logger.debug(`[squide] ${index} Updating local module deferred registration.`, "Data:", data); + + try { + await deferredRegister(data, "update"); + } catch (error: unknown) { + runtime.logger.error( + `[squide] ${index} An error occured while updating the deferred registrations of a local module.`, + error + ); + + errors.push({ + error + }); + } + + runtime.logger.debug(`[squide] ${index} Updated local module deferred registration.`); + })); + + return errors; + } + + registerStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { this.#statusChangedListeners.add(callback); } - removeStatusChangedListener(callback: LocalModuleRegistrationStatusChangedListener) { + removeStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { this.#statusChangedListeners.delete(callback); } @@ -128,39 +146,48 @@ export class LocalModuleRegistry { get registrationStatus() { return this.#registrationStatus; } +} + +let localModuleRegistry: ModuleRegistry | undefined; - // Strictly for Jest tests, this is NOT ideal. - __reset() { - // Bypass the "setRegistrationStatus" function to prevent calling the listeners. - this.#registrationStatus = "none"; - this.#deferredRegistrations = []; - this.#statusChangedListeners.clear(); +function getLocalModuleRegistry() { + if (!localModuleRegistry) { + localModuleRegistry = new LocalModuleRegistry(); } + + return localModuleRegistry; +} + +// This function should only be used by tests. +export function __setLocalModuleRegistry(registry: ModuleRegistry) { + localModuleRegistry = registry; } -const localModuleRegistry = new LocalModuleRegistry(); +// This function should only be used by tests. +export function __clearLocalModuleRegistry() { + localModuleRegistry = undefined; +} -export function registerLocalModules(registerFunctions: ModuleRegisterFunction[], runtime: TRuntime, options?: RegisterLocalModulesOptions) { - return localModuleRegistry.registerModules(registerFunctions, runtime, options); +export function registerLocalModules(modules: ModuleRegisterFunction[], runtime: TRuntime, options?: RegisterModulesOptions) { + return getLocalModuleRegistry().registerModules(modules, runtime, options); } -export function completeLocalModuleRegistrations(runtime: TRuntime, data?: TData) { - return localModuleRegistry.completeModuleRegistrations(runtime, data); +export function registerLocalModuleDeferredRegistrations(data: TData, runtime: TRuntime) { + return getLocalModuleRegistry().registerDeferredRegistrations(data, runtime); } -export function getLocalModuleRegistrationStatus() { - return localModuleRegistry.registrationStatus; +export function updateLocalModuleDeferredRegistrations(data: TData, runtime: TRuntime) { + return getLocalModuleRegistry().updateDeferredRegistrations(data, runtime); } -export function addLocalModuleRegistrationStatusChangedListener(callback: LocalModuleRegistrationStatusChangedListener) { - localModuleRegistry.registerStatusChangedListener(callback); +export function getLocalModuleRegistrationStatus() { + return getLocalModuleRegistry().registrationStatus; } -export function removeLocalModuleRegistrationStatusChangedListener(callback: LocalModuleRegistrationStatusChangedListener) { - localModuleRegistry.removeStatusChangedListener(callback); +export function addLocalModuleRegistrationStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + getLocalModuleRegistry().registerStatusChangedListener(callback); } -// Strictly for Jest tests, this is NOT ideal. -export function __resetLocalModuleRegistrations() { - localModuleRegistry.__reset(); +export function removeLocalModuleRegistrationStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + getLocalModuleRegistry().removeStatusChangedListener(callback); } diff --git a/packages/core/src/federation/registerModule.ts b/packages/core/src/federation/registerModule.ts index afd0cb37e..9d13b696d 100644 --- a/packages/core/src/federation/registerModule.ts +++ b/packages/core/src/federation/registerModule.ts @@ -1,6 +1,8 @@ import type { Runtime } from "../runtime/runtime.ts"; -export type DeferredRegistrationFunction = (data?: TData) => Promise | void; +export type DeferredRegistrationOperation = "register" | "update"; + +export type DeferredRegistrationFunction = (data: TData, operation: DeferredRegistrationOperation) => Promise | void; export type ModuleRegisterFunction = (runtime: TRuntime, context?: TContext) => Promise | void> | DeferredRegistrationFunction | void; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 77ed71df0..b29e4a1fa 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,26 +1,21 @@ export * from "./shared/assertions.ts"; +export * from "./logging/consoleLogger.ts"; +export * from "./logging/logger.ts"; +export * from "./runtime/runtime.ts"; export * from "./runtime/RuntimeContext.ts"; export * from "./runtime/RuntimeLogger.ts"; -export * from "./runtime/runtime.ts"; export * from "./runtime/useEventBus.ts"; -export * from "./runtime/useLogOnceLogger.ts"; export * from "./runtime/useLogger.ts"; export * from "./runtime/usePlugin.ts"; export * from "./runtime/useRuntimeMode.ts"; -export * from "./runtime/useSession.ts"; - -export * from "./logging/consoleLogger.ts"; -export * from "./logging/logger.ts"; - -export * from "./session/useIsAuthenticated.ts"; export * from "./messaging/eventBus.ts"; export * from "./messaging/useEventBusDispatcher.ts"; export * from "./messaging/useEventBusListener.ts"; export * from "./federation/mergeDeferredRegistrations.ts"; -export * from "./federation/moduleRegistrationStatus.ts"; +export * from "./federation/moduleRegistry.ts"; export * from "./federation/registerLocalModules.ts"; export * from "./federation/registerModule.ts"; diff --git a/packages/core/src/plugins/plugin.ts b/packages/core/src/plugins/plugin.ts index 4fec33545..e60cdeec4 100644 --- a/packages/core/src/plugins/plugin.ts +++ b/packages/core/src/plugins/plugin.ts @@ -1,15 +1,15 @@ import type { Runtime } from "../runtime/runtime.ts"; export abstract class Plugin { - protected readonly _name: string; + readonly #name: string; + protected readonly _runtime: Runtime; - constructor(name: string) { - this._name = name; + constructor(name: string, runtime: Runtime) { + this.#name = name; + this._runtime = runtime; } get name() { - return this._name; + return this.#name; } - - _setRuntime?(runtime: Runtime): void; } diff --git a/packages/core/src/runtime/runtime.ts b/packages/core/src/runtime/runtime.ts index 6891fec34..c11889157 100644 --- a/packages/core/src/runtime/runtime.ts +++ b/packages/core/src/runtime/runtime.ts @@ -3,15 +3,14 @@ import { EventBus } from "../messaging/eventBus.ts"; import type { Plugin } from "../plugins/plugin.ts"; import { RuntimeLogger } from "./RuntimeLogger.ts"; -export type SessionAccessorFunction = () => unknown; - export type RuntimeMode = "development" | "production"; +export type PluginFactory = (runtime: Runtime) => Plugin; + export interface RuntimeOptions { mode?: RuntimeMode; loggers?: Logger[]; - plugins?: Plugin[]; - sessionAccessor?: SessionAccessorFunction; + plugins?: PluginFactory[]; } export interface RegisterRouteOptions { @@ -31,20 +30,14 @@ export abstract class Runtime { protected readonly _logger: RuntimeLogger; protected readonly _eventBus: EventBus; protected readonly _plugins: Plugin[]; - protected _sessionAccessor?: SessionAccessorFunction; - constructor({ mode = "development", loggers, plugins = [], sessionAccessor }: RuntimeOptions = {}) { + constructor({ mode = "development", loggers, plugins = [] }: RuntimeOptions = {}) { this._mode = mode; - this._plugins = plugins; this._logger = new RuntimeLogger(loggers); this._eventBus = new EventBus({ logger: this._logger }); - this._sessionAccessor = sessionAccessor; - this._plugins.forEach(x => { - if (x._setRuntime) { - x._setRuntime(this); - } - }); + // It's important to instanciate the plugins once all the properties are set. + this._plugins = plugins.map(x => x(this)); } abstract registerRoute(route: TRoute, options?: RegisterRouteOptions): void; @@ -55,6 +48,10 @@ export abstract class Runtime { abstract getNavigationItems(menuId?: string): TNavigationItem[]; + abstract startDeferredRegistrationScope(transactional?: boolean): void; + + abstract completeDeferredRegistrationScope(): void; + get mode() { return this._mode; } @@ -81,16 +78,7 @@ export abstract class Runtime { return this._eventBus; } - getSession() { - if (!this._sessionAccessor) { - throw new Error("[squide] Cannot retrieve the session because no session accessor has been provided. Did you provide a sessionAccessor function to the Runtime instance?"); - } - - return this._sessionAccessor(); - } - - // Prefixed by _ to indicate that it's considered as an "internal" method. - _completeRegistration() { - this._logger.debug("[squide] %cModules are ready%c.", "color: white; background-color: green;", ""); - } + // Prefixed by _ to indicate that it's considered as an "internal" method, cannot use "#"" because of inheritance. + // Not abstract so concrete classes are not required to provide an implementation. + _validateRegistrations() {} } diff --git a/packages/core/src/runtime/useLogOnceLogger.ts b/packages/core/src/runtime/useLogOnceLogger.ts deleted file mode 100644 index fdec1e62a..000000000 --- a/packages/core/src/runtime/useLogOnceLogger.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { useMemo } from "react"; -import type { Logger } from "../logging/logger.ts"; -import { useLogger } from "./useLogger.ts"; - -// This is an internal class to ensure that when the application is in React strict mode -// and the application is being runned in development, no messages are logged twice. -export class LogOnceLogger implements Logger { - readonly #logger: Logger; - readonly #hasLoggedOnce = new Set(); - - constructor(logger: Logger) { - this.#logger = logger; - } - - #logOnce(key: string, action: () => Promise) { - if (!this.#hasLoggedOnce.has(key)) { - this.#hasLoggedOnce.add(key); - - return action(); - } - - return Promise.resolve(); - } - - debug(log: string, ...rest: unknown[]) { - return this.#logger.debug(log, ...rest); - } - - debugOnce(key: string, log: string, ...rest: unknown[]) { - this.#logOnce(key, () => this.debug(log, ...rest)); - } - - information(log: string, ...rest: unknown[]) { - return this.#logger.information(log, ...rest); - } - - informationOnce(key: string, log: string, ...rest: unknown[]) { - this.#logOnce(key, () => this.information(log, ...rest)); - } - - warning(log: string, ...rest: unknown[]) { - return this.#logger.warning(log, ...rest); - } - - warningOnce(key: string, log: string, ...rest: unknown[]) { - this.#logOnce(key, () => this.warning(log, ...rest)); - } - - error(log: string, ...rest: unknown[]) { - return this.#logger.error(log, ...rest); - } - - errorOnce(key: string, log: string, ...rest: unknown[]) { - this.#logOnce(key, () => this.error(log, ...rest)); - } - - critical(log: string, ...rest: unknown[]) { - return this.#logger.critical(log, ...rest); - } - - criticalOnce(key: string, log: string, ...rest: unknown[]) { - this.#logOnce(key, () => this.critical(log, ...rest)); - } -} - -export function useLogOnceLogger() { - const logger = useLogger(); - - return useMemo(() => { - return new LogOnceLogger(logger); - }, [logger]); -} diff --git a/packages/core/src/runtime/useSession.ts b/packages/core/src/runtime/useSession.ts deleted file mode 100644 index ac392cc3d..000000000 --- a/packages/core/src/runtime/useSession.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useRuntime } from "./RuntimeContext.ts"; - -export function useSession() { - const runtime = useRuntime(); - - return runtime.getSession(); -} diff --git a/packages/core/src/session/useIsAuthenticated.ts b/packages/core/src/session/useIsAuthenticated.ts deleted file mode 100644 index c85bd3a92..000000000 --- a/packages/core/src/session/useIsAuthenticated.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useSession } from "../runtime/useSession.ts"; -import { isNil } from "../shared/assertions.ts"; - -export function useIsAuthenticated() { - const session = useSession(); - - return !isNil(session); -} diff --git a/packages/core/tests/moduleDeferredRegistrations.test.ts b/packages/core/tests/mergeDeferredRegistrations.test.ts similarity index 74% rename from packages/core/tests/moduleDeferredRegistrations.test.ts rename to packages/core/tests/mergeDeferredRegistrations.test.ts index 52aec68dc..982df2c7e 100644 --- a/packages/core/tests/moduleDeferredRegistrations.test.ts +++ b/packages/core/tests/mergeDeferredRegistrations.test.ts @@ -10,25 +10,25 @@ test("when deferred registrations are provided, all the deferred registrations a const mergeFunction = mergeDeferredRegistrations([fct1, fct2, fct3]); - await mergeFunction!(); + await mergeFunction!("foo", "register"); expect(fct1).toHaveBeenCalledTimes(1); expect(fct2).toHaveBeenCalledTimes(1); expect(fct3).toHaveBeenCalledTimes(1); }); -test("when deferred registrations are provided and there's deferred data, all the deferred registrations are called with the data", async () => { +test("when deferred registrations are provided, all the deferred registrations are called with the provided data and state", async () => { const fct1: DeferredRegistrationFunction = jest.fn(); const fct2: DeferredRegistrationFunction = jest.fn(); const fct3: DeferredRegistrationFunction = jest.fn(); const mergeFunction = mergeDeferredRegistrations([fct1, fct2, fct3]); - await mergeFunction!("foo"); + await mergeFunction!("foo", "register"); - expect(fct1).toHaveBeenCalledWith("foo"); - expect(fct2).toHaveBeenCalledWith("foo"); - expect(fct3).toHaveBeenCalledWith("foo"); + expect(fct1).toHaveBeenCalledWith("foo", "register"); + expect(fct2).toHaveBeenCalledWith("foo", "register"); + expect(fct3).toHaveBeenCalledWith("foo", "register"); }); test("when void results are provided, the void results are ignored", async () => { @@ -37,10 +37,10 @@ test("when void results are provided, the void results are ignored", async () => const mergeFunction = mergeDeferredRegistrations([noop(), fct1, noop(), fct2]); - await mergeFunction!("foo"); + await mergeFunction!("foo", "register"); - expect(fct1).toHaveBeenCalledWith("foo"); - expect(fct2).toHaveBeenCalledWith("foo"); + expect(fct1).toHaveBeenCalledWith("foo", "register"); + expect(fct2).toHaveBeenCalledWith("foo", "register"); }); test("when no deferred registrations are provided, return undefined", () => { @@ -54,9 +54,9 @@ test("when a single deferred registration is provided, the deferred registration const mergeFunction = mergeDeferredRegistrations([fct]); - await mergeFunction!("foo"); + await mergeFunction!("foo", "register"); - expect(fct).toHaveBeenCalledWith("foo"); + expect(fct).toHaveBeenCalledWith("foo", "register"); }); test("when a single deferred registration is provided, return the deferred registration", async () => { diff --git a/packages/core/tests/completeLocalModuleRegistrations.test.ts b/packages/core/tests/registerLocalModuleDeferredRegistrations.test.ts similarity index 62% rename from packages/core/tests/completeLocalModuleRegistrations.test.ts rename to packages/core/tests/registerLocalModuleDeferredRegistrations.test.ts index 53b370a42..a23711b3f 100644 --- a/packages/core/tests/completeLocalModuleRegistrations.test.ts +++ b/packages/core/tests/registerLocalModuleDeferredRegistrations.test.ts @@ -25,6 +25,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); @@ -32,7 +40,7 @@ const runtime = new DummyRuntime(); test("when called before registerLocalModules, throw an error", async () => { const registry = new LocalModuleRegistry(); - await expect(() => registry.completeModuleRegistrations(runtime, {})).rejects.toThrow(/The completeLocalModuleRegistration function can only be called once the registerLocalModules function terminated/); + await expect(() => registry.registerDeferredRegistrations({}, runtime)).rejects.toThrow(/The registerDeferredRegistrations function can only be called once the local modules are registered/); }); test("when called twice, throw an error", async () => { @@ -43,9 +51,9 @@ test("when called twice, throw an error", async () => { () => () => {} ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); - await expect(() => registry.completeModuleRegistrations(runtime, {})).rejects.toThrow(/The completeLocalModuleRegistration function can only be called once/); + await expect(() => registry.registerDeferredRegistrations({}, runtime)).rejects.toThrow(/The registerDeferredRegistrations function can only be called once/); }); test("when called for the first time but the registration status is already \"ready\", return a resolving promise", async () => { @@ -59,12 +67,12 @@ test("when called for the first time but the registration status is already \"re expect(registry.registrationStatus).toBe("ready"); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(registry.registrationStatus).toBe("ready"); }); -test("can complete all the deferred registrations", async () => { +test("can register all the deferred registrations", async () => { const registry = new LocalModuleRegistry(); const register1 = jest.fn(); @@ -77,14 +85,14 @@ test("can complete all the deferred registrations", async () => { () => register3 ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(register1).toHaveBeenCalled(); expect(register2).toHaveBeenCalled(); expect(register3).toHaveBeenCalled(); }); -test("when all the deferred registrations are completed, set the status to \"ready\"", async () => { +test("when all the deferred registrations are registered, set the status to \"ready\"", async () => { const registry = new LocalModuleRegistry(); await registry.registerModules([ @@ -92,9 +100,9 @@ test("when all the deferred registrations are completed, set the status to \"rea () => () => {} ], runtime); - expect(registry.registrationStatus).toBe("registered"); + expect(registry.registrationStatus).toBe("modules-registered"); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(registry.registrationStatus).toBe("ready"); }); @@ -114,12 +122,12 @@ test("when a deferred registration is asynchronous, the function can be awaited" () => () => {} ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(hasBeenCompleted).toBeTruthy(); }); -test("when a deferred registration fail, complete the remaining deferred registrations", async () => { +test("when a deferred registration fail, register the remaining deferred registrations", async () => { const registry = new LocalModuleRegistry(); const register1 = jest.fn(); @@ -131,7 +139,7 @@ test("when a deferred registration fail, complete the remaining deferred registr () => register3 ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(register1).toHaveBeenCalled(); expect(register3).toHaveBeenCalled(); @@ -146,13 +154,37 @@ test("when a deferred registration fail, return the error", async () => { () => () => {} ], runtime); - const errors = await registry.completeModuleRegistrations(runtime, {}); + const errors = await registry.registerDeferredRegistrations({}, runtime); expect(errors.length).toBe(1); expect(errors[0]!.error!.toString()).toContain("Module 2 deferred registration failed"); }); -test("when data is provided, all the deferred module registrations receive the data object", async () => { +test("all the deferred module registrations receive the data object", async () => { + const registry = new LocalModuleRegistry(); + + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + await registry.registerModules([ + () => register1, + () => register2, + () => register3 + ], runtime); + + const data = { + foo: "bar" + }; + + await registry.registerDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "register"); + expect(register2).toHaveBeenCalledWith(data, "register"); + expect(register3).toHaveBeenCalledWith(data, "register"); +}); + +test("all the deferred module registrations receive \"register\" as state", async () => { const registry = new LocalModuleRegistry(); const register1 = jest.fn(); @@ -169,11 +201,11 @@ test("when data is provided, all the deferred module registrations receive the d foo: "bar" }; - await registry.completeModuleRegistrations(runtime, data); + await registry.registerDeferredRegistrations(data, runtime); - expect(register1).toHaveBeenCalledWith(data); - expect(register2).toHaveBeenCalledWith(data); - expect(register3).toHaveBeenCalledWith(data); + expect(register1).toHaveBeenCalledWith(data, "register"); + expect(register2).toHaveBeenCalledWith(data, "register"); + expect(register3).toHaveBeenCalledWith(data, "register"); }); diff --git a/packages/core/tests/registerLocalModules.test.ts b/packages/core/tests/registerLocalModules.test.ts index c34538f0b..96b2a2473 100644 --- a/packages/core/tests/registerLocalModules.test.ts +++ b/packages/core/tests/registerLocalModules.test.ts @@ -25,6 +25,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); @@ -84,7 +92,7 @@ test("when there are no deferred registrations, once all the modules are registe expect(registry.registrationStatus).toBe("ready"); }); -test("when there are deferred registrations, once all the modules are registered, set the status to \"registered\"", async () => { +test("when there are deferred registrations, once all the modules are registered, set the status to \"modules-registered\"", async () => { const registry = new LocalModuleRegistry(); await registry.registerModules([ @@ -92,7 +100,7 @@ test("when there are deferred registrations, once all the modules are registered () => () => {} ], runtime); - expect(registry.registrationStatus).toBe("registered"); + expect(registry.registrationStatus).toBe("modules-registered"); }); test("when a module registration fail, register the remaining modules", async () => { @@ -124,4 +132,26 @@ test("when a module registration fail, return the error", async () => { expect(errors[0]!.error!.toString()).toContain("Module 2 registration failed"); }); +test("when a context is provided, all the register functions receive the provided context", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + const registry = new LocalModuleRegistry(); + + const context = { + foo: "bar" + }; + + await registry.registerModules([ + register1, + register2, + register3 + ], runtime, { context }); + + expect(register1).toHaveBeenCalledWith(runtime, context); + expect(register2).toHaveBeenCalledWith(runtime, context); + expect(register3).toHaveBeenCalledWith(runtime, context); +}); + diff --git a/packages/core/tests/updateLocalModuleDeferredRegistrations.test.ts b/packages/core/tests/updateLocalModuleDeferredRegistrations.test.ts new file mode 100644 index 000000000..9a7662291 --- /dev/null +++ b/packages/core/tests/updateLocalModuleDeferredRegistrations.test.ts @@ -0,0 +1,220 @@ +import { LocalModuleRegistry } from "../src/federation/registerLocalModules.ts"; +import { Runtime } from "../src/runtime/runtime.ts"; + +function simulateDelay(delay: number) { + return new Promise(resolve => { + setTimeout(() => { + resolve(undefined); + }, delay); + }); +} + +class DummyRuntime extends Runtime { + registerRoute() { + throw new Error("Method not implemented."); + } + + get routes() { + return []; + } + + registerNavigationItem() { + throw new Error("Method not implemented."); + } + + getNavigationItems() { + return []; + } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } +} + +const runtime = new DummyRuntime(); + +test("when called before registerLocalModules, throw an error", async () => { + const registry = new LocalModuleRegistry(); + + await expect(() => registry.updateDeferredRegistrations({}, runtime)).rejects.toThrow(/The updateDeferredRegistrations function can only be called once the local modules are ready/); +}); + +test("when called before registerLocalModuleDeferredRegistrations, throw an error", async () => { + const registry = new LocalModuleRegistry(); + + await registry.registerModules([ + () => () => {}, + () => () => {}, + () => () => {} + ], runtime); + + await expect(() => registry.updateDeferredRegistrations({}, runtime)).rejects.toThrow(/The updateDeferredRegistrations function can only be called once the local modules are ready/); +}); + +test("can update all the deferred registrations", async () => { + const registry = new LocalModuleRegistry(); + + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + await registry.registerModules([ + () => register1, + () => register2, + () => register3 + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register2.mockReset(); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(register1).toHaveBeenCalled(); + expect(register2).toHaveBeenCalled(); + expect(register3).toHaveBeenCalled(); +}); + +test("when a deferred registration is asynchronous, the function can be awaited", async () => { + const registry = new LocalModuleRegistry(); + + let hasBeenCompleted = false; + + await registry.registerModules([ + () => () => {}, + // Do not wait on the "registerDeferredRegistrations" call + // but wait on the "updateDeferredRegistrations" call. + () => jest.fn() + .mockImplementationOnce(() => {}) + .mockImplementationOnce(async () => { + await simulateDelay(10); + + hasBeenCompleted = true; + }), + () => () => {} + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(hasBeenCompleted).toBeTruthy(); +}); + +test("when a deferred registration fail, update the remaining deferred registrations", async () => { + const registry = new LocalModuleRegistry(); + + const register1 = jest.fn(); + const register3 = jest.fn(); + + await registry.registerModules([ + () => register1, + // Do not throw on the "registerDeferredRegistrations" call + // but throw on the "updateDeferredRegistrations" call. + () => jest.fn() + .mockImplementationOnce(() => {}) + .mockImplementationOnce(async () => { + throw new Error("Module 2 registration failed"); + }), + () => register3 + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register3.mockReset(); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(register1).toHaveBeenCalled(); + expect(register3).toHaveBeenCalled(); +}); + +test("when a deferred registration fail, return the error", async () => { + const registry = new LocalModuleRegistry(); + + await registry.registerModules([ + () => () => {}, + // Do not throw on the "registerDeferredRegistrations" call + // but throw on the "updateDeferredRegistrations" call. + () => jest.fn() + .mockImplementationOnce(() => {}) + .mockImplementationOnce(async () => { + throw new Error("Module 2 registration failed"); + }), + () => () => {} + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + const errors = await registry.updateDeferredRegistrations({}, runtime); + + expect(errors.length).toBe(1); + expect(errors[0]!.error!.toString()).toContain("Module 2 registration failed"); +}); + +test("all the deferred module registrations receive the data object", async () => { + const registry = new LocalModuleRegistry(); + + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + await registry.registerModules([ + () => register1, + () => register2, + () => register3 + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register3.mockReset(); + + const data = { + foo: "bar" + }; + + await registry.updateDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "update"); + expect(register2).toHaveBeenCalledWith(data, "update"); + expect(register3).toHaveBeenCalledWith(data, "update"); +}); + +test("all the deferred module registrations receive \"update\" as state", async () => { + const registry = new LocalModuleRegistry(); + + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + await registry.registerModules([ + () => register1, + () => register2, + () => register3 + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register3.mockReset(); + + const data = { + foo: "bar" + }; + + await registry.updateDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "update"); + expect(register2).toHaveBeenCalledWith(data, "update"); + expect(register3).toHaveBeenCalledWith(data, "update"); +}); diff --git a/packages/fakes/package.json b/packages/fakes/package.json index e41407c5b..f9c7b9e21 100644 --- a/packages/fakes/package.json +++ b/packages/fakes/package.json @@ -35,8 +35,8 @@ "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "@squide/core": "workspace:*" diff --git a/packages/fakes/src/index.ts b/packages/fakes/src/index.ts index a1f2a534c..7bc2b03f0 100644 --- a/packages/fakes/src/index.ts +++ b/packages/fakes/src/index.ts @@ -1,3 +1,5 @@ +export * from "./localStorageAccessor.ts"; +export * from "./localStorageManager.ts"; +export * from "./localStorageSessionAccessor.ts"; export * from "./localStorageSessionManager.ts"; -export * from "./readonlySessionLocalStorage.ts"; diff --git a/packages/fakes/src/localStorageAccessor.ts b/packages/fakes/src/localStorageAccessor.ts new file mode 100644 index 000000000..4b4161a86 --- /dev/null +++ b/packages/fakes/src/localStorageAccessor.ts @@ -0,0 +1,19 @@ +import { isNilOrEmpty } from "@squide/core"; + +export class LocalStorageAccessor { + readonly #key: string; + + constructor(key: string) { + this.#key = key; + } + + getObjectValue() { + const rawValue = window.localStorage.getItem(this.#key); + + if (!isNilOrEmpty(rawValue)) { + return JSON.parse(rawValue) as T; + } + + return undefined; + } +} diff --git a/packages/fakes/src/localStorageManager.ts b/packages/fakes/src/localStorageManager.ts new file mode 100644 index 000000000..4097e74be --- /dev/null +++ b/packages/fakes/src/localStorageManager.ts @@ -0,0 +1,42 @@ +import { isNil, isNilOrEmpty } from "@squide/core"; + +export class LocalStorageManager { + readonly #key: string; + #cache?: T = undefined; + + constructor(key: string) { + this.#key = key; + } + + setObjectValue(value: T) { + if (isNil(value)) { + window.localStorage.removeItem(this.#key); + } else { + window.localStorage.setItem(this.#key, JSON.stringify(value)); + } + + this.#cache = undefined; + } + + getObjectValue() { + if (!isNil(this.#cache)) { + return this.#cache; + } + + const rawValue = window.localStorage.getItem(this.#key); + + if (!isNilOrEmpty(rawValue)) { + this.#cache = JSON.parse(rawValue); + + return this.#cache; + } + + return undefined; + } + + clearStorage() { + this.#cache = undefined; + + window.localStorage.removeItem(this.#key); + } +} diff --git a/packages/fakes/src/localStorageSessionAccessor.ts b/packages/fakes/src/localStorageSessionAccessor.ts new file mode 100644 index 000000000..7b83790f5 --- /dev/null +++ b/packages/fakes/src/localStorageSessionAccessor.ts @@ -0,0 +1,18 @@ +import { LocalStorageAccessor } from "./localStorageAccessor.ts"; +import { SessionLocalStorageKey } from "./sessionKey.ts"; + +export interface LocalStorageSessionAccessorOptions { + key?: string; +} + +export class LocalStorageSessionAccessor { + readonly #localStorageAccessor: LocalStorageAccessor; + + constructor({ key = SessionLocalStorageKey }: LocalStorageSessionAccessorOptions = {}) { + this.#localStorageAccessor = new LocalStorageAccessor(key); + } + + getSession() { + return this.#localStorageAccessor.getObjectValue(); + } +} diff --git a/packages/fakes/src/localStorageSessionManager.ts b/packages/fakes/src/localStorageSessionManager.ts index 134f90c30..c6502aa7e 100644 --- a/packages/fakes/src/localStorageSessionManager.ts +++ b/packages/fakes/src/localStorageSessionManager.ts @@ -1,4 +1,4 @@ -import { isNil, isNilOrEmpty } from "@squide/core"; +import { LocalStorageManager } from "./localStorageManager.ts"; import { SessionLocalStorageKey } from "./sessionKey.ts"; export interface LocalStorageSessionManagerOptions { @@ -6,42 +6,21 @@ export interface LocalStorageSessionManagerOptions { } export class LocalStorageSessionManager { - readonly #key: string; - #cache?: T = undefined; + readonly #localStorageManager: LocalStorageManager; constructor({ key = SessionLocalStorageKey }: LocalStorageSessionManagerOptions = {}) { - this.#key = key; + this.#localStorageManager = new LocalStorageManager(key); } setSession(session: T) { - if (isNil(session)) { - window.localStorage.removeItem(this.#key); - } else { - window.localStorage.setItem(this.#key, JSON.stringify(session)); - } - - this.#cache = undefined; + this.#localStorageManager.setObjectValue(session); } getSession() { - if (!isNil(this.#cache)) { - return this.#cache; - } - - const rawSession = window.localStorage.getItem(this.#key); - - if (!isNilOrEmpty(rawSession)) { - this.#cache = JSON.parse(rawSession); - - return this.#cache; - } - - return undefined; + return this.#localStorageManager.getObjectValue(); } clearSession() { - this.#cache = undefined; - - window.localStorage.removeItem(this.#key); + this.#localStorageManager.clearStorage(); } } diff --git a/packages/fakes/src/readonlySessionLocalStorage.ts b/packages/fakes/src/readonlySessionLocalStorage.ts deleted file mode 100644 index bdfb5162d..000000000 --- a/packages/fakes/src/readonlySessionLocalStorage.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { isNil, isNilOrEmpty } from "@squide/core"; -import { SessionLocalStorageKey } from "./sessionKey.ts"; - -export interface ReadonlySessionLocalStorageOptions { - key?: string; -} - -export class ReadonlySessionLocalStorage { - readonly #key: string; - #cache?: T = undefined; - - constructor({ key = SessionLocalStorageKey }: ReadonlySessionLocalStorageOptions = {}) { - this.#key = key; - } - - getSession() { - if (!isNil(this.#cache)) { - return this.#cache; - } - - const rawSession = window.localStorage.getItem(this.#key); - - if (!isNilOrEmpty(rawSession)) { - this.#cache = JSON.parse(rawSession); - - return this.#cache; - } - - return undefined; - } -} diff --git a/packages/firefly-webpack-configs/package.json b/packages/firefly-webpack-configs/package.json index 047208e3d..db5c1cf9c 100644 --- a/packages/firefly-webpack-configs/package.json +++ b/packages/firefly-webpack-configs/package.json @@ -40,8 +40,8 @@ "webpack-dev-server": ">=5.0.0" }, "devDependencies": { - "@module-federation/enhanced": "0.1.11", - "@swc/core": "1.4.17", + "@module-federation/enhanced": "0.2.6", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", "@workleap/eslint-plugin": "3.2.2", @@ -51,10 +51,10 @@ "eslint": "8.57.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "ts-jest": "29.1.2", - "tsup": "8.0.2", - "typescript": "5.4.5", - "webpack": "5.91.0" + "ts-jest": "29.2.3", + "tsup": "8.1.2", + "typescript": "5.5.3", + "webpack": "5.93.0" }, "dependencies": { "@squide/webpack-configs": "workspace:*", diff --git a/packages/firefly/jest.config.ts b/packages/firefly/jest.config.ts index 994f0febf..1b237ca78 100644 --- a/packages/firefly/jest.config.ts +++ b/packages/firefly/jest.config.ts @@ -8,11 +8,19 @@ const config: Config = { transform: { "^.+\\.(js|ts|tsx)$": ["@swc/jest", swcConfig as Record] }, + transformIgnorePatterns: [ + "node_modules/(?!.pnpm|memoize|mimic-function)" + ], moduleNameMapper: { ...pathsToModuleNameMapper(compilerOptions.paths, { prefix: "" }) }, + globals: { + __webpack_share_scopes__: { + default: {} + } + }, setupFilesAfterEnv: ["/jest-setup.js"], cacheDirectory: "./node_modules/.cache/jest" }; diff --git a/packages/firefly/package.json b/packages/firefly/package.json index 98b7d6104..e2ab34cd5 100644 --- a/packages/firefly/package.json +++ b/packages/firefly/package.json @@ -2,7 +2,7 @@ "name": "@squide/firefly", "author": "Workleap", "version": "8.0.0", - "description": "Helpers to facilitate the creation of a shell package with Squide firefly technology stack.", + "description": "Helpers to facilitate the creation of an application with the Squide firefly technology stack.", "license": "Apache-2.0", "repository": { "type": "git", @@ -31,19 +31,19 @@ "build": "tsup --config ./tsup.build.ts" }, "peerDependencies": { + "@tanstack/react-query": "*", "msw": "*", "react": "*", "react-dom": "*", - "react-error-boundary": "*", "react-router-dom": "*" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", - "@testing-library/jest-dom": "6.4.2", - "@testing-library/react": "15.0.5", + "@testing-library/jest-dom": "6.4.6", + "@testing-library/react": "16.0.0", "@types/jest": "29.5.12", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", @@ -52,14 +52,13 @@ "eslint": "8.57.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "msw": "2.2.14", + "msw": "2.3.1", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0", - "ts-jest": "29.1.2", - "tsup": "8.0.2", - "typescript": "5.4.5" + "react-router-dom": "6.25.1", + "ts-jest": "29.2.3", + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "@squide/core": "workspace:*", diff --git a/packages/firefly/src/AppRouter.tsx b/packages/firefly/src/AppRouter.tsx index 3b5127a46..a029217e2 100644 --- a/packages/firefly/src/AppRouter.tsx +++ b/packages/firefly/src/AppRouter.tsx @@ -1,256 +1,63 @@ -import { isNil, useLogOnceLogger } from "@squide/core"; -import { useAreModulesReady, useAreModulesRegistered } from "@squide/module-federation"; -import { useIsMswStarted } from "@squide/msw"; -import { findRouteByPath, useIsRouteProtected, useRouteMatch, useRoutes, type Route } from "@squide/react-router"; -import { cloneElement, useCallback, useEffect, useMemo, type ReactElement } from "react"; -import { ErrorBoundary, useErrorBoundary } from "react-error-boundary"; -import { Outlet, useLocation, type RouterProviderProps } from "react-router-dom"; - -export type OnLoadPublicDataFunction = (signal: AbortSignal) => Promise; - -export type OnLoadProtectedDataFunction = (signal: AbortSignal) => Promise; - -export type OnCompleteRegistrationsFunction = () => Promise; - -function useLoadPublicData(areModulesRegistered: boolean, areModulesReady: boolean, isMswStarted: boolean, isLoaded: boolean, onLoadData?: OnLoadPublicDataFunction) { - const logger = useLogOnceLogger(); - - const { showBoundary } = useErrorBoundary(); - - useEffect(() => { - // Don't go further if no handler has been provided to load public data. - if (onLoadData && !isLoaded) { - if ((areModulesRegistered || areModulesReady) && isMswStarted) { - // Prevent logging twice because of React strict mode. - logger.debugOnce("loading-public-data", "[shell] Loading public data."); - - const abortController = new AbortController(); - const signal = abortController.signal; - - const result = onLoadData(signal); - - if (!isPromise(result)) { - throw Error("[squide] An AppRouter onLoadPublicData handler must return a promise object."); - } - - result - .then(() => { - // Prevent logging twice because of React strict mode. - logger.debugOnce("public-data-loaded", "[shell] Public data has been loaded."); - }) - .catch(error => { - // Do not handle aborted requests. - if (!signal.aborted) { - showBoundary(error); - } - }); - - return () => { - abortController.abort(); - }; - } - } - }, [areModulesRegistered, areModulesReady, isMswStarted, isLoaded, showBoundary, onLoadData, logger]); +import { useLogger } from "@squide/core"; +import { useRoutes, type Route } from "@squide/react-router"; +import { useEffect, useMemo, type ReactElement } from "react"; +import type { RouterProviderProps } from "react-router-dom"; +import { AppRouterDispatcherContext, AppRouterStateContext } from "./AppRouterContext.ts"; +import { useAppRouterReducer } from "./AppRouterReducer.ts"; +import { RootRoute } from "./RootRoute.tsx"; +import { useStrictRegistrationMode } from "./useStrictRegistrationMode.ts"; + +export interface AppRouterRenderFunctionArgs { + routes: Route[]; } -function useLoadProtectedData(areModulesRegistered: boolean, areModulesReady: boolean, isMswStarted: boolean, isActiveRouteProtected: boolean, isLoaded: boolean, onLoadData?: OnLoadProtectedDataFunction) { - const logger = useLogOnceLogger(); - - const { showBoundary } = useErrorBoundary(); - - useEffect(() => { - // Don't go further if no handler has been provided to load protected data. - if (onLoadData && !isLoaded) { - if ((areModulesRegistered || areModulesReady) && isMswStarted) { - if (isActiveRouteProtected) { - // Prevent logging twice because of React strict mode. - logger.debugOnce("loading-protected-data", `[shell] Loading protected data as "${location.pathname}" is a protected route.`); - - const abortController = new AbortController(); - const signal = abortController.signal; - - const result = onLoadData(signal); - - if (!isPromise(result)) { - throw Error("[squide] An AppRouter onLoadProtectedData handler must return a promise object."); - } - - result - .then(() => { - // Prevent logging twice because of React strict mode. - logger.debugOnce("protected-data-loaded", "[shell] Protected data has been loaded."); - }) - .catch(error => { - // Do not handle aborted requests. - if (!signal.aborted) { - showBoundary(error); - } - }); - - return () => { - abortController.abort(); - }; - } else { - // Prevent logging twice because of React strict mode. - logger.debugOnce("is-a-public-route", `[shell] Not loading protected data as "${location.pathname}" is a public route.`); - } - } - } - }, [areModulesRegistered, areModulesReady, isMswStarted, isActiveRouteProtected, isLoaded, showBoundary, onLoadData, logger]); -} - -interface BootstrappingRouteProps { - fallbackElement: ReactElement; - onLoadPublicData?: OnLoadPublicDataFunction; - onLoadProtectedData?: OnLoadProtectedDataFunction; - isPublicDataLoaded: boolean; - isProtectedDataLoaded: boolean; - onCompleteRegistrations?: OnCompleteRegistrationsFunction; - waitForMsw: boolean; - areModulesRegistered: boolean; - areModulesReady: boolean; +export interface RenderRouterProviderFunctionArgs { + rootRoute: ReactElement; + registeredRoutes: Route[]; + routerProviderProps: Omit; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function isPromise(value: any): value is Promise { - return !isNil(value) && !isNil(value.then) && !isNil(value.catch); -} - -// Most of the bootstrapping logic has been moved to this component because AppRouter -// cannot leverage "useLocation" since it must be used in a child component of "RouterProvider". -export function BootstrappingRoute(props: BootstrappingRouteProps) { - const { - fallbackElement, - onLoadPublicData, - onLoadProtectedData, - isPublicDataLoaded, - isProtectedDataLoaded, - onCompleteRegistrations, - waitForMsw, - areModulesRegistered, - areModulesReady - } = props; - - const logger = useLogOnceLogger(); - const location = useLocation(); - - // Re-render the app once MSW is started, otherwise, the API calls for module routes will return a 404 status. - const isMswStarted = useIsMswStarted(waitForMsw); - - useEffect(() => { - // Only log these messages if MSW is enabled. - if (waitForMsw) { - if ((areModulesRegistered || areModulesReady) && !isMswStarted) { - // Prevent logging twice because of React strict mode. - logger.debugOnce("waiting-for-msw", `[shell] Modules are ${areModulesReady ? "ready" : "registered"}, waiting for MSW to start...`); - } else if (!areModulesRegistered && !areModulesReady && isMswStarted) { - // Prevent logging twice because of React strict mode. - logger.debugOnce("waiting-for-modules", "[shell] MSW is started, waiting for the modules..."); - } - } - }, [logger, areModulesRegistered, areModulesReady, isMswStarted, waitForMsw]); - - // Try to load the public data if an handler is defined. - useLoadPublicData(areModulesRegistered, areModulesReady, isMswStarted, isPublicDataLoaded, onLoadPublicData); - - // Only throw when there's no match if the modules has been registered, otherwise it's expected that there are no registered routes. - const activeRoute = useRouteMatch(location, { throwWhenThereIsNoMatch: areModulesReady }); - const isActiveRouteProtected = useIsRouteProtected(activeRoute); - - // Try to load the protected data if an handler is defined. - useLoadProtectedData(areModulesRegistered, areModulesReady, isMswStarted, isActiveRouteProtected, isProtectedDataLoaded, onLoadProtectedData); - - useEffect(() => { - // Don't go further if no handler has been provided to complete the registration. - if (onCompleteRegistrations) { - if (areModulesRegistered && isMswStarted && isPublicDataLoaded && (!isActiveRouteProtected || isProtectedDataLoaded)) { - if (!areModulesReady) { - onCompleteRegistrations(); - } - } - } - }, [areModulesRegistered, areModulesReady, isMswStarted, isPublicDataLoaded, isProtectedDataLoaded, isActiveRouteProtected, onCompleteRegistrations]); - - if (!areModulesReady || !isMswStarted || !activeRoute || !isPublicDataLoaded || (isActiveRouteProtected && !isProtectedDataLoaded)) { - return fallbackElement; - } - - return ( - - ); -} - -export type RenderRouterProviderFunction = (routes: Route[], providerProps: Omit) => ReactElement; +export type RenderRouterProviderFunction = (args: RenderRouterProviderFunctionArgs) => ReactElement; export interface AppRouterProps { - fallbackElement: ReactElement; - errorElement: ReactElement; - onLoadPublicData?: OnLoadPublicDataFunction; - onLoadProtectedData?: OnLoadProtectedDataFunction; - isPublicDataLoaded?: boolean; - isProtectedDataLoaded?: boolean; - onCompleteRegistrations?: OnCompleteRegistrationsFunction; waitForMsw: boolean; + waitForPublicData?: boolean; + waitForProtectedData?: boolean; children: RenderRouterProviderFunction; } export function AppRouter(props: AppRouterProps) { const { - fallbackElement, - errorElement, - onLoadPublicData, - onLoadProtectedData, - isPublicDataLoaded = true, - isProtectedDataLoaded = true, - onCompleteRegistrations, waitForMsw, + waitForPublicData = false, + waitForProtectedData = false, children: renderRouterProvider } = props; - // Re-render the app once all the remote modules are registered, otherwise the remote modules routes won't be added to the router. - const areModulesRegistered = useAreModulesRegistered(); - - // Re-render the app once all the remote modules are ready, otherwise the deferred remote modules routes won't be added to the router. - const areModulesReady = useAreModulesReady(); + const [state, dispatch] = useAppRouterReducer(waitForMsw, waitForPublicData, waitForProtectedData); + const logger = useLogger(); const routes = useRoutes(); - const errorRenderer = useCallback(({ error }: { error: unknown }) => { - return cloneElement(errorElement, { - error - }); - }, [errorElement]); + useStrictRegistrationMode(); - return useMemo(() => { - // HACK: - // When there's a direct hit on a deferred route, since the route has not been registered yet (because it's a deferred registration), - // the React Router router instance doesn't know about that route and will therefore fallback to the no match route. - // If there's isn't a custom no match route defined with path="*", React Router will fallback it's default no match router instead - // of rendering a route which will break the AppRouter component. - // To circumvent this issue, if the application doesn't register a custom no match route, an Error is thrown. - if (areModulesRegistered && !findRouteByPath(routes, "*")) { - throw new Error("[squide] For the AppRouter component to work properly, the application must define a custom no match route. For additional information, refer to: https://reactrouter.com/en/main/start/tutorial#handling-not-found-errors."); - } + useEffect(() => { + logger.debug("[squide] AppRouter state updated:", state); + }, [state, logger]); + + const routerProvider = useMemo(() => { + return renderRouterProvider({ + rootRoute: , + registeredRoutes: routes, + routerProviderProps: {} + }); + }, [routes, renderRouterProvider]); - return renderRouterProvider([ - { - element: ( - - - - ), - children: routes - } - ], {}); - }, [areModulesRegistered, areModulesReady, routes, onLoadPublicData, onLoadProtectedData, isPublicDataLoaded, isProtectedDataLoaded, onCompleteRegistrations, waitForMsw, errorRenderer, fallbackElement, renderRouterProvider]); + return ( + + + {routerProvider} + + + ); } diff --git a/packages/firefly/src/AppRouterContext.ts b/packages/firefly/src/AppRouterContext.ts new file mode 100644 index 000000000..d01850e61 --- /dev/null +++ b/packages/firefly/src/AppRouterContext.ts @@ -0,0 +1,27 @@ +import { isNil } from "@squide/core"; +import { createContext, useContext } from "react"; +import type { AppRouterDispatch, AppRouterState } from "./AppRouterReducer.ts"; + +export const AppRouterStateContext = createContext(undefined); + +export function useAppRouterState() { + const state = useContext(AppRouterStateContext); + + if (isNil(state)) { + throw new Error("[squide] The useAppRouterState hook must be called by a children of the AppRouter component."); + } + + return state; +} + +export const AppRouterDispatcherContext = createContext(undefined); + +export function useAppRouterDispatcher() { + const dispatch = useContext(AppRouterDispatcherContext); + + if (isNil(dispatch)) { + throw new Error("[squide] The useAppRouterDispatcher hook must be called by a children of the AppRouter component."); + } + + return dispatch; +} diff --git a/packages/firefly/src/AppRouterReducer.ts b/packages/firefly/src/AppRouterReducer.ts new file mode 100644 index 000000000..284c65ce3 --- /dev/null +++ b/packages/firefly/src/AppRouterReducer.ts @@ -0,0 +1,254 @@ +import { addLocalModuleRegistrationStatusChangedListener, getLocalModuleRegistrationStatus, removeLocalModuleRegistrationStatusChangedListener, useLogger } from "@squide/core"; +import { addRemoteModuleRegistrationStatusChangedListener, areModulesReady, areModulesRegistered, getRemoteModuleRegistrationStatus, removeRemoteModuleRegistrationStatusChangedListener } from "@squide/module-federation"; +import { addMswStateChangedListener, isMswReady, removeMswStateChangedListener } from "@squide/msw"; +import { useCallback, useEffect, useMemo, useReducer, type Dispatch } from "react"; + +export interface AppRouterState { + waitForMsw: boolean; + waitForPublicData: boolean; + waitForProtectedData: boolean; + areModulesRegistered: boolean; + areModulesReady: boolean; + isMswReady: boolean; + isPublicDataReady: boolean; + isProtectedDataReady: boolean; + publicDataUpdatedAt?: number; + protectedDataUpdatedAt?: number; + deferredRegistrationsUpdatedAt?: number; + isActiveRouteProtected: boolean; + isUnauthorized: boolean; +} + +export type AppRouterActionType = +| "modules-registered" +| "modules-ready" +| "msw-ready" +| "public-data-ready" +| "protected-data-ready" +| "public-data-updated" +| "protected-data-updated" +| "deferred-registrations-updated" +| "active-route-is-protected" +| "is-unauthorized"; + +export interface AppRouterAction { + type: AppRouterActionType; +} + +export type AppRouterDispatch = Dispatch; + +function useVerboseDispatch(dispatch: AppRouterDispatch) { + const logger = useLogger(); + + return useCallback((action: AppRouterAction) => { + logger.debug("[squide] The following action has been dispatched to the AppRouter reducer:", action); + + dispatch(action); + }, [dispatch, logger]); +} + +function reducer(state: AppRouterState, action: AppRouterAction) { + let newState = state; + + switch (action.type) { + case "modules-registered": { + newState = { + ...newState, + areModulesRegistered: true + }; + + break; + } + case "modules-ready": { + newState = { + ...newState, + areModulesReady: true, + // Will be set even if the app is not using deferred registrations. + deferredRegistrationsUpdatedAt: Date.now() + }; + + break; + } + case "msw-ready": { + newState = { + ...newState, + isMswReady: true + }; + + break; + } + case "public-data-ready": { + newState = { + ...newState, + isPublicDataReady: true, + publicDataUpdatedAt: Date.now() + }; + + break; + } + case "protected-data-ready": { + newState = { + ...newState, + isProtectedDataReady: true, + protectedDataUpdatedAt: Date.now() + }; + + break; + } + case "public-data-updated": { + newState = { + ...newState, + publicDataUpdatedAt: Date.now() + }; + + break; + } + case "protected-data-updated": { + newState = { + ...newState, + protectedDataUpdatedAt: Date.now() + }; + + break; + } + case "deferred-registrations-updated": { + newState = { + ...newState, + deferredRegistrationsUpdatedAt: Date.now() + }; + + break; + } + case "active-route-is-protected": { + newState = { + ...newState, + isActiveRouteProtected: true + }; + + break; + } + case "is-unauthorized": { + newState = { + ...newState, + isUnauthorized: true + }; + + break; + } + default: { + throw new Error(`[squide] The AppRouter component state reducer doesn't support action type "${action.type}".`); + } + } + + return newState; +} + +export function getAreModulesRegistered() { + const localModuleStatus = getLocalModuleRegistrationStatus(); + const remoteModuleStatus = getRemoteModuleRegistrationStatus(); + + return areModulesRegistered(localModuleStatus, remoteModuleStatus); +} + +export function getAreModulesReady() { + const localModuleStatus = getLocalModuleRegistrationStatus(); + const remoteModuleStatus = getRemoteModuleRegistrationStatus(); + + return areModulesReady(localModuleStatus, remoteModuleStatus); +} + +export function useModuleRegistrationStatusDispatcher(areModulesRegisteredValue: boolean, areModulesReadyValue: boolean, dispatch: AppRouterDispatch) { + const logger = useLogger(); + + return useEffect(() => { + const handleModulesRegistrationStatusChange = () => { + if (!areModulesRegisteredValue && getAreModulesRegistered()) { + dispatch({ type: "modules-registered" }); + } + + if (!areModulesReadyValue && getAreModulesReady()) { + dispatch({ type: "modules-ready" }); + + logger.debug("[squide] %cModules are ready%c.", "color: white; background-color: green;", ""); + } + }; + + addLocalModuleRegistrationStatusChangedListener(handleModulesRegistrationStatusChange); + addRemoteModuleRegistrationStatusChangedListener(handleModulesRegistrationStatusChange); + + return () => { + removeLocalModuleRegistrationStatusChangedListener(handleModulesRegistrationStatusChange); + removeRemoteModuleRegistrationStatusChangedListener(handleModulesRegistrationStatusChange); + }; + }, [areModulesRegisteredValue, areModulesReadyValue, dispatch, logger]); +} + +export function useMswStatusDispatcher(isMswReadyValue: boolean, dispatch: AppRouterDispatch) { + const logger = useLogger(); + + useEffect(() => { + const handleMswStateChange = () => { + if (!isMswReadyValue && isMswReady()) { + dispatch({ type: "msw-ready" }); + + logger.debug("[squide] %cMSW is ready%c.", "color: white; background-color: green;", ""); + } + }; + + addMswStateChangedListener(handleMswStateChange); + + return () => { + removeMswStateChangedListener(handleMswStateChange); + }; + }, [isMswReadyValue, dispatch, logger]); +} + +let dispatchProxyFactory: ((reactDispatch: AppRouterDispatch) => AppRouterDispatch) | undefined; + +// This function should only be used by tests. +export function __setAppReducerDispatchProxyFactory(factory: (reactDispatch: AppRouterDispatch) => AppRouterDispatch) { + dispatchProxyFactory = factory; +} + +// This function should only be used by tests. +export function __clearAppReducerDispatchProxy() { + dispatchProxyFactory = undefined; +} + +function useDispatchProxy(reactDispatch: AppRouterDispatch) { + return useMemo(() => { + return dispatchProxyFactory ? dispatchProxyFactory(reactDispatch) : reactDispatch; + }, [reactDispatch]); +} + +export function useAppRouterReducer(waitForMsw: boolean, waitForPublicData: boolean, waitForProtectedData: boolean): [AppRouterState, AppRouterDispatch] { + const [state, reactDispatch] = useReducer(reducer, { + waitForMsw, + waitForPublicData, + waitForProtectedData, + // When the modules registration functions are awaited, the event listeners are registered after the modules are registered. + areModulesRegistered: getAreModulesRegistered(), + areModulesReady: getAreModulesReady(), + isMswReady: isMswReady(), + isPublicDataReady: false, + isProtectedDataReady: false, + isActiveRouteProtected: false, + isUnauthorized: false + }); + + const { + areModulesRegistered: areModulesRegisteredValue, + areModulesReady: areModulesReadyValue, + isMswReady: isMswReadyValue + } = state; + + // The dispatch proxy is strictly an utility allowing tests to mock the useReducer dispatch function. It's easier + // than mocking the import from React. + const dispatchProxy = useDispatchProxy(reactDispatch); + const dispatch = useVerboseDispatch(dispatchProxy); + + useModuleRegistrationStatusDispatcher(areModulesRegisteredValue, areModulesReadyValue, dispatch); + useMswStatusDispatcher(isMswReadyValue, dispatch); + + return [state, dispatch]; +} diff --git a/packages/firefly/src/FireflyRuntime.tsx b/packages/firefly/src/FireflyRuntime.tsx new file mode 100644 index 000000000..9292dddbe --- /dev/null +++ b/packages/firefly/src/FireflyRuntime.tsx @@ -0,0 +1,71 @@ +import type { RegisterRouteOptions, RuntimeOptions } from "@squide/core"; +import { MswPlugin } from "@squide/msw"; +import { ReactRouterRuntime, type Route } from "@squide/react-router"; +import type { RequestHandler } from "msw"; +import { getAreModulesRegistered } from "./AppRouterReducer.ts"; + +export interface FireflyRuntimeOptions extends RuntimeOptions { + useMsw?: boolean; +} + +export class FireflyRuntime extends ReactRouterRuntime { + readonly #useMsw: boolean; + + constructor({ plugins, useMsw, ...options }: FireflyRuntimeOptions = {}) { + if (useMsw) { + super({ + plugins: [ + ...(plugins ?? []), + runtime => new MswPlugin(runtime) + ], + ...options + }); + + this.#useMsw = true; + } else { + super({ + plugins, + ...options + }); + + this.#useMsw = false; + } + } + + registerRequestHandlers(handlers: RequestHandler[]) { + const mswPlugin = this.getPlugin(MswPlugin.name) as MswPlugin; + + if (!mswPlugin) { + throw new Error("[squide] Cannot register the provided MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?"); + } + + if (getAreModulesRegistered()) { + throw new Error("[squide] Cannot register an MSW request handlers once the modules are registered. Are you trying to register an MSW request handler in a deferred registration function? Only navigation items can be registered in a deferred registration function."); + } + + mswPlugin.registerRequestHandlers(handlers); + } + + // Must define a return type otherwise we get an "error TS2742: The inferred type of 'requestHandlers' cannot be named" error. + get requestHandlers(): RequestHandler[] { + const mswPlugin = this.getPlugin(MswPlugin.name) as MswPlugin; + + if (!mswPlugin) { + throw new Error("[squide] Cannot retrieve MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?"); + } + + return mswPlugin.requestHandlers; + } + + registerRoute(route: Route, options: RegisterRouteOptions = {}) { + if (getAreModulesRegistered()) { + throw new Error("[squide] Cannot register a route once the modules are registered. Are you trying to register a route in a deferred registration function? Only navigation items can be registered in a deferred registration function."); + } + + super.registerRoute(route, options); + } + + get isMswEnabled() { + return this.#useMsw; + } +} diff --git a/packages/firefly/src/GlobalDataQueriesError.ts b/packages/firefly/src/GlobalDataQueriesError.ts new file mode 100644 index 000000000..018163bda --- /dev/null +++ b/packages/firefly/src/GlobalDataQueriesError.ts @@ -0,0 +1,17 @@ +export class GlobalDataQueriesError extends Error { + readonly #errors: Error[]; + + constructor(message: string, errors: Error[]) { + super(message); + + this.#errors = errors; + } + + get errors() { + return this.#errors; + } +} + +export function isGlobalDataQueriesError(error?: unknown): error is GlobalDataQueriesError { + return error !== undefined && error !== null && error instanceof GlobalDataQueriesError; +} diff --git a/packages/firefly/src/RootRoute.tsx b/packages/firefly/src/RootRoute.tsx new file mode 100644 index 000000000..d9df550ee --- /dev/null +++ b/packages/firefly/src/RootRoute.tsx @@ -0,0 +1,23 @@ +import { useEffect } from "react"; +import { Outlet } from "react-router-dom"; +import { useAppRouterDispatcher, useAppRouterState } from "./AppRouterContext.ts"; +import { useIsActiveRouteProtected } from "./useIsActiveRouteProtected.ts"; + +export function RootRoute() { + const state = useAppRouterState(); + const isActiveRouteProtected = useIsActiveRouteProtected(state.areModulesReady); + + const dispatch = useAppRouterDispatcher(); + + useEffect(() => { + if (isActiveRouteProtected) { + // Dispatching the active route visibility must be done in a route because React Router's useLocation + // hook throws if it's not called from a child of the router component. + dispatch({ type: "active-route-is-protected" }); + } + }, [isActiveRouteProtected, dispatch]); + + return ( + + ); +} diff --git a/packages/firefly/src/fireflyRuntime.tsx b/packages/firefly/src/fireflyRuntime.tsx deleted file mode 100644 index 6274ebaaf..000000000 --- a/packages/firefly/src/fireflyRuntime.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import type { RuntimeOptions } from "@squide/core"; -import { MswPlugin } from "@squide/msw"; -import { ReactRouterRuntime } from "@squide/react-router"; -import type { RequestHandler } from "msw"; - -export interface FireflyRuntimeOptions extends RuntimeOptions { - useMsw?: boolean; -} - -export class FireflyRuntime extends ReactRouterRuntime { - readonly #mswPlugin?: MswPlugin; - readonly #useMsw: boolean; - - constructor({ plugins, useMsw, ...options }: FireflyRuntimeOptions = {}) { - if (useMsw) { - const mswPlugin = new MswPlugin(); - - super({ - plugins: [ - ...(plugins ?? []), - mswPlugin - ], - ...options - }); - - this.#mswPlugin = mswPlugin; - this.#useMsw = true; - } else { - super({ - plugins, - ...options - }); - - this.#useMsw = false; - } - } - - registerRequestHandlers(handlers: RequestHandler[]) { - if (!this.#mswPlugin) { - throw new Error("[squide] Cannot register the provided MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?"); - } - - this.#mswPlugin.registerRequestHandlers(handlers); - } - - get requestHandlers(): RequestHandler[] { - if (!this.#mswPlugin) { - throw new Error("[squide] Cannot retrieve MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?"); - } - - return this.#mswPlugin.requestHandlers; - } - - get isMswEnabled() { - return this.#useMsw; - } -} diff --git a/packages/firefly/src/index.ts b/packages/firefly/src/index.ts index f272bfb0a..41383aa9a 100644 --- a/packages/firefly/src/index.ts +++ b/packages/firefly/src/index.ts @@ -3,6 +3,23 @@ export * from "@squide/module-federation"; export * from "@squide/msw"; export * from "@squide/react-router"; +export * from "./FireflyRuntime.tsx"; + export * from "./AppRouter.tsx"; -export * from "./fireflyRuntime.tsx"; +export * from "./AppRouterContext.ts"; +export * from "./AppRouterReducer.ts"; +export * from "./GlobalDataQueriesError.ts"; +export * from "./useCanFetchProtectedData.ts"; +export * from "./useCanFetchPublicData.ts"; +export * from "./useCanRegisterDeferredRegistrations.ts"; +export * from "./useCanUpdateDeferredRegistrations.ts"; +export * from "./useDeferredRegistrations.ts"; +export * from "./useIsActiveRouteProtected.ts"; +export * from "./useIsBootstrapping.ts"; +export * from "./useNavigationItems.ts"; +export * from "./useProtectedDataQueries.ts"; +export * from "./usePublicDataQueries.ts"; +export * from "./useRegisterDeferredRegistrations.ts"; +export * from "./useStrictRegistrationMode.ts"; +export * from "./useUpdateDeferredRegistrations.ts"; diff --git a/packages/firefly/src/useCanFetchProtectedData.ts b/packages/firefly/src/useCanFetchProtectedData.ts new file mode 100644 index 000000000..eed9e6e81 --- /dev/null +++ b/packages/firefly/src/useCanFetchProtectedData.ts @@ -0,0 +1,26 @@ +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useCanFetchProtectedData() { + const { + waitForMsw, + areModulesRegistered, + areModulesReady, + isMswReady, + isProtectedDataReady, + isActiveRouteProtected + } = useAppRouterState(); + + return ( + // Always return true when the protected data has already been fetched sucessfully so TanStack Query can update the data in the background. + isProtectedDataReady + || ( + // Wait until the modules has been registered, but do not wait for the deferred registrations to be registered as they will probably + // depends on the protected data. + (areModulesRegistered || areModulesReady) + // Only fetch the protected data for protected routes, aka do not fetch the protected data for public routes. + && isActiveRouteProtected + // Wait for MSW since the endpoints for the protected data might be an MSW endpoint when in development. + && (!waitForMsw || isMswReady) + ) + ); +} diff --git a/packages/firefly/src/useCanFetchPublicData.ts b/packages/firefly/src/useCanFetchPublicData.ts new file mode 100644 index 000000000..86339b921 --- /dev/null +++ b/packages/firefly/src/useCanFetchPublicData.ts @@ -0,0 +1,23 @@ +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useCanFetchPublicData() { + const { + waitForMsw, + areModulesRegistered, + areModulesReady, + isMswReady, + isPublicDataReady + } = useAppRouterState(); + + return ( + // Always return true when the public data has already been fetched sucessfully so TanStack Query can update the data in the background. + isPublicDataReady + || ( + // Wait until the modules has been registered, but do not wait for the deferred registrations to be registered has they will probably + // depends on the protected data. + (areModulesRegistered || areModulesReady) + // Wait for MSW since the endpoints for the protected data might be an MSW endpoint when in development. + && (!waitForMsw || isMswReady) + ) + ); +} diff --git a/packages/firefly/src/useCanRegisterDeferredRegistrations.ts b/packages/firefly/src/useCanRegisterDeferredRegistrations.ts new file mode 100644 index 000000000..abd3fd2d4 --- /dev/null +++ b/packages/firefly/src/useCanRegisterDeferredRegistrations.ts @@ -0,0 +1,24 @@ +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useCanRegisterDeferredRegistrations() { + const { + waitForPublicData, + waitForProtectedData, + areModulesReady, + areModulesRegistered, + isPublicDataReady, + isProtectedDataReady, + isActiveRouteProtected, + isUnauthorized + } = useAppRouterState(); + + return ( + !isUnauthorized + // Wait for the modules to be registered but make sure the deferred registrations has not been registered yet (updates are handled by another hook). + && areModulesRegistered && !areModulesReady + // && (!waitForMsw || isMswReady) + // Wait for the initial data to be ready since the deferred registrations will probably need that data. + && (!waitForPublicData || isPublicDataReady) + && (!waitForProtectedData || !isActiveRouteProtected || isProtectedDataReady) + ); +} diff --git a/packages/firefly/src/useCanUpdateDeferredRegistrations.ts b/packages/firefly/src/useCanUpdateDeferredRegistrations.ts new file mode 100644 index 000000000..4d035a70a --- /dev/null +++ b/packages/firefly/src/useCanUpdateDeferredRegistrations.ts @@ -0,0 +1,23 @@ +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useCanUpdateDeferredRegistrations() { + const { + areModulesReady, + publicDataUpdatedAt, + protectedDataUpdatedAt, + deferredRegistrationsUpdatedAt + } = useAppRouterState(); + + return ( + // Do not trigger an update if the deferred registrations has not been registered yet (if there are deferred registrations, once they are + // registered, the modules will be marked as ready). + areModulesReady + // Make sure the apps is actually having deferred registrations. + && deferredRegistrationsUpdatedAt + // If either the public data or the protected data has been updated, update the deferred registrations. + && ( + (publicDataUpdatedAt && publicDataUpdatedAt > deferredRegistrationsUpdatedAt) || + (protectedDataUpdatedAt && protectedDataUpdatedAt > deferredRegistrationsUpdatedAt) + ) + ); +} diff --git a/packages/firefly/src/useDeferredRegistrations.ts b/packages/firefly/src/useDeferredRegistrations.ts new file mode 100644 index 000000000..352e09122 --- /dev/null +++ b/packages/firefly/src/useDeferredRegistrations.ts @@ -0,0 +1,59 @@ +import { useRuntime, type ModuleRegistrationError } from "@squide/core"; +import { useEffect } from "react"; +import { useCanRegisterDeferredRegistrations } from "./useCanRegisterDeferredRegistrations.ts"; +import { useCanUpdateDeferredRegistrations } from "./useCanUpdateDeferredRegistrations.ts"; +import { useRegisterDeferredRegistrations } from "./useRegisterDeferredRegistrations.ts"; +import { useUpdateDeferredRegistrations } from "./useUpdateDeferredRegistrations.ts"; + +export interface DeferredRegistrationsErrorsObject { + localModuleErrors: ModuleRegistrationError[]; + remoteModuleErrors: ModuleRegistrationError[]; +} + +export type DeferredRegistrationsErrorCallback = (errorsObject: DeferredRegistrationsErrorsObject) => void; + +export interface UseDeferredRegistrationsOptions { + onError?: DeferredRegistrationsErrorCallback; +} + +function hasError({ localModuleErrors, remoteModuleErrors }: DeferredRegistrationsErrorsObject) { + return localModuleErrors.length > 0 || remoteModuleErrors.length > 0; +} + +export function useDeferredRegistrations(data: unknown, { onError }: UseDeferredRegistrationsOptions = {}) { + const runtime = useRuntime(); + + const canRegisterDeferredRegistrations = useCanRegisterDeferredRegistrations(); + const canUpdateDeferredRegistrations = useCanUpdateDeferredRegistrations(); + + const registerDeferredRegistrations = useRegisterDeferredRegistrations(); + const updateDeferredRegistrations = useUpdateDeferredRegistrations(); + + useEffect(() => { + if (canRegisterDeferredRegistrations) { + const register = async () => { + const errors = await registerDeferredRegistrations(data, runtime); + + if (hasError(errors) && onError) { + onError(errors); + } + }; + + register(); + } + }, [canRegisterDeferredRegistrations, registerDeferredRegistrations, data, onError, runtime]); + + useEffect(() => { + if (canUpdateDeferredRegistrations) { + const update = async () => { + const errors = await updateDeferredRegistrations(data, runtime); + + if (hasError(errors) && onError) { + onError(errors); + } + }; + + update(); + } + }, [canUpdateDeferredRegistrations, updateDeferredRegistrations, data, onError, runtime]); +} diff --git a/packages/firefly/src/useIsActiveRouteProtected.ts b/packages/firefly/src/useIsActiveRouteProtected.ts new file mode 100644 index 000000000..67ebead0d --- /dev/null +++ b/packages/firefly/src/useIsActiveRouteProtected.ts @@ -0,0 +1,12 @@ +import { useIsRouteProtected, useRouteMatch } from "@squide/react-router"; +import { useLocation } from "react-router-dom"; + +export function useIsActiveRouteProtected(areModulesReady: boolean) { + // Using this hook instead of window.location to retrieve the current location because it triggers a re-render everytime the browser location change. + const location = useLocation(); + + // Only throw when there's no match if the modules are ready, otherwise it's expected that no route will be found since they are not all registered yet. + const activeRoute = useRouteMatch(location, { throwWhenThereIsNoMatch: areModulesReady }); + + return useIsRouteProtected(activeRoute); +} diff --git a/packages/firefly/src/useIsBootstrapping.ts b/packages/firefly/src/useIsBootstrapping.ts new file mode 100644 index 000000000..dc3aef507 --- /dev/null +++ b/packages/firefly/src/useIsBootstrapping.ts @@ -0,0 +1,38 @@ +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useIsBootstrapping() { + const { + waitForMsw, + waitForPublicData, + waitForProtectedData, + areModulesReady, + isMswReady, + isPublicDataReady, + isProtectedDataReady, + isActiveRouteProtected, + isUnauthorized + } = useAppRouterState(); + + const isAppReady = ( + !isUnauthorized + // Wait until the modules has been registered and the deferred registrations has been registered if any. + && areModulesReady + // Not required but can sometimes prevent a re-render when the state value is somehow updated after the initial data is ready. + && (!waitForMsw || isMswReady) + // Wait for the initial data to be ready. + && (!waitForPublicData || isPublicDataReady) + && (!waitForProtectedData || !isActiveRouteProtected || isProtectedDataReady) + ); + + // When an API request returns a 401, the bootstrapping should be bypassed to render the login page. + const flush = ( + // Only applicable when there's a unauthorized request while fetching the initial data. + isUnauthorized + // Not required but can sometimes prevent a re-render when the state value is somehow updated after the public data is ready. + && (!waitForMsw || isMswReady) + // If the application is loading public data, we want to wait for this data to be ready to prevent a re-render. + && (!waitForPublicData || isPublicDataReady) + ); + + return !isAppReady && !flush; +} diff --git a/packages/firefly/src/useNavigationItems.ts b/packages/firefly/src/useNavigationItems.ts new file mode 100644 index 000000000..55f7c5a91 --- /dev/null +++ b/packages/firefly/src/useNavigationItems.ts @@ -0,0 +1,16 @@ +import { useRuntimeNavigationItems } from "@squide/react-router"; +import { useAppRouterState } from "./AppRouterContext.ts"; + +export function useNavigationItems() { + // This is not the most sophisticated strategy but it seems to be good enough for now. + // The idea is that when deferred registrations are used by the consumer applications, the deferred registrations could + // be updated when the global data is updated. If the deferred registrations are updated, it means that the registered + // navigation items might have been updated and a re-render must happens to display the new navigation items. + // Since the "deferredRegistrationsUpdatedAt" state value of the AppRouterReducer is updated everytime the deferred registrations + // are updated, subscribing to the state with useAppRouterState ensure that the navigation items will be re-rendered. + // A more sophisticated strategy could be implemented later on if needed, something involving a subscription to the "runtime" changes, or + // even introducing new module states. + useAppRouterState(); + + return useRuntimeNavigationItems(); +} diff --git a/packages/firefly/src/useProtectedDataQueries.ts b/packages/firefly/src/useProtectedDataQueries.ts new file mode 100644 index 000000000..59add693d --- /dev/null +++ b/packages/firefly/src/useProtectedDataQueries.ts @@ -0,0 +1,75 @@ +import { useQueries, type QueriesOptions, type QueriesResults, type UseQueryResult } from "@tanstack/react-query"; +import { useCallback, useEffect, useRef } from "react"; +import { useAppRouterDispatcher, useAppRouterState } from "./AppRouterContext.ts"; +import { GlobalDataQueriesError } from "./GlobalDataQueriesError.ts"; +import { useCanFetchProtectedData } from "./useCanFetchProtectedData.ts"; + +export type IsUnauthorizedErrorCallback = (error: unknown) => boolean; + +// This converts an array of UseQueryResult to an array of the data type of each query result. +// For more information, view: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html#mapped-types-on-tuples-and-arrays. +type MapUseQueryResultToData = { [K in keyof T]: T[K] extends UseQueryResult ? U : never }; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function useProtectedDataQueries>(queries: QueriesOptions, isUnauthorizedError: IsUnauthorizedErrorCallback): MapUseQueryResultToData> { + const canFetchProtectedData = useCanFetchProtectedData(); + + const dispatch = useAppRouterDispatcher(); + + const combineResults = useCallback((results: UseQueryResult[]) => { + const errors = results.filter(x => x.error).map(x => x.error) as Error[]; + + return { + data: results.map(x => x.data) as MapUseQueryResultToData>, + errors, + hasErrors: errors.length > 0, + isReady: results.length === queries.length && results.every(x => x.data) + }; + }, [queries.length]); + + const { data, errors: queriesErrors, hasErrors, isReady } = useQueries({ + queries: queries.map(x => ({ + enabled: canFetchProtectedData, + ...x + })), + combine: combineResults + }); + + const { + isProtectedDataReady, + isUnauthorized + } = useAppRouterState(); + + useEffect(() => { + if (hasErrors) { + if (!isProtectedDataReady && !isUnauthorized && queriesErrors.some(x => isUnauthorizedError(x))) { + // Will transition the state to allow the routes to render even if the bootstrapping is not complete, because otherwise + // a login page for example could not be rendered. + dispatch({ type: "is-unauthorized" }); + } + + // Otherwise, when a user is logged off, a refetch might throws a 401. + if (!queriesErrors.every(x => isUnauthorizedError(x))) { + throw new GlobalDataQueriesError("[squide] Global protected data queries failed.", queriesErrors); + } + } + }, [hasErrors, queriesErrors, isProtectedDataReady, isUnauthorized, isUnauthorizedError, dispatch]); + + const isReadyRef = useRef(false); + + useEffect(() => { + if (isReadyRef.current && data) { + dispatch({ type: "protected-data-updated" }); + } + }, [data, dispatch]); + + useEffect(() => { + if (isReady) { + isReadyRef.current = true; + + dispatch({ type: "protected-data-ready" }); + } + }, [isReady, dispatch]); + + return data; +} diff --git a/packages/firefly/src/usePublicDataQueries.ts b/packages/firefly/src/usePublicDataQueries.ts new file mode 100644 index 000000000..3c61093b4 --- /dev/null +++ b/packages/firefly/src/usePublicDataQueries.ts @@ -0,0 +1,59 @@ +import { useQueries, type QueriesOptions, type QueriesResults, type UseQueryResult } from "@tanstack/react-query"; +import { useCallback, useEffect, useRef } from "react"; +import { useAppRouterDispatcher } from "./AppRouterContext.ts"; +import { GlobalDataQueriesError } from "./GlobalDataQueriesError.ts"; +import { useCanFetchPublicData } from "./useCanFetchPublicData.ts"; + +// This converts an array of UseQueryResult to an array of the data type of each query result. +// For more information, view: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html#mapped-types-on-tuples-and-arrays. +type MapUseQueryResultToData = { [K in keyof T]: T[K] extends UseQueryResult ? U : never }; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function usePublicDataQueries>(queries: QueriesOptions): MapUseQueryResultToData> { + const canFetchPublicData = useCanFetchPublicData(); + + const dispatch = useAppRouterDispatcher(); + + const combineResults = useCallback((results: UseQueryResult[]) => { + const errors = results.filter(x => x.error).map(x => x.error) as Error[]; + + return { + data: results.map(x => x.data) as MapUseQueryResultToData>, + errors, + hasErrors: errors.length > 0, + isReady: results.length === queries.length && results.every(x => x.data) + }; + }, [queries.length]); + + const { data, errors: queriesErrors, hasErrors, isReady } = useQueries({ + queries: queries.map(x => ({ + enabled: canFetchPublicData, + ...x + })), + combine: combineResults + }); + + useEffect(() => { + if (hasErrors) { + throw new GlobalDataQueriesError("[squide] Global public data queries failed.", queriesErrors); + } + }, [hasErrors, queriesErrors]); + + const isReadyRef = useRef(false); + + useEffect(() => { + if (isReadyRef.current && data) { + dispatch({ type: "public-data-updated" }); + } + }, [data, dispatch]); + + useEffect(() => { + if (isReady) { + isReadyRef.current = true; + + dispatch({ type: "public-data-ready" }); + } + }, [isReady, dispatch]); + + return data; +} diff --git a/packages/firefly/src/useRegisterDeferredRegistrations.ts b/packages/firefly/src/useRegisterDeferredRegistrations.ts new file mode 100644 index 000000000..f4c44ef70 --- /dev/null +++ b/packages/firefly/src/useRegisterDeferredRegistrations.ts @@ -0,0 +1,9 @@ +import type { Runtime } from "@squide/core"; +import { registerDeferredRegistrations } from "@squide/module-federation"; +import { useCallback } from "react"; + +export function useRegisterDeferredRegistrations() { + return useCallback((data: TData, runtime: TRuntime) => { + return registerDeferredRegistrations(data, runtime); + }, []); +} diff --git a/packages/firefly/src/useStrictRegistrationMode.ts b/packages/firefly/src/useStrictRegistrationMode.ts new file mode 100644 index 000000000..c62e80bd4 --- /dev/null +++ b/packages/firefly/src/useStrictRegistrationMode.ts @@ -0,0 +1,28 @@ +import { addLocalModuleRegistrationStatusChangedListener, getLocalModuleRegistrationStatus, removeLocalModuleRegistrationStatusChangedListener, useRuntime } from "@squide/core"; +import { addRemoteModuleRegistrationStatusChangedListener, areModulesReady, getRemoteModuleRegistrationStatus, removeRemoteModuleRegistrationStatusChangedListener } from "@squide/module-federation"; +import { useEffect, useSyncExternalStore } from "react"; + +function subscribeToLocalModuleRegistrationStatusChanged(callback: () => void) { + addLocalModuleRegistrationStatusChangedListener(callback); + + return () => removeLocalModuleRegistrationStatusChangedListener(callback); +} + +function subscribeToRemoteModuleRegistrationStatusChanged(callback: () => void) { + addRemoteModuleRegistrationStatusChangedListener(callback); + + return () => removeRemoteModuleRegistrationStatusChangedListener(callback); +} + +export function useStrictRegistrationMode() { + const runtime = useRuntime(); + + const localModuleStatus = useSyncExternalStore(subscribeToLocalModuleRegistrationStatusChanged, getLocalModuleRegistrationStatus); + const remoteModuleStatus = useSyncExternalStore(subscribeToRemoteModuleRegistrationStatusChanged, getRemoteModuleRegistrationStatus); + + useEffect(() => { + if (areModulesReady(localModuleStatus, remoteModuleStatus)) { + runtime._validateRegistrations(); + } + }, [runtime, localModuleStatus, remoteModuleStatus]); +} diff --git a/packages/firefly/src/useUpdateDeferredRegistrations.ts b/packages/firefly/src/useUpdateDeferredRegistrations.ts new file mode 100644 index 000000000..606694506 --- /dev/null +++ b/packages/firefly/src/useUpdateDeferredRegistrations.ts @@ -0,0 +1,16 @@ +import type { Runtime } from "@squide/core"; +import { updateDeferredRegistrations } from "@squide/module-federation"; +import { useCallback } from "react"; +import { useAppRouterDispatcher } from "./AppRouterContext.ts"; + +export function useUpdateDeferredRegistrations() { + const dispatch = useAppRouterDispatcher(); + + return useCallback(async (data: TData, runtime: TRuntime) => { + const errors = await updateDeferredRegistrations(data, runtime); + + dispatch({ type: "deferred-registrations-updated" }); + + return errors; + }, [dispatch]); +} diff --git a/packages/firefly/tests/AppRouter.test.tsx b/packages/firefly/tests/AppRouter.test.tsx deleted file mode 100644 index babe457af..000000000 --- a/packages/firefly/tests/AppRouter.test.tsx +++ /dev/null @@ -1,614 +0,0 @@ -// Not all permutations are tested because there are simply too many. The code path that we deem the most important to test -// has been handled and additional tests will be added once bugs are discovered. - -import { RuntimeContext, __resetLocalModuleRegistrations, registerLocalModules } from "@squide/core"; -import { completeModuleRegistrations } from "@squide/module-federation"; -import { __resetMswStatus, setMswAsStarted } from "@squide/msw"; -import { render, screen } from "@testing-library/react"; -import type { ReactElement, ReactNode } from "react"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import { AppRouter, type AppRouterProps } from "../src/AppRouter.tsx"; -import { FireflyRuntime } from "../src/fireflyRuntime.tsx"; - -function Loading() { - return ( -
            Loading...
            - ); -} - -function ErrorBoundary() { - return ( -
            An error occured!
            - ); -} - -function createAppRouter(props: Omit) { - return ( - } - errorElement={} - {...props} - > - {(routes, providerProps) => ( - - )} - - ); -} - -function renderWithRuntime(runtime: FireflyRuntime, ui: ReactElement) { - return render(ui, { - wrapper: ({ children }: { children?: ReactNode }) => { - return ( - - {children} - - ); - } - }); -} - -beforeEach(() => { - __resetLocalModuleRegistrations(); - __resetMswStatus(); -}); - -test("when no data handlers are provided, msw is disabled, there's no deferred registrations, and modules are not registered yet, render the fallback", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - // Never resolving Promise object. - registerLocalModules([() => new Promise(() => {})], runtime); - - renderWithRuntime(runtime, createAppRouter({ - waitForMsw: false - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when no data handlers are provided, msw is disabled, there's no deferred registrations, and modules are registered, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => { - runtime.registerRoute({ - index: true, - element:
            A route
            - }, { - hoist: true - }); - }], runtime); - - renderWithRuntime(runtime, createAppRouter({ - waitForMsw: false - })); - - expect(await screen.findByTestId("module-route")).toBeInTheDocument(); -}); - -test("when no data handlers are provided, msw is disabled, modules are registered but there's uncompleted deferred registrations, render the fallback", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => () => Promise.resolve()], runtime); - - renderWithRuntime(runtime, createAppRouter({ - waitForMsw: false - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when a onLoadPublicData handler is provided and the public data is not loaded, render the fallback element", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - // Never resolving Promise object. - onLoadPublicData: () => new Promise(() => {}), - isPublicDataLoaded: false, - waitForMsw: false - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when a onLoadPublicData handler is provided and the public data is loaded, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - runtime.registerRoute({ - $visibility: "public", - index: true, - element:
            A route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - const handleLoadPublicData = () => Promise.resolve(); - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onLoadPublicData: handleLoadPublicData, - isPublicDataLoaded: false, - waitForMsw: false - })); - - rerender(createAppRouter({ - onLoadPublicData: handleLoadPublicData, - isPublicDataLoaded: true, - waitForMsw: false - })); - - expect(await screen.findByTestId("route")).toBeInTheDocument(); -}); - -test("when a onLoadProtectedData handler is provided and the protected data is not loaded, render the fallback element", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - // Never resolving Promise object. - onLoadProtectedData: () => new Promise(() => {}), - isProtectedDataLoaded: false, - waitForMsw: false - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when a onLoadProtectedData handler is provided and the protected data is loaded, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - runtime.registerRoute({ - index: true, - element:
            A route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - const handleLoadProtectedData = () => Promise.resolve(); - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onLoadProtectedData: handleLoadProtectedData, - isProtectedDataLoaded: false, - waitForMsw: false - })); - - rerender(createAppRouter({ - onLoadProtectedData: handleLoadProtectedData, - isProtectedDataLoaded: true, - waitForMsw: false - })); - - expect(await screen.findByTestId("route")).toBeInTheDocument(); -}); - -test("when msw is enabled and msw is not started, render the fallback element", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - waitForMsw: true - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when msw is enabled and msw is started, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - runtime.registerRoute({ - index: true, - element:
            A route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - setMswAsStarted(); - - renderWithRuntime(runtime, createAppRouter({ - waitForMsw: true - })); - - expect(await screen.findByTestId("route")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided and there's no deferred registrations, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - runtime.registerRoute({ - index: true, - element:
            A route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - onCompleteRegistrations: () => Promise.resolve(), - waitForMsw: false - })); - - expect(await screen.findByTestId("route")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided and the deferred registrations are not completed, render the fallback element", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - // Never resolving Promise object. - await registerLocalModules([() => () => new Promise(() => {})], runtime); - - renderWithRuntime(runtime, createAppRouter({ - onCompleteRegistrations: () => completeModuleRegistrations(runtime, {}), - waitForMsw: false - })); - - expect(await screen.findByTestId("loading")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided and the deferred registrations are completed, render the router", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => { - return () => { - runtime.registerRoute({ - index: true, - element:
            A deferred route
            - }, { - hoist: true - }); - }; - }], runtime); - - function handleCompleteRegistration() { - return completeModuleRegistrations(runtime, {}); - } - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onCompleteRegistrations: handleCompleteRegistration, - waitForMsw: false - })); - - rerender(createAppRouter({ - onCompleteRegistrations: handleCompleteRegistration, - waitForMsw: false - })); - - expect(await screen.findByTestId("deferred-route")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided and a onLoadPublicData handler is provided, do not complete the deferred registrations and render the route until the public date is loaded", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => { - return () => { - runtime.registerRoute({ - index: true, - element:
            A deferred route
            - }, { - hoist: true - }); - }; - }], runtime); - - const handleLoadPublicData = () => Promise.resolve(); - - const handleCompleteRegistrations = jest.fn(() => { - return completeModuleRegistrations(runtime, {}); - }); - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onLoadPublicData: handleLoadPublicData, - isPublicDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadPublicData: handleLoadPublicData, - isPublicDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadPublicData: handleLoadPublicData, - isPublicDataLoaded: true, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).toHaveBeenCalled(); - expect(await screen.findByTestId("deferred-route")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided and a onLoadProtectedData handler is provided, do not complete the deferred registrations and render the route until the protected date is loaded", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => { - return () => { - runtime.registerRoute({ - index: true, - element:
            A deferred route
            - }, { - hoist: true - }); - }; - }], runtime); - - const handleLoadProtectedData = () => Promise.resolve(); - - const handleCompleteRegistrations = jest.fn(() => { - return completeModuleRegistrations(runtime, {}); - }); - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onLoadProtectedData: handleLoadProtectedData, - isProtectedDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadProtectedData: handleLoadProtectedData, - isProtectedDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadProtectedData: handleLoadProtectedData, - isProtectedDataLoaded: true, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).toHaveBeenCalled(); - expect(await screen.findByTestId("deferred-route")).toBeInTheDocument(); -}); - -test("when a onCompleteRegistrations handler is provided, a onLoadPublicData handler and a onLoadProtectedData handler are provided, do not complete the deferred registrations and render the route until the public and protected date are loaded", async () => { - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => { - return () => { - runtime.registerRoute({ - index: true, - element:
            A deferred route
            - }, { - hoist: true - }); - }; - }], runtime); - - const handleLoadPublicData = () => Promise.resolve(); - const handleLoadProtectedData = () => Promise.resolve(); - - const handleCompleteRegistrations = jest.fn(() => { - return completeModuleRegistrations(runtime, {}); - }); - - const { rerender } = renderWithRuntime(runtime, createAppRouter({ - onLoadPublicData: handleLoadPublicData, - onLoadProtectedData: handleLoadProtectedData, - isPublicDataLoaded: false, - isProtectedDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadPublicData: handleLoadPublicData, - onLoadProtectedData: handleLoadProtectedData, - isPublicDataLoaded: true, - isProtectedDataLoaded: false, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).not.toHaveBeenCalled(); - expect(await screen.findByTestId("loading")).toBeInTheDocument(); - - rerender(createAppRouter({ - onLoadPublicData: handleLoadPublicData, - onLoadProtectedData: handleLoadProtectedData, - isPublicDataLoaded: true, - isProtectedDataLoaded: true, - onCompleteRegistrations: handleCompleteRegistrations, - waitForMsw: false - })); - - expect(handleCompleteRegistrations).toHaveBeenCalled(); - expect(await screen.findByTestId("deferred-route")).toBeInTheDocument(); -}); - -test("when an error occurs while loading the public data, render the error element", async () => { - // An error log is expected because it will hit the ErrorBoundary, see: https://github.com/facebook/react/issues/11098. - const spy = jest.spyOn(console, "error"); - spy.mockImplementation(() => {}); - - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - onLoadPublicData: () => Promise.reject("Dummy error"), - isPublicDataLoaded: false, - waitForMsw: false - })); - - expect(await screen.findByTestId("error")).toBeInTheDocument(); - - spy.mockRestore(); -}); - -test("when an error occurs while loading the protected data, render the error element", async () => { - // An error log is expected because it will hit the ErrorBoundary, see: https://github.com/facebook/react/issues/11098. - const spy = jest.spyOn(console, "error"); - spy.mockImplementation(() => {}); - - const runtime = new FireflyRuntime(); - - runtime.registerRoute({ - path: "*", - element:
            A custom no match route
            - }, { - hoist: true - }); - - await registerLocalModules([() => {}], runtime); - - renderWithRuntime(runtime, createAppRouter({ - onLoadProtectedData: () => Promise.reject("Dummy error"), - isProtectedDataLoaded: false, - waitForMsw: false - })); - - expect(await screen.findByTestId("error")).toBeInTheDocument(); - - spy.mockRestore(); -}); - -test("throw an error if no custom no match route are registered", async () => { - const runtime = new FireflyRuntime(); - - await registerLocalModules([() => {}], runtime); - - expect(() => renderWithRuntime(runtime, createAppRouter({ - waitForMsw: false - }))).toThrow(/For the AppRouter component to work properly, the application must define a custom no match route/); -}); diff --git a/packages/firefly/tests/AppRouterReducer.test.tsx b/packages/firefly/tests/AppRouterReducer.test.tsx new file mode 100644 index 000000000..1fc93563d --- /dev/null +++ b/packages/firefly/tests/AppRouterReducer.test.tsx @@ -0,0 +1,694 @@ +import { __clearLocalModuleRegistry, __setLocalModuleRegistry, RuntimeContext, type ModuleRegistrationError, type ModuleRegistrationStatus, type ModuleRegistrationStatusChangedListener, type ModuleRegistry } from "@squide/core"; +import { __clearRemoteModuleRegistry, __setRemoteModuleRegistry } from "@squide/module-federation"; +import { __setMswState, MswState, type MswStateChangedListener } from "@squide/msw"; +import type { ReactRouterRuntime } from "@squide/react-router"; +import { act, renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { useAppRouterReducer, useModuleRegistrationStatusDispatcher, useMswStatusDispatcher, type AppRouterDispatch } from "../src/AppRouterReducer.ts"; +import { FireflyRuntime } from "../src/FireflyRuntime.tsx"; + +class DummyModuleRegistry implements ModuleRegistry { + readonly #registrationStatus: ModuleRegistrationStatus; + readonly #statusChangedListeners = new Set(); + + constructor(registrationStatus: ModuleRegistrationStatus) { + this.#registrationStatus = registrationStatus; + } + + registerModules(): Promise { + throw new Error("Method not implemented."); + } + + registerDeferredRegistrations(): Promise { + throw new Error("Method not implemented."); + } + + updateDeferredRegistrations(): Promise { + throw new Error("Method not implemented."); + } + + registerStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + this.#statusChangedListeners.add(callback); + } + + removeStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + this.#statusChangedListeners.delete(callback); + } + + get registrationStatus(): ModuleRegistrationStatus { + return this.#registrationStatus; + } + + invokeEventListeners() { + this.#statusChangedListeners.forEach(x => { + x(); + }); + } +} + +class DummyMswState extends MswState { + #isReady = false; + + readonly #stateChangedListeners = new Set(); + + constructor(isReady: boolean) { + super(); + + this.#isReady = isReady; + } + + addStateChangedListener(callback: MswStateChangedListener) { + this.#stateChangedListeners.add(callback); + } + + removeStateChangedListener(callback: MswStateChangedListener) { + this.#stateChangedListeners.delete(callback); + } + + invokeEventListeners() { + this.#stateChangedListeners.forEach(x => { + x(); + }); + } + + get isReady() { + return this.#isReady; + } +} + +afterEach(() => { + __clearLocalModuleRegistry(); + __clearRemoteModuleRegistry(); +}); + +describe("useAppRouterReducer", () => { + function renderUseAppRouterReducerHook(runtime: ReactRouterRuntime, waitForMsw: boolean, waitForPublicData: boolean, waitForProtectedData: boolean, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useAppRouterReducer(waitForMsw, waitForPublicData, waitForProtectedData), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); + } + + test("the reducer is initialized with the provided values for \"waitForMsw\", \"waitForPublicData\" and \"waitForProtectedData\" 1", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, true, true, true); + + const [state] = result.current; + + expect(state.waitForMsw).toBeTruthy(); + expect(state.waitForPublicData).toBeTruthy(); + expect(state.waitForProtectedData).toBeTruthy(); + }); + + test("the reducer is initialized with the provided values for \"waitForMsw\", \"waitForPublicData\" and \"waitForProtectedData\" 2", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + const [state] = result.current; + + expect(state.waitForMsw).toBeFalsy(); + expect(state.waitForPublicData).toBeFalsy(); + expect(state.waitForProtectedData).toBeFalsy(); + }); + + test("when \"modules-registered\" is dispatched, \"areModulesRegistered\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesRegistered).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "modules-registered" }); + }); + + expect(result.current[0].areModulesRegistered).toBeTruthy(); + }); + + test("when \"modules-ready\" is dispatched, \"areModulesReady\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesReady).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "modules-ready" }); + }); + + expect(result.current[0].areModulesReady).toBeTruthy(); + }); + + test("when \"modules-ready\" is dispatched, \"deferredRegistrationsUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].deferredRegistrationsUpdatedAt).toBeUndefined(); + + act(() => { + // dispatch + result.current[1]({ type: "modules-ready" }); + }); + + expect(result.current[0].deferredRegistrationsUpdatedAt).toEqual(Date.parse("2020-02-14")); + }); + + test("when \"msw-ready\" is dispatched, \"isMswReady\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isMswReady).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "msw-ready" }); + }); + + expect(result.current[0].isMswReady).toBeTruthy(); + }); + + test("when \"public-data-ready\" is dispatched, \"isPublicDataReady\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isPublicDataReady).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "public-data-ready" }); + }); + + expect(result.current[0].isPublicDataReady).toBeTruthy(); + }); + + test("when \"public-data-ready\" is dispatched, \"publicDataUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].publicDataUpdatedAt).toBeUndefined(); + + act(() => { + // dispatch + result.current[1]({ type: "public-data-ready" }); + }); + + expect(result.current[0].publicDataUpdatedAt).toEqual(Date.parse("2020-02-14")); + }); + + test("when \"protected-data-ready\" is dispatched, \"isProtectedDataReady\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isProtectedDataReady).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "protected-data-ready" }); + }); + + expect(result.current[0].isProtectedDataReady).toBeTruthy(); + }); + + test("when \"protected-data-ready\" is dispatched, \"protectedDataUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].protectedDataUpdatedAt).toBeUndefined(); + + act(() => { + // dispatch + result.current[1]({ type: "protected-data-ready" }); + }); + + expect(result.current[0].protectedDataUpdatedAt).toEqual(Date.parse("2020-02-14")); + }); + + test("when \"public-data-updated\" is dispatched, \"publicDataUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")) + .mockImplementationOnce(() => Date.parse("2021-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + act(() => { + // dispatch + result.current[1]({ type: "public-data-ready" }); + }); + + expect(result.current[0].publicDataUpdatedAt).toEqual(Date.parse("2020-02-14")); + + act(() => { + // dispatch + result.current[1]({ type: "public-data-updated" }); + }); + + expect(result.current[0].publicDataUpdatedAt).toEqual(Date.parse("2021-02-14")); + }); + + test("when \"protected-data-updated\" is dispatched, \"protectedDataUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")) + .mockImplementationOnce(() => Date.parse("2021-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + act(() => { + // dispatch + result.current[1]({ type: "protected-data-ready" }); + }); + + expect(result.current[0].protectedDataUpdatedAt).toEqual(Date.parse("2020-02-14")); + + act(() => { + // dispatch + result.current[1]({ type: "protected-data-updated" }); + }); + + expect(result.current[0].protectedDataUpdatedAt).toEqual(Date.parse("2021-02-14")); + }); + + test("when \"deferred-registrations-updated\" is dispatched, \"deferredRegistrationsUpdatedAt\" is set to the current timestamp", () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => Date.parse("2020-02-14")); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].deferredRegistrationsUpdatedAt).toBeUndefined(); + + act(() => { + // dispatch + result.current[1]({ type: "deferred-registrations-updated" }); + }); + + expect(result.current[0].deferredRegistrationsUpdatedAt).toEqual(Date.parse("2020-02-14")); + }); + + test("when \"active-route-is-protected\" is dispatched, \"isActiveRouteProtected\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isActiveRouteProtected).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "active-route-is-protected" }); + }); + + expect(result.current[0].isActiveRouteProtected).toBeTruthy(); + }); + + test("when \"is-unauthorized\" is dispatched, \"isUnauthorized\" is true", () => { + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isUnauthorized).toBeFalsy(); + + act(() => { + // dispatch + result.current[1]({ type: "is-unauthorized" }); + }); + + expect(result.current[0].isUnauthorized).toBeTruthy(); + }); + + test("when local modules and remote modules are registered, \"areModulesRegistered\" is true at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesRegistered).toBeTruthy(); + }); + + test("when local modules are registered and remote modules are not registered, \"areModulesRegistered\" is false at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("registering-modules"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesRegistered).toBeFalsy(); + }); + + test("when local modules are not registered and remote modules are registered, \"areModulesRegistered\" is false at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("registering-modules"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesRegistered).toBeFalsy(); + }); + + test("when local modules and remote modules are ready, \"areModulesReady\" is true at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("ready"); + const remoteModuleRegistry = new DummyModuleRegistry("ready"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesReady).toBeTruthy(); + }); + + test("when local modules are ready and remote modules are not ready, \"areModulesReady\" is false at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("ready"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesReady).toBeFalsy(); + }); + + test("when local modules are not ready and remote modules are ready, \"areModulesReady\" is false at initialization", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("ready"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].areModulesReady).toBeFalsy(); + }); + + test("when msw is ready, \"isMswReady\" is true at initialization", () => { + const mswState = new DummyMswState(true); + + __setMswState(mswState); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isMswReady).toBeTruthy(); + }); + + test("when msw is not ready, \"isMswReady\" is false at initialization", () => { + const mswState = new DummyMswState(false); + + __setMswState(mswState); + + const runtime = new FireflyRuntime(); + + const { result } = renderUseAppRouterReducerHook(runtime, false, false, false); + + expect(result.current[0].isMswReady).toBeFalsy(); + }); +}); + +describe("useModuleRegistrationStatusDispatcher", () => { + function renderUseModuleRegistrationStatusDispatcherHook(areModulesRegistered: boolean, areModulesReady: boolean, dispatch: AppRouterDispatch, additionalProps: RenderHookOptions = {}) { + const runtime = new FireflyRuntime(); + + return renderHook(() => useModuleRegistrationStatusDispatcher(areModulesRegistered, areModulesReady, dispatch), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); + } + + test("when local modules and remote modules are not registered, do not dispatch the \"modules-registered\" action", () => { + const localModuleRegistry = new DummyModuleRegistry("registering-modules"); + const remoteModuleRegistry = new DummyModuleRegistry("registering-modules"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(false, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules are registered but remote modules are not registered, do not dispatch the \"modules-registered\" action", async () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("registering-modules"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(false, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules are not registered but remote modules are registered, do not dispatch the \"modules-registered\" action", async () => { + const localModuleRegistry = new DummyModuleRegistry("registering-modules"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(false, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules and remote modules are registered, dispatch the \"modules-registered\" action", async () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(false, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).toHaveBeenCalledWith({ type: "modules-registered" }); + }); + + test("when local modules and remote modules are registered and \"areModulesRegistered\" is already true, do not dispatch the \"modules-registered\" action", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules and remote modules are not ready, do not dispatch the \"modules-ready\" action", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules are ready but remote modules are not ready, do not dispatch the \"modules-ready\" action", () => { + const localModuleRegistry = new DummyModuleRegistry("ready"); + const remoteModuleRegistry = new DummyModuleRegistry("modules-registered"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules are not ready but remote modules are ready, do not dispatch the \"modules-ready\" action", () => { + const localModuleRegistry = new DummyModuleRegistry("modules-registered"); + const remoteModuleRegistry = new DummyModuleRegistry("ready"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when local modules and remote modules are ready, dispatch the \"modules-ready\" action", async () => { + const localModuleRegistry = new DummyModuleRegistry("ready"); + const remoteModuleRegistry = new DummyModuleRegistry("ready"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, false, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).toHaveBeenCalledWith({ type: "modules-ready" }); + }); + + test("when local modules and remote modules are ready and \"areModulesReady\" is already true, do not dispatch the \"modules-ready\" action", async () => { + const localModuleRegistry = new DummyModuleRegistry("ready"); + const remoteModuleRegistry = new DummyModuleRegistry("ready"); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + const dispatch = jest.fn(); + + renderUseModuleRegistrationStatusDispatcherHook(true, true, dispatch); + + localModuleRegistry.invokeEventListeners(); + remoteModuleRegistry.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); +}); + +describe("useMswStatusDispatcher", () => { + function renderUseMswStatusDispatcherHook(isMswReady: boolean, dispatch: AppRouterDispatch, additionalProps: RenderHookOptions = {}) { + const runtime = new FireflyRuntime(); + + return renderHook(() => useMswStatusDispatcher(isMswReady, dispatch), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); + } + + test("when msw is not ready, do not dispatch the \"msw-ready\" action", () => { + const mswState = new DummyMswState(false); + + __setMswState(mswState); + + const dispatch = jest.fn(); + + renderUseMswStatusDispatcherHook(false, dispatch); + + mswState.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); + + test("when msw is ready, dispatch the \"msw-ready\" action", () => { + const mswState = new DummyMswState(true); + + __setMswState(mswState); + + const dispatch = jest.fn(); + + renderUseMswStatusDispatcherHook(false, dispatch); + + mswState.invokeEventListeners(); + + expect(dispatch).toHaveBeenCalledWith({ type: "msw-ready" }); + }); + + test("when msw is ready and \"isMswReady\" is already true, do not dispatch the \"msw-ready\" action", () => { + const mswState = new DummyMswState(true); + + __setMswState(mswState); + + const dispatch = jest.fn(); + + renderUseMswStatusDispatcherHook(true, dispatch); + + mswState.invokeEventListeners(); + + expect(dispatch).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/firefly/tests/useCanFetchProtectedData.test.tsx b/packages/firefly/tests/useCanFetchProtectedData.test.tsx new file mode 100644 index 000000000..b7be1ecda --- /dev/null +++ b/packages/firefly/tests/useCanFetchProtectedData.test.tsx @@ -0,0 +1,118 @@ +import { renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterStateContext } from "../src/AppRouterContext.ts"; +import type { AppRouterState } from "../src/AppRouterReducer.ts"; +import { useCanFetchProtectedData } from "../src/useCanFetchProtectedData.ts"; + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseCanFetchProtectedDataHook(state: AppRouterState, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useCanFetchProtectedData(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +test("when the protected data has already been fetched, return true", () => { + const state = createDefaultAppRouterState(); + state.isProtectedDataReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are registered, the active route is protected, and msw is ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.isActiveRouteProtected = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are ready, and the active route is protected, and msw is ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isActiveRouteProtected = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are registered or ready, the active route is protected, and msw is not ready but it's not required to wait for msw, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isActiveRouteProtected = true; + state.waitForMsw = false; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are not registered, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = false; + state.isActiveRouteProtected = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when the modules are not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = false; + state.isActiveRouteProtected = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when the active route is not protected, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isActiveRouteProtected = false; + state.isMswReady = true; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when it's required to wait for msw and msw is not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isActiveRouteProtected = true; + state.waitForMsw = true; + state.isMswReady = false; + + const { result } = renderUseCanFetchProtectedDataHook(state); + + expect(result.current).toBeFalsy(); +}); diff --git a/packages/firefly/tests/useCanFetchPublicData.test.tsx b/packages/firefly/tests/useCanFetchPublicData.test.tsx new file mode 100644 index 000000000..46c2fbb3b --- /dev/null +++ b/packages/firefly/tests/useCanFetchPublicData.test.tsx @@ -0,0 +1,103 @@ +import { renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterStateContext } from "../src/AppRouterContext.ts"; +import type { AppRouterState } from "../src/AppRouterReducer.ts"; +import { useCanFetchPublicData } from "../src/useCanFetchPublicData.ts"; + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseCanFetchPublicDataHook(state: AppRouterState, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useCanFetchPublicData(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +test("when the public data has already been fetched, return true", () => { + const state = createDefaultAppRouterState(); + state.isPublicDataReady = true; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are registered and msw is ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are ready and msw is ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are registered or ready and msw is not ready but it's not required to wait for msw, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.waitForMsw = false; + state.isMswReady = false; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the modules are not registered, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = false; + state.isMswReady = true; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when the modules are not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = false; + state.areModulesReady = false; + state.isMswReady = true; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when it's required to wait for msw and msw is not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.waitForMsw = true; + state.isMswReady = false; + + const { result } = renderUseCanFetchPublicDataHook(state); + + expect(result.current).toBeFalsy(); +}); diff --git a/packages/firefly/tests/useCanRegisterDeferredRegistrations.test.tsx b/packages/firefly/tests/useCanRegisterDeferredRegistrations.test.tsx new file mode 100644 index 000000000..40960cd44 --- /dev/null +++ b/packages/firefly/tests/useCanRegisterDeferredRegistrations.test.tsx @@ -0,0 +1,135 @@ +import { renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterStateContext } from "../src/AppRouterContext.ts"; +import type { AppRouterState } from "../src/AppRouterReducer.ts"; +import { useCanRegisterDeferredRegistrations } from "../src/useCanRegisterDeferredRegistrations.ts"; + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseCanRegisterDeferredRegistrationsHook(state: AppRouterState, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useCanRegisterDeferredRegistrations(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +test("when modules are registered but not ready, public data is ready, and protected data is ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when public data is not ready but it's not required to wait for public data, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.waitForPublicData = false; + state.isPublicDataReady = false; + state.isProtectedDataReady = true; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when protected data is not ready but it's not required to wait for protected data, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.waitForProtectedData = false; + state.isActiveRouteProtected = true; + state.isProtectedDataReady = false; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when protected data is not ready but the route is public, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isActiveRouteProtected = false; + state.isProtectedDataReady = false; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when modules are ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = true; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when the session is unauthorized, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isUnauthorized = true; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when it's required to wait for public data and public data is not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.waitForPublicData = true; + state.isPublicDataReady = false; + state.isProtectedDataReady = true; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when it's required to wait for protected data and the protected data is not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isActiveRouteProtected = true; + state.waitForProtectedData = true; + state.isProtectedDataReady = false; + + const { result } = renderUseCanRegisterDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); diff --git a/packages/firefly/tests/useCanUpdateDeferredRegistrations.test.tsx b/packages/firefly/tests/useCanUpdateDeferredRegistrations.test.tsx new file mode 100644 index 000000000..2982f7d96 --- /dev/null +++ b/packages/firefly/tests/useCanUpdateDeferredRegistrations.test.tsx @@ -0,0 +1,99 @@ +import { renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterStateContext } from "../src/AppRouterContext.ts"; +import type { AppRouterState } from "../src/AppRouterReducer.ts"; +import { useCanUpdateDeferredRegistrations } from "../src/useCanUpdateDeferredRegistrations.ts"; + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseCanUpdateDeferredRegistrationsHook(state: AppRouterState, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useCanUpdateDeferredRegistrations(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +test("when modules are ready, the deferred registrations has been registered once, and the public data has been updated, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state.publicDataUpdatedAt = Date.parse("2020-03-14"); + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when modules are ready, the deferred registrations has been registered once, and the protected data has been updated, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when modules are ready, the deferred registrations has been registered once, the public data has been updated, and the protected data has been updated, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state.publicDataUpdatedAt = Date.parse("2020-03-14"); + state.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when modules are not ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = false; + state.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state.publicDataUpdatedAt = Date.parse("2020-03-14"); + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when there's no deferred registrations, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.deferredRegistrationsUpdatedAt = undefined; + state.publicDataUpdatedAt = Date.parse("2020-02-14"); + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when the public and protected data has not been updated, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state.publicDataUpdatedAt = undefined; + state.protectedDataUpdatedAt = undefined; + + const { result } = renderUseCanUpdateDeferredRegistrationsHook(state); + + expect(result.current).toBeFalsy(); +}); diff --git a/packages/firefly/tests/useDeferredRegistrations.test.tsx b/packages/firefly/tests/useDeferredRegistrations.test.tsx new file mode 100644 index 000000000..9e6c33ebd --- /dev/null +++ b/packages/firefly/tests/useDeferredRegistrations.test.tsx @@ -0,0 +1,888 @@ +import { __clearLocalModuleRegistry, __setLocalModuleRegistry, LocalModuleRegistry, registerLocalModules, RuntimeContext, type ModuleRegistrationError, type Runtime } from "@squide/core"; +import { __clearRemoteModuleRegistry, __setRemoteModuleRegistry, registerRemoteModules, RemoteModuleRegistry, type RemoteModuleRegistrationError } from "@squide/module-federation"; +import { act, renderHook, waitFor, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterDispatcherContext, AppRouterStateContext } from "../src/AppRouterContext.ts"; +import { __clearAppReducerDispatchProxy, __setAppReducerDispatchProxyFactory, useAppRouterReducer, type AppRouterDispatch, type AppRouterState } from "../src/AppRouterReducer.ts"; +import { FireflyRuntime } from "../src/FireflyRuntime.tsx"; +import { useDeferredRegistrations, type DeferredRegistrationsErrorCallback } from "../src/useDeferredRegistrations.ts"; + +function sleep(delay: number) { + return new Promise(resolve => setTimeout(resolve, delay)); +} + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseAppReducerHook(runtime: Runtime, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useAppRouterReducer(true, true, true), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +function renderUseDeferredRegistrationsHook(runtime: Runtime, state: AppRouterState, dispatch: AppRouterDispatch, data: unknown, onError?: DeferredRegistrationsErrorCallback, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useDeferredRegistrations(data, { onError }), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + + + {children} + + + + ), + ...additionalProps + }); +} + +afterEach(() => { + __clearLocalModuleRegistry(); + __clearRemoteModuleRegistry(); + __clearAppReducerDispatchProxy(); +}); + +test("when modules are registered but not ready, global data is ready and msw is ready, register the deferred registrations", async () => { + const runtime = new FireflyRuntime(); + + let dispatch: jest.Mock; + + const dispatchProxyFactory = (reactDispatch: AppRouterDispatch) => { + act(() => { + dispatch = jest.fn(value => reactDispatch(value)); + }); + + return dispatch; + }; + + __setAppReducerDispatchProxyFactory(dispatchProxyFactory); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state, dispatch, initialData); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "modules-ready" })); +}); + +test("when modules are ready, msw is ready, and the public data change, update the deferred registrations", async () => { + const runtime = new FireflyRuntime(); + + let dispatch: jest.Mock; + + const dispatchProxyFactory = (reactDispatch: AppRouterDispatch) => { + act(() => { + dispatch = jest.fn(value => reactDispatch(value)); + }); + + return dispatch; + }; + + __setAppReducerDispatchProxyFactory(dispatchProxyFactory); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, initialData); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "modules-ready" })); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state2.publicDataUpdatedAt = Date.parse("2020-03-14"); + + const updatedData = { + foo: "toto" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, updatedData); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "deferred-registrations-updated" })); +}); + +test("when modules are ready, msw is ready, and the protected data change, update the deferred registrations", async () => { + const runtime = new FireflyRuntime(); + + let dispatch: jest.Mock; + + const dispatchProxyFactory = (reactDispatch: AppRouterDispatch) => { + act(() => { + dispatch = jest.fn(value => reactDispatch(value)); + }); + + return dispatch; + }; + + __setAppReducerDispatchProxyFactory(dispatchProxyFactory); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, initialData); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "modules-ready" })); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state2.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const updatedData = { + foo: "toto" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, updatedData); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "deferred-registrations-updated" })); +}); + +test("when modules are not registered, do not register the deferred registrations", async () => { + const runtime = new FireflyRuntime(); + + let dispatch: jest.Mock; + + const dispatchProxyFactory = (reactDispatch: AppRouterDispatch) => { + act(() => { + dispatch = jest.fn(value => reactDispatch(value)); + }); + + return dispatch; + }; + + __setAppReducerDispatchProxyFactory(dispatchProxyFactory); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state = createDefaultAppRouterState(); + state.areModulesRegistered = false; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state, dispatch, initialData); + + // Since the hooks cannot be awaited and there's a delay between the hook are rendered and the actions are dispatched, it's safer + // to wait for a little while before asserting. + // Not ideal thought, might be something to improve later on. + await sleep(50); + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + expect(dispatch).not.toHaveBeenCalledWith({ type: "modules-ready" }); +}); + +test("when modules are ready, msw is ready, but the global data hasn't change, do not update the deferred registrations", async () => { + const runtime = new FireflyRuntime(); + + let dispatch: jest.Mock; + + const dispatchProxyFactory = (reactDispatch: AppRouterDispatch) => { + act(() => { + dispatch = jest.fn(value => reactDispatch(value)); + }); + + return dispatch; + }; + + __setAppReducerDispatchProxyFactory(dispatchProxyFactory); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, data); + + await waitFor(() => expect(dispatch).toHaveBeenLastCalledWith({ type: "modules-ready" })); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-03-14"); + state2.publicDataUpdatedAt = Date.parse("2020-02-14"); + state2.protectedDataUpdatedAt = Date.parse("2020-02-14"); + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, data); + + // Since the hooks cannot be awaited and there's a delay between the hook are rendered and the actions are dispatched, it's safer + // to wait for a little while before asserting. + // Not ideal thought, might be something to improve later on. + await sleep(50); + + // Ignoring "dispatch is used before being assigned" because it will always being assigned through the dispatchProxyFactory function. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + expect(dispatch).not.toHaveBeenCalledWith({ type: "deferred-registrations-updated" }); +}); + +test("when an error occurs while registering the deferred registrations of the local modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const localModuleRegistrationError = { + error: new Error("toto") + } satisfies ModuleRegistrationError; + + jest.spyOn(localModuleRegistry, "registerDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + localModuleRegistrationError + ]); + }); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + const dispatch = jest.fn(); + const onError = jest.fn(); + + renderUseDeferredRegistrationsHook(runtime, state, dispatch, initialData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + localModuleErrors: expect.arrayContaining([localModuleRegistrationError]) + }) + )); +}); + +test("when an error occurs while registering the deferred registrations of the remote modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + const remoteModuleRegistrationError = { + remoteName: "foo", + moduleName: "bar", + error: new Error("toto") + } satisfies RemoteModuleRegistrationError; + + jest.spyOn(remoteModuleRegistry, "registerDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + remoteModuleRegistrationError + ]); + }); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + const dispatch = jest.fn(); + const onError = jest.fn(); + + renderUseDeferredRegistrationsHook(runtime, state, dispatch, initialData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + remoteModuleErrors: expect.arrayContaining([remoteModuleRegistrationError]) + }) + )); +}); + +test("when an error occurs while registering the deferred registrations of the local & remote modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const localModuleRegistrationError = { + error: new Error("toto") + } satisfies ModuleRegistrationError; + + jest.spyOn(localModuleRegistry, "registerDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + localModuleRegistrationError + ]); + }); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + const remoteModuleRegistrationError = { + remoteName: "foo", + moduleName: "bar", + error: new Error("toto") + } satisfies RemoteModuleRegistrationError; + + jest.spyOn(remoteModuleRegistry, "registerDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + remoteModuleRegistrationError + ]); + }); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const state = createDefaultAppRouterState(); + state.areModulesRegistered = true; + state.areModulesReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + state.isMswReady = true; + + const initialData = { + foo: "bar" + }; + + const dispatch = jest.fn(); + const onError = jest.fn(); + + renderUseDeferredRegistrationsHook(runtime, state, dispatch, initialData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + localModuleErrors: expect.arrayContaining([localModuleRegistrationError]), + remoteModuleErrors: expect.arrayContaining([remoteModuleRegistrationError]) + }) + )); +}); + +test("when an error occurs while updating the deferred registrations of the local modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const localModuleRegistrationError = { + error: new Error("toto") + } satisfies ModuleRegistrationError; + + jest.spyOn(localModuleRegistry, "updateDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + localModuleRegistrationError + ]); + }); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const dispatch = jest.fn(); + const onError = jest.fn(); + + const initialData = { + foo: "bar" + }; + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, initialData); + + // Since the hooks cannot be awaited and there's a delay between the hook are rendered and the actions are dispatched, it's safer + // to wait for a little while before asserting. + // Not ideal thought, might be something to improve later on. + await sleep(50); + + expect(onError).not.toHaveBeenCalled(); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state2.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const updatedData = { + foo: "toto" + }; + + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, updatedData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + localModuleErrors: expect.arrayContaining([localModuleRegistrationError]) + }) + )); +}); + +test("when an error occurs while updating the deferred registrations of the protected modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + const remoteModuleRegistrationError = { + remoteName: "foo", + moduleName: "bar", + error: new Error("toto") + } satisfies RemoteModuleRegistrationError; + + jest.spyOn(remoteModuleRegistry, "updateDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + remoteModuleRegistrationError + ]); + }); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const dispatch = jest.fn(); + const onError = jest.fn(); + + const initialData = { + foo: "bar" + }; + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, initialData); + + // Since the hooks cannot be awaited and there's a delay between the hook are rendered and the actions are dispatched, it's safer + // to wait for a little while before asserting. + // Not ideal thought, might be something to improve later on. + await sleep(50); + + expect(onError).not.toHaveBeenCalled(); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state2.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const updatedData = { + foo: "toto" + }; + + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, updatedData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + remoteModuleErrors: expect.arrayContaining([remoteModuleRegistrationError]) + }) + )); +}); + +test("when an error occurs while updating the deferred registrations of the local & protected modules, invoke the onError callback", async () => { + const runtime = new FireflyRuntime(); + + // Setting a dummy dispatch proxy to prevent: "Warning: An update to TestComponent inside a test was not wrapped in act(...)" + __setAppReducerDispatchProxyFactory(() => jest.fn()); + + const localModuleRegistry = new LocalModuleRegistry(); + + const localModuleRegistrationError = { + error: new Error("toto") + } satisfies ModuleRegistrationError; + + jest.spyOn(localModuleRegistry, "updateDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + localModuleRegistrationError + ]); + }); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + const remoteModuleRegistrationError = { + remoteName: "foo", + moduleName: "bar", + error: new Error("toto") + } satisfies RemoteModuleRegistrationError; + + jest.spyOn(remoteModuleRegistry, "updateDeferredRegistrations").mockImplementation(() => { + return Promise.resolve([ + remoteModuleRegistrationError + ]); + }); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + renderUseAppReducerHook(runtime); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const dispatch = jest.fn(); + const onError = jest.fn(); + + const initialData = { + foo: "bar" + }; + + const state1 = createDefaultAppRouterState(); + state1.areModulesRegistered = true; + state1.areModulesReady = false; + state1.isPublicDataReady = true; + state1.isProtectedDataReady = true; + state1.isMswReady = true; + + renderUseDeferredRegistrationsHook(runtime, state1, dispatch, initialData); + + // Since the hooks cannot be awaited and there's a delay between the hook are rendered and the actions are dispatched, it's safer + // to wait for a little while before asserting. + // Not ideal thought, might be something to improve later on. + await sleep(50); + + expect(onError).not.toHaveBeenCalled(); + + const state2 = createDefaultAppRouterState(); + state2.areModulesRegistered = true; + state2.areModulesReady = true; + state2.isPublicDataReady = true; + state2.isProtectedDataReady = true; + state2.isMswReady = true; + state2.deferredRegistrationsUpdatedAt = Date.parse("2020-02-14"); + state2.protectedDataUpdatedAt = Date.parse("2020-03-14"); + + const updatedData = { + foo: "toto" + }; + + // Not using the "rerender" function from renderHook because the AppRouterStateProvider value must be updated. I can't find how to update the wrapper + // props through a re-render. + renderUseDeferredRegistrationsHook(runtime, state2, dispatch, updatedData, onError); + + await waitFor(() => expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + localModuleErrors: expect.arrayContaining([localModuleRegistrationError]), + remoteModuleErrors: expect.arrayContaining([remoteModuleRegistrationError]) + }) + )); +}); + + diff --git a/packages/firefly/tests/useIsBootstrapping.test.tsx b/packages/firefly/tests/useIsBootstrapping.test.tsx new file mode 100644 index 000000000..18fea67cb --- /dev/null +++ b/packages/firefly/tests/useIsBootstrapping.test.tsx @@ -0,0 +1,157 @@ +import { renderHook, type RenderHookOptions } from "@testing-library/react"; +import type { ReactNode } from "react"; +import { AppRouterStateContext } from "../src/AppRouterContext.ts"; +import type { AppRouterState } from "../src/AppRouterReducer.ts"; +import { useIsBootstrapping } from "../src/useIsBootstrapping.ts"; + +function createDefaultAppRouterState(): AppRouterState { + return { + areModulesReady: false, + areModulesRegistered: false, + isActiveRouteProtected: false, + isMswReady: false, + isProtectedDataReady: false, + isPublicDataReady: false, + isUnauthorized: false, + waitForMsw: false, + waitForProtectedData: false, + waitForPublicData: false + }; +} + +function renderUseIsBootstrappingHook(state: AppRouterState, additionalProps: RenderHookOptions = {}) { + return renderHook(() => useIsBootstrapping(), { + wrapper: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), + ...additionalProps + }); +} + +test("when modules are ready, and msw is ready, public data is ready, and protected data is ready, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when msw is not ready but it's not required to wait for msw, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.waitForMsw = false; + state.isMswReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when public data is not ready but it's not required to wait for public data, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.waitForPublicData = false; + state.isPublicDataReady = false; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when protected data is not ready but it's not required to wait for protected data, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.isPublicDataReady = true; + state.waitForProtectedData = false; + state.isProtectedDataReady = false; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when protected data is not ready but the active route is public, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.isPublicDataReady = true; + state.isActiveRouteProtected = false; + state.isProtectedDataReady = false; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); + +test("when modules are not ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = false; + state.isMswReady = true; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when msw is not ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.waitForMsw = true; + state.isMswReady = false; + state.isPublicDataReady = true; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when public data is not ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.waitForPublicData = true; + state.isPublicDataReady = false; + state.isProtectedDataReady = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when protected data is not ready, return true", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = true; + state.isMswReady = true; + state.isPublicDataReady = true; + state.waitForProtectedData = true; + state.isActiveRouteProtected = true; + state.isProtectedDataReady = false; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeTruthy(); +}); + +test("when the session is unauthorized, return false", () => { + const state = createDefaultAppRouterState(); + state.areModulesReady = false; + state.isUnauthorized = true; + + const { result } = renderUseIsBootstrappingHook(state); + + expect(result.current).toBeFalsy(); +}); diff --git a/packages/i18next/package.json b/packages/i18next/package.json index 9e3a42f9c..c0e5fc8b7 100644 --- a/packages/i18next/package.json +++ b/packages/i18next/package.json @@ -38,26 +38,26 @@ "react-i18next": "*" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "i18next": "23.11.3", - "i18next-browser-languagedetector": "7.2.1", + "i18next": "23.12.1", + "i18next-browser-languagedetector": "8.0.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-i18next": "14.1.1", - "ts-jest": "29.1.2", - "tsup": "8.0.2", - "typescript": "5.4.5" + "react-i18next": "15.0.0", + "ts-jest": "29.2.3", + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "@formatjs/intl-localematcher": "0.5.4", diff --git a/packages/i18next/src/i18nextPlugin.ts b/packages/i18next/src/i18nextPlugin.ts index 7bad45157..852d6bfe7 100644 --- a/packages/i18next/src/i18nextPlugin.ts +++ b/packages/i18next/src/i18nextPlugin.ts @@ -31,7 +31,6 @@ export function findSupportedPreferredLanguage(userPreferredLa } export class i18nextPlugin extends Plugin { - #runtime?: Runtime; #currentLanguage?: T; readonly #supportedLanguages: T[]; @@ -39,8 +38,8 @@ export class i18nextPlugin extends Plugin { readonly #languageDetector: LanguageDetector; readonly #registry = new i18nextInstanceRegistry(); - constructor(supportedLanguages: T[], fallbackLanguage: T, queryStringKey: string, { detection }: i18nextPluginOptions = {}) { - super(i18nextPlugin.name); + constructor(supportedLanguages: T[], fallbackLanguage: T, queryStringKey: string, { detection }: i18nextPluginOptions = {}, runtime: Runtime) { + super(i18nextPlugin.name, runtime); this.#supportedLanguages = supportedLanguages; this.#fallbackLanguage = fallbackLanguage; @@ -52,14 +51,10 @@ export class i18nextPlugin extends Plugin { }); } - _setRuntime(runtime: Runtime) { - this.#runtime = runtime; - } - registerInstance(key: string, instance: i18n) { this.#registry.add(key, instance); - this.#runtime?.logger.debug(`[squide] Registered a new i18next instance with key "${key}":`, instance); + this._runtime.logger.debug(`[squide] Registered a new i18next instance with key "${key}":`, instance); } getInstance(key: string) { @@ -79,12 +74,12 @@ export class i18nextPlugin extends Plugin { if (detectedLanguage) { // The navigator language preferences could be something like ["en-US", "en", "fr-CA", "fr"]. if (Array.isArray(detectedLanguage)) { - this.#runtime?.logger.debug(`[squide] Detected ${detectedLanguage.map(x => `"${x}"`).join(",")} as user language${detectedLanguage.length >= 1 ? "s" : ""}.`); + this._runtime.logger.debug(`[squide] Detected ${detectedLanguage.map(x => `"${x}"`).join(",")} as user language${detectedLanguage.length >= 1 ? "s" : ""}.`); // Ensure the navigator language preferences includes at least one supported language. detectedLanguage = findSupportedPreferredLanguage(detectedLanguage, this.#supportedLanguages); } else { - this.#runtime?.logger.debug(`[squide] Detected "${detectedLanguage}" as user language.`); + this._runtime.logger.debug(`[squide] Detected "${detectedLanguage}" as user language.`); // Ensure the navigator language preferences includes at least one supported language. detectedLanguage = findSupportedPreferredLanguage([detectedLanguage], this.#supportedLanguages); @@ -97,7 +92,7 @@ export class i18nextPlugin extends Plugin { this.#currentLanguage = detectedLanguage as T; - this.#runtime?.logger.debug(`[squide] The language has been set to "${this.#currentLanguage}".`); + this._runtime.logger.debug(`[squide] The language has been set to "${this.#currentLanguage}".`); } get currentLanguage() { @@ -120,7 +115,7 @@ export class i18nextPlugin extends Plugin { this.#currentLanguage = language; - this.#runtime?.logger.debug(`[squide] The language has been changed to "${this.#currentLanguage}".`); + this._runtime.logger.debug(`[squide] The language has been changed to "${this.#currentLanguage}".`); } } } diff --git a/packages/module-federation/package.json b/packages/module-federation/package.json index 2fb14f5dc..ead7b3e38 100644 --- a/packages/module-federation/package.json +++ b/packages/module-federation/package.json @@ -35,11 +35,11 @@ "react-dom": "*" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@types/node": "20.12.7", - "@types/react": "18.3.1", + "@types/node": "20.14.11", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", @@ -50,12 +50,12 @@ "jest-environment-jsdom": "29.7.0", "react": "18.3.1", "react-dom": "18.3.1", - "ts-jest": "29.1.2", - "tsup": "8.0.2", - "typescript": "5.4.5" + "ts-jest": "29.2.3", + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { - "@module-federation/enhanced": "0.1.11", + "@module-federation/enhanced": "0.2.6", "@squide/core": "workspace:*" }, "sideEffects": false, diff --git a/packages/module-federation/src/areModulesReady.ts b/packages/module-federation/src/areModulesReady.ts new file mode 100644 index 000000000..b40825696 --- /dev/null +++ b/packages/module-federation/src/areModulesReady.ts @@ -0,0 +1,11 @@ +import type { ModuleRegistrationStatus } from "@squide/core"; + +export function areModulesReady(localModuleRegistrationStatus: ModuleRegistrationStatus, remoteModuleRegistrationStatus: ModuleRegistrationStatus) { + if (localModuleRegistrationStatus === "none" && remoteModuleRegistrationStatus === "none") { + return false; + } + + // The registration for local or remote modules could be "none" if an application doesn't register either local or remote modules. + return (localModuleRegistrationStatus === "none" || localModuleRegistrationStatus === "ready") && + (remoteModuleRegistrationStatus === "none" || remoteModuleRegistrationStatus === "ready"); +} diff --git a/packages/module-federation/src/areModulesRegistered.ts b/packages/module-federation/src/areModulesRegistered.ts new file mode 100644 index 000000000..6f3ad198d --- /dev/null +++ b/packages/module-federation/src/areModulesRegistered.ts @@ -0,0 +1,13 @@ +import type { ModuleRegistrationStatus } from "@squide/core"; + +export function areModulesRegistered(localModuleRegistrationStatus: ModuleRegistrationStatus, remoteModuleRegistrationStatus: ModuleRegistrationStatus) { + if (localModuleRegistrationStatus === "none" && remoteModuleRegistrationStatus === "none") { + return false; + } + + // The registration for local or remote modules could be "none" if an application doesn't register either local or remote modules. + // The registration for local or remote modules could be "registering-deferred-registration" if all the modules of an application are registered and it's registering the deferred registrations (which is considered as being already registered). + // The registration statuses could be at "ready" if there's no deferred registrations. + return (localModuleRegistrationStatus === "none" || localModuleRegistrationStatus === "modules-registered" || localModuleRegistrationStatus === "registering-deferred-registration" || localModuleRegistrationStatus === "ready") && + (remoteModuleRegistrationStatus === "none" || remoteModuleRegistrationStatus === "modules-registered" || remoteModuleRegistrationStatus === "registering-deferred-registration" || remoteModuleRegistrationStatus === "ready"); +} diff --git a/packages/module-federation/src/completeModuleRegistrations.ts b/packages/module-federation/src/completeModuleRegistrations.ts deleted file mode 100644 index 454df8afb..000000000 --- a/packages/module-federation/src/completeModuleRegistrations.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { completeLocalModuleRegistrations, getLocalModuleRegistrationStatus, type LocalModuleRegistrationError, type Runtime } from "@squide/core"; -import { completeRemoteModuleRegistrations, getRemoteModuleRegistrationStatus, type RemoteModuleRegistrationError } from "./registerRemoteModules.ts"; - -export async function completeModuleRegistrations(runtime: TRuntime, data?: TData) { - const promise: Promise[] = []; - - if (getLocalModuleRegistrationStatus() !== "none") { - promise.push(completeLocalModuleRegistrations(runtime, data)); - } - - if (getRemoteModuleRegistrationStatus() !== "none") { - promise.push(completeRemoteModuleRegistrations(runtime, data)); - } - - const [localModuleErrors, remoteModuleErrors] = await Promise.allSettled(promise); - - return { - localModuleErrors: localModuleErrors as unknown as LocalModuleRegistrationError, - remoteModuleErrors: remoteModuleErrors as unknown as RemoteModuleRegistrationError - }; -} diff --git a/packages/module-federation/src/index.ts b/packages/module-federation/src/index.ts index 4c8e6d8ad..a8001cff6 100644 --- a/packages/module-federation/src/index.ts +++ b/packages/module-federation/src/index.ts @@ -1,6 +1,7 @@ -export * from "./completeModuleRegistrations.ts"; +export * from "./areModulesReady.ts"; +export * from "./areModulesRegistered.ts"; +export * from "./registerDeferredRegistrations.ts"; export * from "./registerRemoteModules.ts"; export * from "./remoteDefinition.ts"; -export { useAreModulesReady } from "./useAreModulesReady.ts"; -export { useAreModulesRegistered } from "./useAreModulesRegistered.ts"; +export * from "./updateDeferredRegistrations.ts"; diff --git a/packages/module-federation/src/registerDeferredRegistrations.ts b/packages/module-federation/src/registerDeferredRegistrations.ts new file mode 100644 index 000000000..03e6b61a4 --- /dev/null +++ b/packages/module-federation/src/registerDeferredRegistrations.ts @@ -0,0 +1,18 @@ +import { registerLocalModuleDeferredRegistrations, type Runtime } from "@squide/core"; +import { registerRemoteModuleDeferredRegistrations } from "./registerRemoteModules.ts"; + +export async function registerDeferredRegistrations(data: TData, runtime: TRuntime) { + runtime.startDeferredRegistrationScope(); + + try { + const localModuleErrors = await registerLocalModuleDeferredRegistrations(data, runtime); + const remoteModuleErrors = await registerRemoteModuleDeferredRegistrations(data, runtime); + + return { + localModuleErrors, + remoteModuleErrors + }; + } finally { + runtime.completeDeferredRegistrationScope(); + } +} diff --git a/packages/module-federation/src/registerRemoteModules.ts b/packages/module-federation/src/registerRemoteModules.ts index 7d9cc011b..14037337b 100644 --- a/packages/module-federation/src/registerRemoteModules.ts +++ b/packages/module-federation/src/registerRemoteModules.ts @@ -1,5 +1,5 @@ import { loadRemote as loadModuleFederationRemote } from "@module-federation/enhanced/runtime"; -import { isFunction, isNil, registerModule, type DeferredRegistrationFunction, type Logger, type ModuleRegistrationStatus, type Runtime } from "@squide/core"; +import { isFunction, isNil, registerModule, type DeferredRegistrationFunction, type Logger, type ModuleRegistrationError, type ModuleRegistrationStatus, type ModuleRegistrationStatusChangedListener, type ModuleRegistry, type RegisterModulesOptions, type Runtime } from "@squide/core"; import type { RemoteDefinition } from "./remoteDefinition.ts"; const RemoteRegisterModuleName = "register"; @@ -13,19 +13,11 @@ interface DeferredRegistration { fct: DeferredRegistrationFunction; } -export interface RegisterRemoteModulesOptions { - context?: TContext; -} - -export type RemoteModuleRegistrationStatusChangedListener = () => void; - -export interface RemoteModuleRegistrationError { +export interface RemoteModuleRegistrationError extends ModuleRegistrationError { // The name of the remote module. remoteName: string; // The name of the remote module resource. moduleName: string; - // The registration error. - error: unknown; } export class RemoteModuleRegistry { @@ -33,7 +25,7 @@ export class RemoteModuleRegistry { readonly #deferredRegistrations: DeferredRegistration[] = []; readonly #loadRemote: LoadRemoteFunction; - readonly #statusChangedListeners = new Set(); + readonly #statusChangedListeners = new Set(); constructor(loadRemote: LoadRemoteFunction) { this.#loadRemote = loadRemote; @@ -52,7 +44,7 @@ export class RemoteModuleRegistry { } } - async registerModules(remotes: RemoteDefinition[], runtime: TRuntime, { context }: RegisterRemoteModulesOptions = {}) { + async registerModules(remotes: RemoteDefinition[], runtime: TRuntime, { context }: RegisterModulesOptions = {}) { const errors: RemoteModuleRegistrationError[] = []; if (this.#registrationStatus !== "none") { @@ -61,7 +53,7 @@ export class RemoteModuleRegistry { runtime.logger.debug(`[squide] Found ${remotes.length} remote module${remotes.length !== 1 ? "s" : ""} to register.`); - this.#setRegistrationStatus("in-progress"); + this.#setRegistrationStatus("registering-modules"); await Promise.allSettled(remotes.map(async (x, index) => { const remoteName = x.name; @@ -102,7 +94,7 @@ export class RemoteModuleRegistry { } })); - this.#setRegistrationStatus(this.#deferredRegistrations.length > 0 ? "registered" : "ready"); + this.#setRegistrationStatus(this.#deferredRegistrations.length > 0 ? "modules-registered" : "ready"); // After introducting the "setRegistrationStatus" method, TypeScript seems to think that the only possible // values for registrationStatus is "none" and now complains about the lack of overlapping between "none" and "ready". @@ -115,32 +107,32 @@ export class RemoteModuleRegistry { return errors; } - async completeModuleRegistrations(runtime: TRuntime, data?: TData) { + async registerDeferredRegistrations(data: TData, runtime: TRuntime) { const errors: RemoteModuleRegistrationError[] = []; - if (this.#registrationStatus === "none" || this.#registrationStatus === "in-progress") { - throw new Error("[squide] The completeRemoteModuleRegistration function can only be called once the registerRemoteModules function terminated."); + if (this.#registrationStatus === "none" || this.#registrationStatus === "registering-modules") { + throw new Error("[squide] The registerDeferredRegistrations function can only be called once the remote modules are registered."); } - if (this.#registrationStatus !== "registered" && this.#deferredRegistrations.length > 0) { - throw new Error("[squide] The completeRemoteModuleRegistration function can only be called once."); + if (this.#registrationStatus !== "modules-registered" && this.#deferredRegistrations.length > 0) { + throw new Error("[squide] The registerDeferredRegistrations function can only be called once."); } if (this.#registrationStatus === "ready") { // No deferred registrations were returned by the remote modules, skip the completion process. - return Promise.resolve(errors); + return errors; } - this.#setRegistrationStatus("in-completion"); + this.#setRegistrationStatus("registering-deferred-registration"); await Promise.allSettled(this.#deferredRegistrations.map(async ({ remoteName, index, fct: deferredRegister }) => { - runtime.logger.debug(`[squide] ${index} Completing registration for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); + runtime.logger.debug(`[squide] ${index} Registering the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); try { - await deferredRegister(data); + await deferredRegister(data, "register"); } catch (error: unknown) { runtime.logger.error( - `[squide] ${index} An error occured while completing the registration for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`, + `[squide] ${index} An error occured while registering the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`, error ); @@ -151,7 +143,7 @@ export class RemoteModuleRegistry { }); } - runtime.logger.debug(`[squide] ${index} Completed registration for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); + runtime.logger.debug(`[squide] ${index} Registered the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); })); this.#setRegistrationStatus("ready"); @@ -161,11 +153,42 @@ export class RemoteModuleRegistry { return errors; } - registerStatusChangedListener(callback: RemoteModuleRegistrationStatusChangedListener) { + async updateDeferredRegistrations(data: TData, runtime: TRuntime) { + const errors: RemoteModuleRegistrationError[] = []; + + if (this.#registrationStatus !== "ready") { + throw new Error("[squide] The updateDeferredRegistrations function can only be called once the remote modules are ready."); + } + + await Promise.allSettled(this.#deferredRegistrations.map(async ({ remoteName, index, fct: deferredRegister }) => { + runtime.logger.debug(`[squide] ${index} Updating the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); + + try { + await deferredRegister(data, "update"); + } catch (error: unknown) { + runtime.logger.error( + `[squide] ${index} An error occured while updating the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`, + error + ); + + errors.push({ + remoteName, + moduleName: RemoteRegisterModuleName, + error + }); + } + + runtime.logger.debug(`[squide] ${index} Updated the deferred registrations for module "${RemoteRegisterModuleName}" of remote "${remoteName}".`); + })); + + return errors; + } + + registerStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { this.#statusChangedListeners.add(callback); } - removeStatusChangedListener(callback: RemoteModuleRegistrationStatusChangedListener) { + removeStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { this.#statusChangedListeners.delete(callback); } @@ -180,31 +203,48 @@ export class RemoteModuleRegistry { get registrationStatus() { return this.#registrationStatus; } +} + +let remoteModuleRegistry: ModuleRegistry | undefined; - // Required to test hooks that dependent on the registration status. - resetRegistrationStatus() { - this.#registrationStatus = "none"; +function getRemoteModuleRegistry() { + if (!remoteModuleRegistry) { + remoteModuleRegistry = new RemoteModuleRegistry((remoteName, moduleName) => loadModuleFederationRemote(`${remoteName}/${moduleName}`)); } + + return remoteModuleRegistry; +} + +// This function should only be used by tests. +export function __setRemoteModuleRegistry(registry: ModuleRegistry) { + remoteModuleRegistry = registry; +} + +// This function should only be used by tests. +export function __clearRemoteModuleRegistry() { + remoteModuleRegistry = undefined; } -const remoteModuleRegistry = new RemoteModuleRegistry((remoteName, moduleName) => loadModuleFederationRemote(`${remoteName}/${moduleName}`)); +export function registerRemoteModules(remotes: RemoteDefinition[], runtime: TRuntime, options?: RegisterModulesOptions) { + return getRemoteModuleRegistry().registerModules(remotes, runtime, options); +} -export function registerRemoteModules(remotes: RemoteDefinition[], runtime: TRuntime, options?: RegisterRemoteModulesOptions) { - return remoteModuleRegistry.registerModules(remotes, runtime, options); +export function registerRemoteModuleDeferredRegistrations(data: TData, runtime: TRuntime) { + return getRemoteModuleRegistry().registerDeferredRegistrations(data, runtime); } -export function completeRemoteModuleRegistrations(runtime: TRuntime, data?: TData) { - return remoteModuleRegistry.completeModuleRegistrations(runtime, data); +export function updateRemoteModuleDeferredRegistrations(data: TData, runtime: TRuntime) { + return getRemoteModuleRegistry().updateDeferredRegistrations(data, runtime); } export function getRemoteModuleRegistrationStatus() { - return remoteModuleRegistry.registrationStatus; + return getRemoteModuleRegistry().registrationStatus; } -export function addRemoteModuleRegistrationStatusChangedListener(callback: RemoteModuleRegistrationStatusChangedListener) { - remoteModuleRegistry.registerStatusChangedListener(callback); +export function addRemoteModuleRegistrationStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + getRemoteModuleRegistry().registerStatusChangedListener(callback); } -export function removeRemoteModuleRegistrationStatusChangedListener(callback: RemoteModuleRegistrationStatusChangedListener) { - remoteModuleRegistry.removeStatusChangedListener(callback); +export function removeRemoteModuleRegistrationStatusChangedListener(callback: ModuleRegistrationStatusChangedListener) { + getRemoteModuleRegistry().removeStatusChangedListener(callback); } diff --git a/packages/module-federation/src/updateDeferredRegistrations.ts b/packages/module-federation/src/updateDeferredRegistrations.ts new file mode 100644 index 000000000..9bc6a06c3 --- /dev/null +++ b/packages/module-federation/src/updateDeferredRegistrations.ts @@ -0,0 +1,18 @@ +import { updateLocalModuleDeferredRegistrations, type Runtime } from "@squide/core"; +import { updateRemoteModuleDeferredRegistrations } from "./registerRemoteModules.ts"; + +export async function updateDeferredRegistrations(data: TData, runtime: TRuntime) { + runtime.startDeferredRegistrationScope(true); + + try { + const localModuleErrors = await updateLocalModuleDeferredRegistrations(data, runtime); + const remoteModuleErrors = await updateRemoteModuleDeferredRegistrations(data, runtime); + + return { + localModuleErrors, + remoteModuleErrors + }; + } finally { + runtime.completeDeferredRegistrationScope(); + } +} diff --git a/packages/module-federation/src/useAreModulesReady.ts b/packages/module-federation/src/useAreModulesReady.ts deleted file mode 100644 index 38e2a0e62..000000000 --- a/packages/module-federation/src/useAreModulesReady.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { addLocalModuleRegistrationStatusChangedListener, getLocalModuleRegistrationStatus, removeLocalModuleRegistrationStatusChangedListener, useRuntime, type ModuleRegistrationStatus } from "@squide/core"; -import { useEffect, useMemo, useSyncExternalStore } from "react"; -import { addRemoteModuleRegistrationStatusChangedListener, getRemoteModuleRegistrationStatus, removeRemoteModuleRegistrationStatusChangedListener } from "./registerRemoteModules.ts"; - -export function areModulesReady(localModuleRegistrationStatus: ModuleRegistrationStatus, remoteModuleRegistrationStatus: ModuleRegistrationStatus) { - if (localModuleRegistrationStatus === "none" && remoteModuleRegistrationStatus === "none") { - return false; - } - - // The registration for local or remote modules could be "none" if an application doesn't register either local or remote modules. - return (localModuleRegistrationStatus === "none" || localModuleRegistrationStatus === "ready") && - (remoteModuleRegistrationStatus === "none" || remoteModuleRegistrationStatus === "ready"); -} - -function subscribeToLocalModuleRegistrationStatusChanged(callback: () => void) { - addLocalModuleRegistrationStatusChangedListener(callback); - - return () => removeLocalModuleRegistrationStatusChangedListener(callback); -} - -function subscribeToRemoteModuleRegistrationStatusChanged(callback: () => void) { - addRemoteModuleRegistrationStatusChangedListener(callback); - - return () => removeRemoteModuleRegistrationStatusChangedListener(callback); -} - -export function useAreModulesReady() { - const localModuleStatus = useSyncExternalStore(subscribeToLocalModuleRegistrationStatusChanged, getLocalModuleRegistrationStatus); - const remoteModuleStatus = useSyncExternalStore(subscribeToRemoteModuleRegistrationStatusChanged, getRemoteModuleRegistrationStatus); - - const runtime = useRuntime(); - - useEffect(() => { - if (areModulesReady(localModuleStatus, remoteModuleStatus)) { - runtime._completeRegistration(); - } - }, []); - - return useMemo(() => { - return areModulesReady(localModuleStatus, remoteModuleStatus); - }, [localModuleStatus, remoteModuleStatus]); -} diff --git a/packages/module-federation/src/useAreModulesRegistered.ts b/packages/module-federation/src/useAreModulesRegistered.ts deleted file mode 100644 index db2202a00..000000000 --- a/packages/module-federation/src/useAreModulesRegistered.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { addLocalModuleRegistrationStatusChangedListener, getLocalModuleRegistrationStatus, removeLocalModuleRegistrationStatusChangedListener, type ModuleRegistrationStatus } from "@squide/core"; -import { useMemo, useSyncExternalStore } from "react"; -import { addRemoteModuleRegistrationStatusChangedListener, getRemoteModuleRegistrationStatus, removeRemoteModuleRegistrationStatusChangedListener } from "./registerRemoteModules.ts"; - -export function areModulesRegistered(localModuleRegistrationStatus: ModuleRegistrationStatus, remoteModuleRegistrationStatus: ModuleRegistrationStatus) { - if (localModuleRegistrationStatus === "none" && remoteModuleRegistrationStatus === "none") { - return false; - } - - // The registration for local or remote modules could be "none" if an application doesn't register either local or remote modules. - // The registration statuses could be at "ready" if there's no deferred registrations. - return (localModuleRegistrationStatus === "none" || localModuleRegistrationStatus === "registered" || localModuleRegistrationStatus === "ready") && - (remoteModuleRegistrationStatus === "none" || remoteModuleRegistrationStatus === "registered" || remoteModuleRegistrationStatus === "ready"); -} - -function subscribeToLocalModuleRegistrationStatusChanged(callback: () => void) { - addLocalModuleRegistrationStatusChangedListener(callback); - - return () => removeLocalModuleRegistrationStatusChangedListener(callback); -} - -function subscribeToRemoteModuleRegistrationStatusChanged(callback: () => void) { - addRemoteModuleRegistrationStatusChangedListener(callback); - - return () => removeRemoteModuleRegistrationStatusChangedListener(callback); -} - -export function useAreModulesRegistered() { - const localModuleStatus = useSyncExternalStore(subscribeToLocalModuleRegistrationStatusChanged, getLocalModuleRegistrationStatus); - const remoteModuleStatus = useSyncExternalStore(subscribeToRemoteModuleRegistrationStatusChanged, getRemoteModuleRegistrationStatus); - - return useMemo(() => { - return areModulesRegistered(localModuleStatus, remoteModuleStatus); - }, [localModuleStatus, remoteModuleStatus]); -} diff --git a/packages/module-federation/tests/areModulesReady.test.tsx b/packages/module-federation/tests/areModulesReady.test.tsx index 79a542184..b313f63a7 100644 --- a/packages/module-federation/tests/areModulesReady.test.tsx +++ b/packages/module-federation/tests/areModulesReady.test.tsx @@ -1,10 +1,6 @@ -// The areModulesReady function is tested instead of the useAreModulesReady hook because it requires less mocking and -// kind of provide the same coverage as the only important logic to test for that hook is the check to validate whether -// or not the module registrations is considered as ready or not. - import { LocalModuleRegistry, Runtime } from "@squide/core"; +import { areModulesReady } from "../src/areModulesReady.ts"; import { RemoteModuleRegistry } from "../src/registerRemoteModules.ts"; -import { areModulesReady } from "../src/useAreModulesReady.ts"; class DummyRuntime extends Runtime { registerRoute() { @@ -22,6 +18,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); @@ -49,7 +53,7 @@ test("when only local modules are registered and they are ready, return true", a () => {} ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -67,7 +71,7 @@ test("when only remote modules are registered and they are ready, return true", { name: "Dummy-3" } ], runtime); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -85,7 +89,7 @@ test("when only local module deferred registrations are registered and they are () => () => {} ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -104,7 +108,7 @@ test("when only remote module deferred registrations are registered and they are ], runtime); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -128,8 +132,8 @@ test("when local module deferred registrations and remote module deferred regist { name: "Dummy-3" } ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -153,8 +157,8 @@ test("when local module deferred registrations and remote modules are registered { name: "Dummy-3" } ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -178,8 +182,8 @@ test("when local modules and remote module deferred registrations are registered { name: "Dummy-3" } ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeTruthy(); }); @@ -257,7 +261,7 @@ test("when local module deferred registrations and remote module deferred regist { name: "Dummy-3" } ], runtime); - await localModuleRegistry.completeModuleRegistrations(runtime, {}); + await localModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeFalsy(); }); @@ -281,7 +285,7 @@ test("when local module deferred registrations and remote module deferred regist { name: "Dummy-3" } ], runtime); - await remoteModuleRegistry.completeModuleRegistrations(runtime, {}); + await remoteModuleRegistry.registerDeferredRegistrations({}, runtime); expect(areModulesReady(localModuleRegistry.registrationStatus, remoteModuleRegistry.registrationStatus)).toBeFalsy(); }); diff --git a/packages/module-federation/tests/areModulesRegistered.test.tsx b/packages/module-federation/tests/areModulesRegistered.test.tsx index f59ba515e..2de5b90f3 100644 --- a/packages/module-federation/tests/areModulesRegistered.test.tsx +++ b/packages/module-federation/tests/areModulesRegistered.test.tsx @@ -1,10 +1,6 @@ -// The areModulesRegistered function is tested instead of the useAreModulesRegistered hook because it requires less mocking and -// kind of provide the same coverage as the only important logic to test for that hook is the check to validate whether -// or not the module registrations is considered as registered or not. - import { LocalModuleRegistry, Runtime } from "@squide/core"; +import { areModulesRegistered } from "../src/areModulesRegistered.ts"; import { RemoteModuleRegistry } from "../src/registerRemoteModules.ts"; -import { areModulesRegistered } from "../src/useAreModulesRegistered.ts"; class DummyRuntime extends Runtime { registerRoute() { @@ -22,6 +18,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); diff --git a/packages/module-federation/tests/registerDeferredRegistrations.test.ts b/packages/module-federation/tests/registerDeferredRegistrations.test.ts new file mode 100644 index 000000000..0c60d51b9 --- /dev/null +++ b/packages/module-federation/tests/registerDeferredRegistrations.test.ts @@ -0,0 +1,142 @@ +import { __setLocalModuleRegistry, LocalModuleRegistry, registerLocalModules, Runtime } from "@squide/core"; +import { registerDeferredRegistrations } from "../src/registerDeferredRegistrations.ts"; +import { __setRemoteModuleRegistry, registerRemoteModules, RemoteModuleRegistry } from "../src/registerRemoteModules.ts"; + +class DummyRuntime extends Runtime { + registerRoute() { + throw new Error("Method not implemented."); + } + + get routes() { + return []; + } + + registerNavigationItem() { + throw new Error("Method not implemented."); + } + + getNavigationItems() { + return []; + } + + startDeferredRegistrationScope(): void { + } + + completeDeferredRegistrationScope(): void { + } +} + +test("register local and remote deferred registrations", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const localRegistrationsSpy = jest.spyOn(localModuleRegistry, "registerDeferredRegistrations"); + const remoteRegistrationsSpy = jest.spyOn(remoteModuleRegistry, "registerDeferredRegistrations"); + + const data = { + foo: "bar" + }; + + await registerDeferredRegistrations(data, runtime); + + expect(localRegistrationsSpy).toHaveBeenCalledWith(data, runtime); + expect(remoteRegistrationsSpy).toHaveBeenCalledWith(data, runtime); +}); + +test("start and complete a deferred registration scope", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + const startScopeSpy = jest.spyOn(runtime, "startDeferredRegistrationScope"); + const completeScopeSpy = jest.spyOn(runtime, "completeDeferredRegistrationScope"); + + await registerDeferredRegistrations(data, runtime); + + expect(startScopeSpy).toHaveBeenCalledTimes(1); + expect(completeScopeSpy).toHaveBeenCalledTimes(1); +}); + +test("when an unmanaged error is thrown, complete the deferred registration scope", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + jest.spyOn(localModuleRegistry, "registerDeferredRegistrations").mockImplementation(() => { + throw new Error("Something went wrong!"); + }); + + const completeScopeSpy = jest.spyOn(runtime, "completeDeferredRegistrationScope"); + + // Oddly, I can't get it to work with expect(() => {}).toThrow(); + try { + await registerDeferredRegistrations(data, runtime); + } catch (error: unknown) { + // .... + } + + expect(completeScopeSpy).toHaveBeenCalledTimes(1); +}); diff --git a/packages/module-federation/tests/completeRemoteModuleRegistrations.test.ts b/packages/module-federation/tests/registerRemoteModuleDeferredRegistrations.test.ts similarity index 69% rename from packages/module-federation/tests/completeRemoteModuleRegistrations.test.ts rename to packages/module-federation/tests/registerRemoteModuleDeferredRegistrations.test.ts index b570ee379..dfcf53aed 100644 --- a/packages/module-federation/tests/completeRemoteModuleRegistrations.test.ts +++ b/packages/module-federation/tests/registerRemoteModuleDeferredRegistrations.test.ts @@ -25,6 +25,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); @@ -32,7 +40,7 @@ const runtime = new DummyRuntime(); test("when called before registerRemoteModules, throw an error", async () => { const registry = new RemoteModuleRegistry(jest.fn()); - await expect(() => registry.completeModuleRegistrations(runtime, {})).rejects.toThrow(/The completeRemoteModuleRegistration function can only be called once the registerRemoteModules function terminated/); + await expect(() => registry.registerDeferredRegistrations({}, runtime)).rejects.toThrow(/The registerDeferredRegistrations function can only be called once the remote modules are registered/); }); test("when called twice, throw an error", async () => { @@ -47,9 +55,9 @@ test("when called twice, throw an error", async () => { { name: "Dummy-2" } ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); - await expect(() => registry.completeModuleRegistrations(runtime, {})).rejects.toThrow(/The completeRemoteModuleRegistration function can only be called once/); + await expect(() => registry.registerDeferredRegistrations({}, runtime)).rejects.toThrow(/The registerDeferredRegistrations function can only be called once/); }); test("when called for the first time but the registration status is already \"ready\", return a resolving promise", async () => { @@ -67,7 +75,7 @@ test("when called for the first time but the registration status is already \"re expect(registry.registrationStatus).toBe("ready"); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(registry.registrationStatus).toBe("ready"); }); @@ -77,9 +85,7 @@ test("can complete all the deferred registrations", async () => { const register2 = jest.fn(); const register3 = jest.fn(); - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => register1 }) @@ -98,7 +104,7 @@ test("can complete all the deferred registrations", async () => { { name: "Dummy-3" } ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(register1).toHaveBeenCalled(); expect(register2).toHaveBeenCalled(); @@ -118,17 +124,17 @@ test("when all the deferred registrations are completed, set the status to \"rea { name: "Dummy-3" } ], runtime); - expect(registry.registrationStatus).toBe("registered"); + expect(registry.registrationStatus).toBe("modules-registered"); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(registry.registrationStatus).toBe("ready"); }); test("when a deferred registration is asynchronous, the function can be awaited", async () => { - const loadRemote = jest.fn(); + let hasBeenCompleted = false; - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => () => {} }) @@ -145,15 +151,13 @@ test("when a deferred registration is asynchronous, the function can be awaited" const registry = new RemoteModuleRegistry(loadRemote); - let hasBeenCompleted = false; - await registry.registerModules([ { name: "Dummy-1" }, { name: "Dummy-2" }, { name: "Dummy-3" } ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(hasBeenCompleted).toBeTruthy(); }); @@ -162,9 +166,7 @@ test("when a deferred registration fail, complete the remaining deferred registr const register1 = jest.fn(); const register3 = jest.fn(); - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => register1 }) @@ -183,16 +185,14 @@ test("when a deferred registration fail, complete the remaining deferred registr { name: "Dummy-3" } ], runtime); - await registry.completeModuleRegistrations(runtime, {}); + await registry.registerDeferredRegistrations({}, runtime); expect(register1).toHaveBeenCalled(); expect(register3).toHaveBeenCalled(); }); test("when a deferred registration fail, return the error", async () => { - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => () => {} }) @@ -211,20 +211,53 @@ test("when a deferred registration fail, return the error", async () => { { name: "Dummy-3" } ], runtime); - const errors = await registry.completeModuleRegistrations(runtime, {}); + const errors = await registry.registerDeferredRegistrations({}, runtime); expect(errors.length).toBe(1); expect(errors[0]!.error!.toString()).toContain("Module 2 deferred registration failed"); }); -test("when data is provided, all the deferred registrations receive the data object", async () => { +test("all the deferred registrations receive the data object", async () => { const register1 = jest.fn(); const register2 = jest.fn(); const register3 = jest.fn(); - const loadRemote = jest.fn(); + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + const data = { + foo: "bar" + }; + + await registry.registerDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "register"); + expect(register2).toHaveBeenCalledWith(data, "register"); + expect(register3).toHaveBeenCalledWith(data, "register"); +}); + +test("all the deferred registrations receive \"register\" as state", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => register1 }) @@ -247,11 +280,11 @@ test("when data is provided, all the deferred registrations receive the data obj foo: "bar" }; - await registry.completeModuleRegistrations(runtime, data); + await registry.registerDeferredRegistrations(data, runtime); - expect(register1).toHaveBeenCalledWith(data); - expect(register2).toHaveBeenCalledWith(data); - expect(register3).toHaveBeenCalledWith(data); + expect(register1).toHaveBeenCalledWith(data, "register"); + expect(register2).toHaveBeenCalledWith(data, "register"); + expect(register3).toHaveBeenCalledWith(data, "register"); }); diff --git a/packages/module-federation/tests/registerRemoteModules.test.ts b/packages/module-federation/tests/registerRemoteModules.test.ts index a4f706799..c1489c927 100644 --- a/packages/module-federation/tests/registerRemoteModules.test.ts +++ b/packages/module-federation/tests/registerRemoteModules.test.ts @@ -17,6 +17,14 @@ class DummyRuntime extends Runtime { getNavigationItems() { return []; } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } } const runtime = new DummyRuntime(); @@ -26,9 +34,7 @@ test("can register all the modules", async () => { const register2 = jest.fn(); const register3 = jest.fn(); - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: register1 }) @@ -79,7 +85,7 @@ test("when there are no deferred registrations, once all the modules are registe expect(registry.registrationStatus).toBe("ready"); }); -test("when there are deferred registrations, once all the modules are registered, set the status to \"registered\"", async () => { +test("when there are deferred registrations, once all the modules are registered, set the status to \"modules-registered\"", async () => { const loadRemote = jest.fn().mockResolvedValue({ register: () => () => {} }); @@ -91,16 +97,14 @@ test("when there are deferred registrations, once all the modules are registered { name: "Dummy-2" } ], runtime); - expect(registry.registrationStatus).toBe("registered"); + expect(registry.registrationStatus).toBe("modules-registered"); }); test("when a module registration fail, register the remaining modules", async () => { const register1 = jest.fn(); const register3 = jest.fn(); - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: register1 }) @@ -124,9 +128,7 @@ test("when a module registration fail, register the remaining modules", async () }); test("when a module registration fail, return the error", async () => { - const loadRemote = jest.fn(); - - loadRemote + const loadRemote = jest.fn() .mockResolvedValueOnce({ register: () => {} }) @@ -148,3 +150,36 @@ test("when a module registration fail, return the error", async () => { expect(errors.length).toBe(1); expect(errors[0]!.error!.toString()).toContain("Module 2 registration failed"); }); + +test("when a context is provided, all the register functions receive the provided context", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: register1 + }) + .mockResolvedValueOnce({ + register: register2 + }) + .mockResolvedValueOnce({ + register: register3 + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + const context = { + foo: "bar" + }; + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime, { context }); + + expect(register1).toHaveBeenCalledWith(runtime, context); + expect(register2).toHaveBeenCalledWith(runtime, context); + expect(register3).toHaveBeenCalledWith(runtime, context); +}); diff --git a/packages/module-federation/tests/updateDeferredRegistrations.test.ts b/packages/module-federation/tests/updateDeferredRegistrations.test.ts new file mode 100644 index 000000000..ffdde1435 --- /dev/null +++ b/packages/module-federation/tests/updateDeferredRegistrations.test.ts @@ -0,0 +1,149 @@ +import { __setLocalModuleRegistry, LocalModuleRegistry, registerLocalModules, Runtime } from "@squide/core"; +import { registerDeferredRegistrations } from "../src/registerDeferredRegistrations.ts"; +import { __setRemoteModuleRegistry, registerRemoteModules, RemoteModuleRegistry } from "../src/registerRemoteModules.ts"; +import { updateDeferredRegistrations } from "../src/updateDeferredRegistrations.ts"; + +class DummyRuntime extends Runtime { + registerRoute() { + throw new Error("Method not implemented."); + } + + get routes() { + return []; + } + + registerNavigationItem() { + throw new Error("Method not implemented."); + } + + getNavigationItems() { + return []; + } + + startDeferredRegistrationScope(): void { + } + + completeDeferredRegistrationScope(): void { + } +} + +test("update local and remote deferred registrations", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + await registerDeferredRegistrations(data, runtime); + + const localRegistrationsSpy = jest.spyOn(localModuleRegistry, "updateDeferredRegistrations"); + const remoteRegistrationsSpy = jest.spyOn(remoteModuleRegistry, "updateDeferredRegistrations"); + + await updateDeferredRegistrations(data, runtime); + + expect(localRegistrationsSpy).toHaveBeenCalledWith(data, runtime); + expect(remoteRegistrationsSpy).toHaveBeenCalledWith(data, runtime); +}); + +test("start and complete a deferred registration scope", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + await registerDeferredRegistrations(data, runtime); + + const startScopeSpy = jest.spyOn(runtime, "startDeferredRegistrationScope"); + const completeScopeSpy = jest.spyOn(runtime, "completeDeferredRegistrationScope"); + + await updateDeferredRegistrations(data, runtime); + + expect(startScopeSpy).toHaveBeenCalledTimes(1); + expect(completeScopeSpy).toHaveBeenCalledTimes(1); +}); + +test("when an unmanaged error is thrown, complete the deferred registration scope", async () => { + const runtime = new DummyRuntime(); + + const localModuleRegistry = new LocalModuleRegistry(); + + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const remoteModuleRegistry = new RemoteModuleRegistry(loadRemote); + + __setLocalModuleRegistry(localModuleRegistry); + __setRemoteModuleRegistry(remoteModuleRegistry); + + await registerLocalModules([ + () => () => {} + ], runtime); + + await registerRemoteModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + const data = { + foo: "bar" + }; + + await registerDeferredRegistrations(data, runtime); + + jest.spyOn(localModuleRegistry, "updateDeferredRegistrations").mockImplementation(() => { + throw new Error("Something went wrong!"); + }); + + const completeScopeSpy = jest.spyOn(runtime, "completeDeferredRegistrationScope"); + + // Oddly, I can't get it to work with expect(() => {}).toThrow(); + try { + await updateDeferredRegistrations(data, runtime); + } catch (error: unknown) { + // .... + } + + expect(completeScopeSpy).toHaveBeenCalledTimes(1); +}); diff --git a/packages/module-federation/tests/updateRemoteModuleDeferredRegistrations.test.ts b/packages/module-federation/tests/updateRemoteModuleDeferredRegistrations.test.ts new file mode 100644 index 000000000..8899b5356 --- /dev/null +++ b/packages/module-federation/tests/updateRemoteModuleDeferredRegistrations.test.ts @@ -0,0 +1,309 @@ +import { Runtime } from "@squide/core"; +import { RemoteModuleRegistry } from "../src/registerRemoteModules.ts"; + +function simulateDelay(delay: number) { + return new Promise(resolve => { + setTimeout(() => { + resolve(undefined); + }, delay); + }); +} + +class DummyRuntime extends Runtime { + registerRoute() { + throw new Error("Method not implemented."); + } + + get routes() { + return []; + } + + registerNavigationItem() { + throw new Error("Method not implemented."); + } + + getNavigationItems() { + return []; + } + + startDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } + + completeDeferredRegistrationScope(): void { + throw new Error("Method not implemented."); + } +} + +const runtime = new DummyRuntime(); + +test("when called before registerLocalModules, throw an error", async () => { + const loadRemote = jest.fn(); + + const registry = new RemoteModuleRegistry(loadRemote); + + await expect(() => registry.updateDeferredRegistrations({}, runtime)).rejects.toThrow(/The updateDeferredRegistrations function can only be called once the remote modules are ready/); +}); + +test("when called before registerLocalModuleDeferredRegistrations, throw an error", async () => { + const loadRemote = jest.fn().mockResolvedValue({ + register: () => () => {} + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" } + ], runtime); + + await expect(() => registry.updateDeferredRegistrations({}, runtime)).rejects.toThrow(/The updateDeferredRegistrations function can only be called once the remote modules are ready/); +}); + +test("can update all the deferred registrations", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register2.mockReset(); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(register1).toHaveBeenCalled(); + expect(register2).toHaveBeenCalled(); + expect(register3).toHaveBeenCalled(); +}); + +test("when a deferred registration is asynchronous, the function can be awaited", async () => { + let hasBeenCompleted = false; + + const register1 = jest.fn(); + + const register2 = jest.fn() + // Do not wait on the "registerDeferredRegistrations" call + // but wait on the "updateDeferredRegistrations" call. + .mockImplementationOnce(() => {}) + .mockImplementationOnce(async () => { + await simulateDelay(10); + + hasBeenCompleted = true; + }); + + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(hasBeenCompleted).toBeTruthy(); +}); + +test("when a deferred registration fail, update the remaining deferred registrations", async () => { + const register1 = jest.fn(); + + const register2 = jest.fn() + // Do not wait on the "registerDeferredRegistrations" call + // but wait on the "updateDeferredRegistrations" call. + .mockImplementationOnce(() => {}) + .mockImplementationOnce(() => { + throw new Error("Module 2 registration failed"); + }); + + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register3.mockReset(); + + await registry.updateDeferredRegistrations({}, runtime); + + expect(register1).toHaveBeenCalled(); + expect(register3).toHaveBeenCalled(); +}); + +test("when a deferred registration fail, return the error", async () => { + const register1 = jest.fn(); + + const register2 = jest.fn() + // Do not wait on the "registerDeferredRegistrations" call + // but wait on the "updateDeferredRegistrations" call. + .mockImplementationOnce(() => {}) + .mockImplementationOnce(() => { + throw new Error("Module 2 registration failed"); + }); + + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + const errors = await registry.updateDeferredRegistrations({}, runtime); + + expect(errors.length).toBe(1); + expect(errors[0]!.error!.toString()).toContain("Module 2 registration failed"); +}); + +test("all the deferred module registrations receive the data object", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register3.mockReset(); + + const data = { + foo: "bar" + }; + + await registry.updateDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "update"); + expect(register2).toHaveBeenCalledWith(data, "update"); + expect(register3).toHaveBeenCalledWith(data, "update"); +}); + +test("all the deferred module registrations receive \"update\" as state", async () => { + const register1 = jest.fn(); + const register2 = jest.fn(); + const register3 = jest.fn(); + + const loadRemote = jest.fn() + .mockResolvedValueOnce({ + register: () => register1 + }) + .mockResolvedValueOnce({ + register: () => register2 + }) + .mockResolvedValueOnce({ + register: () => register3 + }); + + const registry = new RemoteModuleRegistry(loadRemote); + + await registry.registerModules([ + { name: "Dummy-1" }, + { name: "Dummy-2" }, + { name: "Dummy-3" } + ], runtime); + + await registry.registerDeferredRegistrations({}, runtime); + + register1.mockReset(); + register2.mockReset(); + register3.mockReset(); + + const data = { + foo: "bar" + }; + + await registry.updateDeferredRegistrations(data, runtime); + + expect(register1).toHaveBeenCalledWith(data, "update"); + expect(register2).toHaveBeenCalledWith(data, "update"); + expect(register3).toHaveBeenCalledWith(data, "update"); +}); diff --git a/packages/msw/package.json b/packages/msw/package.json index ecc754b97..40453000f 100644 --- a/packages/msw/package.json +++ b/packages/msw/package.json @@ -41,17 +41,17 @@ } }, "devDependencies": { - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "msw": "2.2.14", + "msw": "2.3.1", "react": "18.3.1", "react-dom": "18.3.1", - "tsup": "8.0.2", - "typescript": "5.4.5" + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "@squide/core": "workspace:*" diff --git a/packages/msw/src/index.ts b/packages/msw/src/index.ts index e4bca0fe9..5ffef7b88 100644 --- a/packages/msw/src/index.ts +++ b/packages/msw/src/index.ts @@ -1,5 +1,4 @@ export * from "./mswPlugin.ts"; export * from "./mswState.ts"; export * from "./requestHandlerRegistry.ts"; -export * from "./useIsMswStarted.ts"; diff --git a/packages/msw/src/mswPlugin.ts b/packages/msw/src/mswPlugin.ts index 9c58be6cd..8b7cbf26c 100644 --- a/packages/msw/src/mswPlugin.ts +++ b/packages/msw/src/mswPlugin.ts @@ -3,22 +3,16 @@ import type { RequestHandler } from "msw"; import { RequestHandlerRegistry } from "./requestHandlerRegistry.ts"; export class MswPlugin extends Plugin { - #runtime?: Runtime; - readonly #requestHandlerRegistry = new RequestHandlerRegistry(); - constructor() { - super(MswPlugin.name); - } - - _setRuntime(runtime: Runtime) { - this.#runtime = runtime; + constructor(runtime: Runtime) { + super(MswPlugin.name, runtime); } registerRequestHandlers(handlers: RequestHandler[]) { this.#requestHandlerRegistry.add(handlers); - this.#runtime?.logger.debug("[squide] The following MSW request handlers has been registered: ", handlers); + this._runtime.logger.debug("[squide] The following MSW request handlers has been registered: ", handlers); } get requestHandlers(): RequestHandler[] { diff --git a/packages/msw/src/mswState.ts b/packages/msw/src/mswState.ts index 71bd59bba..a599fb07c 100644 --- a/packages/msw/src/mswState.ts +++ b/packages/msw/src/mswState.ts @@ -1,7 +1,7 @@ export type MswStateChangedListener = () => void; export class MswState { - #isStarted = false; + #isReady = false; readonly #stateChangedListeners = new Set(); @@ -13,9 +13,9 @@ export class MswState { this.#stateChangedListeners.delete(callback); } - setAsStarted() { - if (!this.#isStarted) { - this.#isStarted = true; + setAsReady() { + if (!this.#isReady) { + this.#isReady = true; this.#stateChangedListeners.forEach(x => { x(); @@ -23,35 +23,38 @@ export class MswState { } } - get isStarted() { - return this.#isStarted; + get isReady() { + return this.#isReady; } +} + +let mswState: MswState; - // Strictly for Jest tests, this is NOT ideal. - _reset() { - this.#isStarted = false; +function getMswState() { + if (!mswState) { + mswState = new MswState(); } + + return mswState; } -const mswState = new MswState(); +// This function should only be used by tests. +export function __setMswState(state: MswState) { + mswState = state; +} -export function setMswAsStarted() { - mswState.setAsStarted(); +export function setMswAsReady() { + getMswState().setAsReady(); } -export function isMswStarted() { - return mswState.isStarted; +export function isMswReady() { + return getMswState().isReady; } export function addMswStateChangedListener(callback: MswStateChangedListener) { - mswState.addStateChangedListener(callback); + getMswState().addStateChangedListener(callback); } export function removeMswStateChangedListener(callback: MswStateChangedListener) { - mswState.removeStateChangedListener(callback); -} - -// Strictly for Jest tests, this is NOT ideal. -export function __resetMswStatus() { - mswState._reset(); + getMswState().removeStateChangedListener(callback); } diff --git a/packages/msw/src/requestHandlerRegistry.ts b/packages/msw/src/requestHandlerRegistry.ts index b01954cd5..e9721fdb3 100644 --- a/packages/msw/src/requestHandlerRegistry.ts +++ b/packages/msw/src/requestHandlerRegistry.ts @@ -1,11 +1,11 @@ import type { RequestHandler } from "msw"; -import { isMswStarted } from "./mswState.ts"; +import { isMswReady } from "./mswState.ts"; export class RequestHandlerRegistry { readonly #handlers: RequestHandler[] = []; add(handlers: RequestHandler[]) { - if (isMswStarted()) { + if (isMswReady()) { throw new Error("[squide] MSW request handlers cannot be registered once MSW is started. Did you defer the registration of a MSW request handler?"); } diff --git a/packages/msw/src/useIsMswStarted.ts b/packages/msw/src/useIsMswStarted.ts deleted file mode 100644 index f88717e6f..000000000 --- a/packages/msw/src/useIsMswStarted.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useLogOnceLogger } from "@squide/core"; -import { useEffect, useSyncExternalStore } from "react"; -import { addMswStateChangedListener, isMswStarted, removeMswStateChangedListener } from "./mswState.ts"; - -function subscribe(callback: () => void) { - addMswStateChangedListener(callback); - - return () => removeMswStateChangedListener(callback); -} - -export function useIsMswStarted(enabled: boolean) { - const isStarted = useSyncExternalStore(subscribe, isMswStarted); - - const logger = useLogOnceLogger(); - - useEffect(() => { - if (isStarted) { - // Adding a guard to log once so React strict mode doesn't mess up with the logs when in development. - logger.debugOnce("msw-is-started", "[squide] %cMSW is ready%c.", "color: white; background-color: green;", ""); - } - }, [isStarted, logger]); - - return isStarted || !enabled; -} diff --git a/packages/react-router/jest.config.ts b/packages/react-router/jest.config.ts index 8e3354ec7..ad75f0386 100644 --- a/packages/react-router/jest.config.ts +++ b/packages/react-router/jest.config.ts @@ -8,6 +8,9 @@ const config: Config = { transform: { "^.+\\.(js|ts|tsx)$": ["@swc/jest", swcConfig as Record] }, + transformIgnorePatterns: [ + "node_modules/(?!.pnpm|memoize|mimic-function)" + ], moduleNameMapper: { ...pathsToModuleNameMapper(compilerOptions.paths, { prefix: "" diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 2ec56921a..4381da0c3 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -36,11 +36,11 @@ "react-router-dom": "*" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", - "@testing-library/react": "15.0.5", + "@testing-library/react": "16.0.0", "@types/jest": "29.5.12", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@types/react-test-renderer": "18.3.0", "@workleap/eslint-plugin": "3.2.2", @@ -52,14 +52,15 @@ "jest-environment-jsdom": "29.7.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-router-dom": "6.23.0", + "react-router-dom": "6.25.1", "react-test-renderer": "18.3.1", - "ts-jest": "29.1.2", - "tsup": "8.0.2", - "typescript": "5.4.5" + "ts-jest": "29.2.3", + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { - "@squide/core": "workspace:*" + "@squide/core": "workspace:*", + "memoize": "10.0.0" }, "sideEffects": false, "engines": { diff --git a/packages/react-router/src/index.ts b/packages/react-router/src/index.ts index 8021a1256..d790f1d1d 100644 --- a/packages/react-router/src/index.ts +++ b/packages/react-router/src/index.ts @@ -5,8 +5,8 @@ export * from "./reactRouterRuntime.ts"; export * from "./resolveRouteSegments.ts"; export * from "./routeRegistry.ts"; export * from "./useIsRouteProtected.ts"; -export * from "./useNavigationItems.ts"; export * from "./useRenderedNavigationItems.tsx"; export * from "./useRouteMatch.ts"; export * from "./useRoutes.ts"; +export * from "./useRuntimeNavigationItems.ts"; diff --git a/packages/react-router/src/navigationItemRegistry.ts b/packages/react-router/src/navigationItemRegistry.ts index 330b67b2e..55a035d12 100644 --- a/packages/react-router/src/navigationItemRegistry.ts +++ b/packages/react-router/src/navigationItemRegistry.ts @@ -1,16 +1,21 @@ import { isNil } from "@squide/core"; +import memoize, { memoizeClear } from "memoize"; import type { ReactNode } from "react"; import type { LinkProps } from "react-router-dom"; export interface NavigationLink extends Omit { + $key?: string; $label: ReactNode; $additionalProps?: Record; + $canRender?: (obj?: unknown) => boolean; children?: never; } export interface NavigationSection { + $key?: string; $label: ReactNode; $additionalProps?: Record; + $canRender?: (obj?: unknown) => boolean; children: NavigationItem[]; to?: never; } @@ -27,20 +32,113 @@ export type RootNavigationItem = NavigationItem & { $priority?: number; }; +export type NavigationItemRegistrationType = "static" | "deferred"; + +export interface RegistryItem { + menuId: string; + registrationType: NavigationItemRegistrationType; + item: RootNavigationItem; +} + +export class NavigationItemDeferredRegistrationScope { + readonly _registry: NavigationItemRegistry; + + constructor(registry: NavigationItemRegistry) { + this._registry = registry; + } + + addItem(menuId: string, navigationItem: RootNavigationItem) { + this._registry.add(menuId, "deferred", navigationItem); + } + + getItems(menuId: string) { + return this._registry.getItems(menuId); + } + + complete() {} +} + +export class NavigationItemDeferredRegistrationTransactionalScope extends NavigationItemDeferredRegistrationScope { + readonly #activeItemsIndex: Map = new Map(); + + addItem(menuId: string, navigationItem: RootNavigationItem) { + this.#activeItemsIndex.set(menuId, [ + ...(this.#activeItemsIndex.get(menuId) ?? []), + { + menuId, + registrationType: "deferred", + item: navigationItem + } + ]); + } + + getItems(menuId: string) { + return this.#activeItemsIndex.get(menuId)?.map(x => x.item) ?? []; + } + + complete() { + this._registry.clearDeferredItems(); + + this.#activeItemsIndex.forEach(items => { + items.forEach(x => { + this._registry.add(x.menuId, x.registrationType, x.item); + }); + }); + + this.#activeItemsIndex.clear(); + } +} + export class NavigationItemRegistry { - readonly #menus: Map = new Map(); + // + readonly #menusIndex: Map = new Map(); + + // Since the "getItems" function is transforming the menus items from registry items to navigation items, the result of + // the transformation is memoized to ensure the returned array is immutable and can be use in React closures. + readonly #memoizedGetItems = memoize((menuId: string) => this.#menusIndex.get(menuId)?.map(x => x.item) ?? []); + + #setItems(menuId: string, items: RegistryItem[]) { + this.#menusIndex.set(menuId, items); - add(menuId: string, navigationItem: RootNavigationItem) { + memoizeClear(this.#memoizedGetItems); + } + + add(menuId: string, registrationType: NavigationItemRegistrationType, navigationItem: RootNavigationItem) { // Create a new array so the navigation items array is immutable. const items = [ - ...(this.#menus.get(menuId) ?? []), - navigationItem + ...(this.#menusIndex.get(menuId) ?? []), + { + menuId, + registrationType, + item: navigationItem + } ]; - this.#menus.set(menuId, items); + this.#setItems(menuId, items); } getItems(menuId: string) { - return this.#menus.get(menuId); + return this.#memoizedGetItems(menuId); + } + + clearDeferredItems() { + const keys = this.#menusIndex.keys(); + + // eslint-disable-next-line no-constant-condition + while (true) { + const next = keys.next(); + + if (next.done) { + break; + } + + const key = next.value; + const registryItems = this.#menusIndex.get(key)!; + + // Keep the "getItems" function immutable by only updating the menu arrays if the items actually changed. + if (registryItems.some(x => x.registrationType === "deferred")) { + this.#setItems(key, registryItems.filter(x => x.registrationType !== "deferred")); + } + } } } diff --git a/packages/react-router/src/reactRouterRuntime.ts b/packages/react-router/src/reactRouterRuntime.ts index a1e209491..e5e01905a 100644 --- a/packages/react-router/src/reactRouterRuntime.ts +++ b/packages/react-router/src/reactRouterRuntime.ts @@ -1,6 +1,6 @@ import { RootMenuId, Runtime, type RegisterNavigationItemOptions, type RegisterRouteOptions } from "@squide/core"; -import { NavigationItemRegistry, type RootNavigationItem } from "./navigationItemRegistry.ts"; -import { ManagedRoutes, ManagedRoutesOutletName } from "./outlets.ts"; +import { NavigationItemDeferredRegistrationScope, NavigationItemDeferredRegistrationTransactionalScope, NavigationItemRegistry, type RootNavigationItem } from "./navigationItemRegistry.ts"; +import { ManagedRoutesOutletName } from "./outlets.ts"; import { RouteRegistry, type Route } from "./routeRegistry.ts"; function translateManagedRoutesParentId(parentId?: string) { @@ -14,6 +14,30 @@ function translateManagedRoutesParentId(parentId?: string) { export class ReactRouterRuntime extends Runtime { readonly #routeRegistry = new RouteRegistry(); readonly #navigationItemRegistry = new NavigationItemRegistry(); + #navigationItemScope?: NavigationItemDeferredRegistrationScope; + + startDeferredRegistrationScope(transactional: boolean = false) { + if (this.#navigationItemScope) { + throw new Error("[squide] Cannot start a new deferred registration scope when there's already an active scope. Did you forget to complete the previous scope?"); + } + + if (transactional) { + this.#navigationItemScope = new NavigationItemDeferredRegistrationTransactionalScope(this.#navigationItemRegistry); + } else { + this.#navigationItemScope = new NavigationItemDeferredRegistrationScope(this.#navigationItemRegistry); + } + } + + completeDeferredRegistrationScope() { + if (!this.#navigationItemScope) { + throw new Error("[squide] A deferred registration scope must be started before calling the complete function. Did you forget to start the scope?"); + } + + if (this.#navigationItemScope) { + this.#navigationItemScope.complete(); + this.#navigationItemScope = undefined; + } + } registerRoute(route: Route, options: RegisterRouteOptions = {}) { const result = this.#routeRegistry.add(route, options); @@ -25,8 +49,7 @@ export class ReactRouterRuntime extends Runtime { this._logger.debug( `[squide] The following route has been %cregistered%c${parentLog}.`, "color: white; background-color: green;", "%s", - "Newly registered item:", - route, + "Newly registered item:", route, "All registered routes:", this.#routeRegistry.routes ); @@ -51,52 +74,62 @@ export class ReactRouterRuntime extends Runtime { } registerNavigationItem(navigationItem: RootNavigationItem, { menuId = RootMenuId }: RegisterNavigationItemOptions = {}) { - this.#navigationItemRegistry.add(menuId, navigationItem); + if (this.#navigationItemScope) { + this.#navigationItemScope.addItem(menuId, navigationItem); - const items = this.#navigationItemRegistry.getItems(menuId)!; + const items = this.#navigationItemScope.getItems(menuId)!; - this._logger.debug( - `[squide] The following navigation item has been %cregistered%c to the "${menuId}" menu for a total of ${items.length} item${items.length !== 1 ? "s" : ""}.`, "color: white; background-color: green;", "%s", - "Newly registered item:", navigationItem, - "All registered items:", this.#navigationItemRegistry.getItems(menuId) - ); + this._logger.debug( + `[squide] The following deferred navigation item has been %cregistered%c to the "${menuId}" menu for a total of ${items.length} deferred item${items.length !== 1 ? "s" : ""}.`, "color: white; background-color: green;", "%s", + "Newly registered item:", navigationItem, + "All registered items:", items + ); + } else { + this.#navigationItemRegistry.add(menuId, "static", navigationItem); + + const items = this.#navigationItemRegistry.getItems(menuId)!; + + this._logger.debug( + `[squide] The following static navigation item has been %cregistered%c to the "${menuId}" menu for a total of ${items.length} static item${items.length !== 1 ? "s" : ""}.`, "color: white; background-color: green;", "%s", + "Newly registered item:", navigationItem, + "All registered items:", items + ); + } } getNavigationItems(menuId: string = RootMenuId) { - return this.#navigationItemRegistry.getItems(menuId) ?? []; + return this.#navigationItemRegistry.getItems(menuId); } - _completeRegistration() { - const pendingRegistrations = this.#routeRegistry.pendingRegistrations; + _validateRegistrations() { + const pendingRegistrations = this.#routeRegistry.getPendingRegistrations(); + const pendingRoutes = pendingRegistrations.getPendingRouteIds(); - if (pendingRegistrations.size > 0) { - if (pendingRegistrations.has(ManagedRoutes.$name!)) { - // eslint-disable-next-line max-len - throw new Error("[squide] The ManagedRoutes placeholder is missing from the router configuration. The ManagedRoutes placeholder must be defined as a children of an hoisted route. Did you include a ManagedRoutes placeholder and hoist the ManagedRoutes placeholder's parent route?"); + if (pendingRoutes.length > 0) { + if (pendingRegistrations.isManagedRoutesOutletPending()) { + throw new Error("[squide] The ManagedRoutes outlet is missing from the router configuration. The ManagedRoutes outlet must be defined as a children of an hoisted route. Did you include a ManagedRoutes outlet and hoist the ManagedRoutes outlet's parent route?"); } - let message = `[squide] ${pendingRegistrations.size} parent route${pendingRegistrations.size !== 1 ? "s" : ""} were expected to be registered but ${pendingRegistrations.size !== 0 ? "are" : "is"} missing:\r\n\r\n`; - let index = 0; - - // It's easier to use for ... of with a Map object. - for (const [parentId, nestedRoutes] of pendingRegistrations) { - index++; + let message = `[squide] ${pendingRoutes.length} route${pendingRoutes.length !== 1 ? "s were" : " is"} expected to be registered but ${pendingRoutes.length !== 1 ? "are" : "is"} missing:\r\n\r\n`; - message += `${index}/${pendingRegistrations.size} Missing parent route with the following path or name: "${parentId}"\r\n`; + pendingRoutes.forEach((x, index) => { + message += `${index}/${pendingRoutes.length} Missing route with the following path or name: "${x}"\r\n`; message += " Pending registrations:\r\n"; - for (const x of nestedRoutes) { - message += ` - "${x.path ?? x.$name ?? "(no identifier)"}"\r\n`; - } + const nestedPendingRegistrations = pendingRegistrations.getPendingRegistrationsForRoute(x); + + nestedPendingRegistrations.forEach(y => { + message += ` - "${y.path ?? y.$name ?? "(no identifier)"}"\r\n`; + }); message += "\r\n"; - } + }); - message += `If you are certain that the parent route${pendingRegistrations.size !== 1 ? "s" : ""} has been registered, make sure that the following conditions are met:\r\n`; - message += "- The missing parent routes \"path\" or \"name\" property perfectly match the provided \"parentPath\" or \"parentName\" (make sure that there's no leading or trailing \"/\" that differs).\r\n"; - message += "- The missing parent routes has been registered with the runtime.registerRoute function. A route cannot be registered under a parent route that has not be registered with the runtime.registerRoute function.\r\n"; + message += `If you are certain that the route${pendingRoutes.length !== 1 ? "s" : ""} has been registered, make sure that the following conditions are met:\r\n`; + message += "- The missing routes \"path\" or \"name\" property perfectly match the provided \"parentPath\" or \"parentName\" (make sure that there's no leading or trailing \"/\" that differs).\r\n"; + message += "- The missing routes has been registered with the runtime.registerRoute function. A route cannot be registered under a parent route that has not be registered with the runtime.registerRoute function.\r\n"; message += "For more information about nested routes, refers to https://gsoft-inc.github.io/wl-squide/reference/runtime/runtime-class/#register-nested-routes-under-an-existing-route.\r\n"; - message += "For more information about the ManagedRoutes placeholder, refers to https://gsoft-inc.github.io/wl-squide/reference/routing/managedroutes."; + message += "For more information about the ManagedRoutes outlet, refers to https://gsoft-inc.github.io/wl-squide/reference/routing/managedroutes."; if (this._mode === "development") { throw new Error(message); @@ -105,6 +138,6 @@ export class ReactRouterRuntime extends Runtime { } } - super._completeRegistration(); + super._validateRegistrations(); } } diff --git a/packages/react-router/src/routeRegistry.ts b/packages/react-router/src/routeRegistry.ts index fcc5d031c..819c6da45 100644 --- a/packages/react-router/src/routeRegistry.ts +++ b/packages/react-router/src/routeRegistry.ts @@ -1,6 +1,6 @@ import type { RegisterRouteOptions } from "@squide/core"; import type { IndexRouteObject, NonIndexRouteObject } from "react-router-dom"; -import { ManagedRoutesOutletName, isManagedRoutesOutletRoute } from "./outlets.ts"; +import { ManagedRoutes, ManagedRoutesOutletName, isManagedRoutesOutletRoute } from "./outlets.ts"; export type RouteVisibility = "public" | "protected"; @@ -45,21 +45,16 @@ export function createIndexKey(route: Route) { return undefined; } - export class RouteRegistry { - #routes: Route[]; + #routes: Route[] = []; - // Using an index to speed up the look up of parent routes. + // An index to speed up the look up of parent routes. // readonly #routesIndex: Map = new Map(); - // A collection of pending routes to registered once their layout is registered. + // An index of pending routes to registered once their parent is registered. // - readonly #pendingRegistrations: Map = new Map(); - - constructor() { - this.#routes = []; - } + readonly #pendingRegistrationsIndex: Map = new Map(); #addIndex(route: Route) { const key = createIndexKey(route); @@ -91,7 +86,6 @@ export class RouteRegistry { const result = this.#recursivelyAddRoutes(route.children); route.children = result.newRoutes; - completedPendingRegistrations.push(...result.completedPendingRegistrations); } @@ -103,7 +97,6 @@ export class RouteRegistry { // of the route). if (indexKey) { const pendingRegistrations = this.#tryRegisterPendingRoutes(indexKey); - completedPendingRegistrations.unshift(...pendingRegistrations); } @@ -117,7 +110,7 @@ export class RouteRegistry { } #tryRegisterPendingRoutes(parentId: string) { - const pendingRegistrations = this.#pendingRegistrations.get(parentId); + const pendingRegistrations = this.#pendingRegistrationsIndex.get(parentId); if (pendingRegistrations) { // Try to register the pending routes. @@ -125,7 +118,7 @@ export class RouteRegistry { if (registrationStatus === "registered") { // Remove the pending registrations. - this.#pendingRegistrations.delete(parentId); + this.#pendingRegistrationsIndex.delete(parentId); return pendingRegistrations; } @@ -191,12 +184,12 @@ export class RouteRegistry { const layoutRoute = this.#routesIndex.get(parentId); if (!layoutRoute) { - const pendingRegistration = this.#pendingRegistrations.get(parentId); + const pendingRegistration = this.#pendingRegistrationsIndex.get(parentId); if (pendingRegistration) { pendingRegistration.push(...routes); } else { - this.#pendingRegistrations.set(parentId, [...routes]); + this.#pendingRegistrationsIndex.set(parentId, [...routes]); } return { @@ -229,7 +222,27 @@ export class RouteRegistry { return this.#routes; } - get pendingRegistrations() { - return this.#pendingRegistrations; + getPendingRegistrations() { + return new PendingRegistrations(this.#pendingRegistrationsIndex); + } +} + +export class PendingRegistrations { + readonly #pendingRegistrationsIndex: Map = new Map(); + + constructor(pendingRegistrationsIndex: Map = new Map()) { + this.#pendingRegistrationsIndex = pendingRegistrationsIndex; + } + + getPendingRouteIds() { + return Array.from(this.#pendingRegistrationsIndex.keys()); + } + + getPendingRegistrationsForRoute(parentId: string) { + return this.#pendingRegistrationsIndex.get(parentId) ?? []; + } + + isManagedRoutesOutletPending() { + return this.#pendingRegistrationsIndex.has(ManagedRoutes.$name!); } } diff --git a/packages/react-router/src/useIsRouteProtected.ts b/packages/react-router/src/useIsRouteProtected.ts index 0d2c8db11..15d11f340 100644 --- a/packages/react-router/src/useIsRouteProtected.ts +++ b/packages/react-router/src/useIsRouteProtected.ts @@ -2,21 +2,6 @@ import type { Route } from "./routeRegistry.ts"; export function useIsRouteProtected(route?: Route) { if (!route) { - // HACK: - // An unregistrered route is considered as "protected" by default to facilitate the implementation of deferred routes. - // The issue is that when there's a direct hit on a deferred route, it cannot be determined whether or not a deferred route is public or protected - // because the deferred route hasn't been registered yet (since it's a deferred route). - // If that deferred route depends on protected data, if we don't return "true" here, the deferred route will be registered before the protected data - // is loaded which will probably cause a runtime error. - return true; - } - - if (route.path === "*") { - // HACK: - // With the current AppRouter component implementation, when there's a direct hit to a deferred route, since the route has not been registered yet to - // the React Router router instance, the router is trying to render the no match route. Therefore this hook returns the a boolean value based - // on the visibility status of the no match route instead of the actual page request by the user. - // To circumvent this issue, "true" is returned for the no match route. return true; } diff --git a/packages/react-router/src/useRenderedNavigationItems.tsx b/packages/react-router/src/useRenderedNavigationItems.tsx index 5927f87ac..a0159e5d6 100644 --- a/packages/react-router/src/useRenderedNavigationItems.tsx +++ b/packages/react-router/src/useRenderedNavigationItems.tsx @@ -7,12 +7,14 @@ export interface NavigationLinkRenderProps { label: ReactNode; linkProps: Omit; additionalProps: Record; + canRender?: (obj?: unknown) => boolean; } export interface NavigationSectionRenderProps { label: ReactNode; section: ReactNode; additionalProps: Record; + canRender?: (obj?: unknown) => boolean; } export type NavigationItemRenderProps = NavigationLinkRenderProps | NavigationSectionRenderProps; @@ -21,42 +23,60 @@ export function isNavigationLink(item: NavigationItemRenderProps): item is Navig return !isNil((item as NavigationLinkRenderProps).linkProps); } -export type RenderItemFunction = (item: NavigationItemRenderProps, index: number, level: number) => ReactNode; +export type RenderItemFunction = (item: NavigationItemRenderProps, key: string, index: number, level: number) => ReactNode; -export type RenderSectionFunction = (elements: ReactNode[], index: number, level: number) => ReactNode; +export type RenderSectionFunction = (elements: ReactNode[], key: string, index: number, level: number) => ReactNode; -function toLinkProps({ $label, $additionalProps, ...linkProps }: NavigationLink): NavigationLinkRenderProps { +function toLinkProps({ + // Explicitly omitted because the "$key" prop shouldn't be used by the consumer. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + $key, + $label, + $additionalProps, + $canRender, + // All the remaining props that belongs to the react-router Link component. + ...linkProps +}: NavigationLink): NavigationLinkRenderProps { return { label: $label, linkProps, - additionalProps: $additionalProps ?? {} + additionalProps: $additionalProps ?? {}, + canRender: $canRender }; } -function toMenuProps({ $label, $additionalProps }: NavigationSection, sectionElement: ReactNode): NavigationSectionRenderProps { +function toMenuProps({ $label, $additionalProps, $canRender }: NavigationSection, sectionElement: ReactNode): NavigationSectionRenderProps { return { label: $label, section: sectionElement, - additionalProps: $additionalProps ?? {} + additionalProps: $additionalProps ?? {}, + canRender: $canRender }; } -function renderItems(items: NavigationItem[], renderItem: RenderItemFunction, renderSection: RenderSectionFunction, index: number, level: number) { +function renderItems(items: NavigationItem[], renderItem: RenderItemFunction, renderSection: RenderSectionFunction, key: string, index: number, level: number) { const itemElements = items.map((x, itemIndex) => { let itemElement: ReactNode; if (isLinkItem(x)) { - itemElement = renderItem(toLinkProps(x), itemIndex, level); + itemElement = renderItem(toLinkProps(x), x.$key ?? `${itemIndex}-${level}`, itemIndex, level); } else { - const sectionElement = renderItems(x.children, renderItem, renderSection, 0, level + 1); + const sectionIndex = 0; + const sectionLevel = level + 1; + const sectionElement = renderItems(x.children, renderItem, renderSection, x.$key ?? `${sectionIndex}-${sectionLevel}`, sectionIndex, sectionLevel); - itemElement = renderItem(toMenuProps(x, sectionElement), itemIndex, level); + itemElement = renderItem(toMenuProps(x, sectionElement), x.$key ?? `${itemIndex}-${level}`, itemIndex, level); } return itemElement; }); - return renderSection(itemElements, index, level); + // Filter out elements that are null or undefined because of the "canRender" prop. + const renderedElements = itemElements.filter(x => x); + + if (renderedElements.length > 0) { + return renderSection(renderedElements, key ?? `${index}-${level}`, index, level); + } } export function useRenderedNavigationItems( @@ -82,6 +102,6 @@ export function useRenderedNavigationItems( // eslint-disable-next-line @typescript-eslint/no-unused-vars .map(({ $priority, ...itemProps }) => itemProps); - return renderItems(sortedItems, renderItem, renderSection, 0, 0); + return renderItems(sortedItems, renderItem, renderSection, "root", 0, 0); }, [navigationItems, renderItem, renderSection]); } diff --git a/packages/react-router/src/useRouteMatch.ts b/packages/react-router/src/useRouteMatch.ts index deee0c3f0..1ea2e2a97 100644 --- a/packages/react-router/src/useRouteMatch.ts +++ b/packages/react-router/src/useRouteMatch.ts @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { matchRoutes } from "react-router-dom"; import { useRoutes } from "./useRoutes.ts"; @@ -8,17 +9,19 @@ export interface UseRouteMatchOptions { export function useRouteMatch(locationArg: Partial, { throwWhenThereIsNoMatch = true }: UseRouteMatchOptions = {}) { const routes = useRoutes(); - const matchingRoutes = matchRoutes(routes, locationArg) ?? []; + return useMemo(() => { + const matchingRoutes = matchRoutes(routes, locationArg) ?? []; - if (matchingRoutes.length > 0) { - // When a route is nested, it also returns all the parts that constituate the whole route (for example the layouts and the boundaries). - // We only want to know the visiblity of the actual route that has been requested, which is always the last entry. - return matchingRoutes[matchingRoutes.length - 1]!.route; - } else { - if (throwWhenThereIsNoMatch) { - throw new Error(`[squide] There's no matching route for the location: "${locationArg.pathname}". Did you add routes to React Router without using the runtime.registerRoute() function?`); + if (matchingRoutes.length > 0) { + // When a route is nested, it also returns all the parts that constituate the whole route (for example the layouts and the boundaries). + // We only want to know the visiblity of the actual route that has been requested, which is always the last entry. + return matchingRoutes[matchingRoutes.length - 1]!.route; + } else { + if (throwWhenThereIsNoMatch) { + throw new Error(`[squide] There's no matching route for the location: "${locationArg.pathname}". Did you add routes to React Router without using the runtime.registerRoute() function?`); + } } - } - return undefined; + return undefined; + }, [locationArg, routes, throwWhenThereIsNoMatch]); } diff --git a/packages/react-router/src/useNavigationItems.ts b/packages/react-router/src/useRuntimeNavigationItems.ts similarity index 52% rename from packages/react-router/src/useNavigationItems.ts rename to packages/react-router/src/useRuntimeNavigationItems.ts index 91fd8547a..3a0216014 100644 --- a/packages/react-router/src/useNavigationItems.ts +++ b/packages/react-router/src/useRuntimeNavigationItems.ts @@ -5,7 +5,9 @@ export interface UseNavigationItemsOptions { menuId?: string; } -export function useNavigationItems({ menuId }: UseNavigationItemsOptions = {}) { +// This hook has been renamed from useNavigationItems to useRuntimeNavigationItems to free up the name for the +// use useNavigationItems hook of the @squide/firefly package. +export function useRuntimeNavigationItems({ menuId }: UseNavigationItemsOptions = {}) { const runtime = useRuntime() as ReactRouterRuntime; return runtime.getNavigationItems(menuId); diff --git a/packages/react-router/tests/__snapshots__/useRenderedNavigationItems.test.tsx.snap b/packages/react-router/tests/__snapshots__/useRenderedNavigationItems.test.tsx.snap index 001630178..dc6592dee 100644 --- a/packages/react-router/tests/__snapshots__/useRenderedNavigationItems.test.tsx.snap +++ b/packages/react-router/tests/__snapshots__/useRenderedNavigationItems.test.tsx.snap @@ -1,110 +1,174 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Link item additionalProps are rendered 1`] = ` -
              +exports[`highest priority goes first 1`] = ` +
              • - Foo + Toto
              • -
              • +
              • Bar
              • +
              • +
                + Foo +
                +
              • +
              • +
                + Tutu +
                +
              `; -exports[`Section item additionalProps are rendered 1`] = ` -
                +exports[`link item additionalProps are rendered 1`] = ` +
                • - Foo -
                    -
                  • -
                    - Bar -
                    -
                  • -
                  -
                • -
                -`; - -exports[`highest priority goes first 1`] = ` -
                  -
                • - Toto + Foo
                • -
                • +
                • Bar
                • -
                • +
                +`; + +exports[`link item custom keys are rendered 1`] = ` +
                  +
                • Foo
                • -
                • +
                • - Tutu + Bar
                `; exports[`negative priority goes last 1`] = ` -
                  -
                • +
                    +
                  • Foo
                  • -
                  • +
                  • Bar
                  • -
                  • +
                  • Tutu
                  • -
                  • +
                  • @@ -114,26 +178,164 @@ exports[`negative priority goes last 1`] = `
                  `; +exports[`nested item custom keys are rendered 1`] = ` +
                    +
                  • + Foo +
                      +
                    • +
                      + Bar +
                      +
                    • +
                    +
                  • +
                  +`; + +exports[`section item additionalProps are rendered 1`] = ` +
                    +
                  • + Foo +
                      +
                    • +
                      + Bar +
                      +
                    • +
                    +
                  • +
                  +`; + +exports[`section item custom keys are rendered 1`] = ` +
                    +
                  • + Foo +
                      +
                    • +
                      + Bar +
                      +
                    • +
                    +
                  • +
                  +`; + exports[`support 2 section levels 1`] = ` -
                    -
                  • +
                      +
                    • Foo
                    • -
                    • +
                    • Bar -
                        -
                      • +
                          +
                        • Toto
                        • -
                        • +
                        • @@ -146,28 +348,60 @@ exports[`support 2 section levels 1`] = ` `; exports[`support 3 section levels 1`] = ` -
                            -
                          • +
                              +
                            • Foo
                            • -
                            • +
                            • Bar -
                                -
                              • +
                                  +
                                • Toto
                                • -
                                • +
                                • Tutu -
                                    -
                                  • +
                                      +
                                    • @@ -180,3 +414,81 @@ exports[`support 3 section levels 1`] = `
                                    `; + +exports[`when a link item canRender prop return false, the item is not rendered 1`] = ` +
                                      +
                                    • +
                                      + Bar +
                                      +
                                    • +
                                    +`; + +exports[`when a section item canRender prop return false, the item is not rendered 1`] = ` +
                                      +
                                    • +
                                      + acme +
                                      +
                                    • +
                                    +`; + +exports[`when the canRender prop of all the items of a nested section return false, do not render the section 1`] = ` +
                                      +
                                    • + Foo +
                                    • +
                                    • + John +
                                        +
                                      • + Doe +
                                      • +
                                      +
                                    • +
                                    +`; + +exports[`when the canRender prop of all the root items return false, do not render the root section 1`] = `null`; diff --git a/packages/react-router/tests/navigationItemRegistry.test.ts b/packages/react-router/tests/navigationItemRegistry.test.ts new file mode 100644 index 000000000..0ea1a3a22 --- /dev/null +++ b/packages/react-router/tests/navigationItemRegistry.test.ts @@ -0,0 +1,425 @@ +import { NavigationItemDeferredRegistrationScope, NavigationItemDeferredRegistrationTransactionalScope, NavigationItemRegistry } from "../src/navigationItemRegistry.ts"; + +describe("add", () => { + test("can add a single deferred item", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "deferred", { + $label: "1", + to: "1" + }); + + expect(registry.getItems("foo")[0]).toBeDefined(); + expect(registry.getItems("foo")[0].$label).toBe("1"); + expect(registry.getItems("foo")[0].to).toBe("1"); + }); + + test("can add a single static item", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "static", { + $label: "1", + to: "1" + }); + + expect(registry.getItems("foo")[0]).toBeDefined(); + expect(registry.getItems("foo")[0].$label).toBe("1"); + expect(registry.getItems("foo")[0].to).toBe("1"); + }); + + test("can add multiple items", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "deferred", { + $label: "1", + to: "1" + }); + + registry.add("foo", "static", { + $label: "2", + to: "2" + }); + + expect(registry.getItems("foo").length).toBe(2); + }); + + test("can add items for different menus", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "deferred", { + $label: "1", + to: "1" + }); + + registry.add("foo", "static", { + $label: "2", + to: "2" + }); + + registry.add("bar", "deferred", { + $label: "3", + to: "3" + }); + + expect(registry.getItems("foo").length).toBe(2); + expect(registry.getItems("bar").length).toBe(1); + }); +}); + +describe("getItems", () => { + test("an empty array is returned when there's no registered items for the specified menu id", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "deferred", { + $label: "1", + to: "1" + }); + + registry.add("foo", "static", { + $label: "2", + to: "2" + }); + + registry.add("bar", "deferred", { + $label: "3", + to: "3" + }); + + expect(Array.isArray(registry.getItems("toto"))).toBeTruthy(); + expect(registry.getItems("toto").length).toBe(0); + }); + + test("the returned items are immutable", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "static", { + $label: "1", + to: "/1" + }); + + const result1 = registry.getItems("foo"); + const result2 = registry.getItems("foo"); + + expect(result1).toBe(result2); + + registry.add("foo", "static", { + $label: "2", + to: "/2" + }); + + const result3 = registry.getItems("foo"); + + expect(result1).not.toBe(result3); + expect(result2).not.toBe(result3); + }); +}); + +describe("clearDeferredItems", () => { + test("clear all deferred items", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "deferred", { + $label: "1", + to: "1" + }); + + registry.add("foo", "static", { + $label: "2", + to: "2" + }); + + registry.add("bar", "deferred", { + $label: "3", + to: "3" + }); + + expect(registry.getItems("foo").length).toBe(2); + expect(registry.getItems("bar").length).toBe(1); + + registry.clearDeferredItems(); + + expect(registry.getItems("foo").length).toBe(1); + expect(registry.getItems("bar").length).toBe(0); + }); + + test("do not clear static items", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "static", { + $label: "1", + to: "1" + }); + + expect(registry.getItems("foo").length).toBe(1); + + registry.clearDeferredItems(); + + expect(registry.getItems("foo")[0]).toBeDefined(); + expect(registry.getItems("foo")[0].$label).toBe("1"); + expect(registry.getItems("foo")[0].to).toBe("1"); + }); + + test("when there's no deferred items to clear, do not mutate the menu arrays", () => { + const registry = new NavigationItemRegistry(); + + registry.add("foo", "static", { + $label: "1", + to: "1" + }); + + const array1 = registry.getItems("foo"); + + registry.clearDeferredItems(); + + const array2 = registry.getItems("foo"); + + expect(array1).toBe(array2); + }); +}); + +describe("NavigationItemDeferredRegistrationScope", () => { + test("can add a single item", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationScope(registry); + + scope.addItem("foo", { + $label: "Bar", + to: "/bar" + }); + + expect(scope.getItems("foo")[0]).toBeDefined(); + expect(scope.getItems("foo")[0].$label).toBe("Bar"); + expect(scope.getItems("foo")[0].to).toBe("/bar"); + }); + + test("can add multiple items", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationScope(registry); + + scope.addItem("foo", { + $label: "1", + to: "/1" + }); + + scope.addItem("foo", { + $label: "2", + to: "/2" + }); + + scope.addItem("foo", { + $label: "3", + to: "/3" + }); + + expect(scope.getItems("foo").length).toBe(3); + }); + + test("can add items for different menus", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationScope(registry); + + scope.addItem("foo", { + $label: "1", + to: "/1" + }); + + scope.addItem("bar", { + $label: "2", + to: "/2" + }); + + expect(scope.getItems("foo").length).toBe(1); + expect(scope.getItems("bar").length).toBe(1); + }); + + test("adding an item also add the item to the registry", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationScope(registry); + + expect(registry.getItems("foo").length).toBe(0); + + scope.addItem("foo", { + $label: "Bar", + to: "/bar" + }); + + expect(registry.getItems("foo").length).toBe(1); + }); + + test("completing the scope doesn't alter the registry items", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationScope(registry); + + registry.add("foo", "deferred", { + $label: "1", + to: "/1" + }); + + registry.add("bar", "deferred", { + $label: "2", + to: "/2" + }); + + expect(registry.getItems("foo").length).toBe(1); + expect(registry.getItems("bar").length).toBe(1); + + scope.addItem("foo", { + $label: "3", + to: "/3" + }); + + scope.complete(); + + expect(registry.getItems("foo").length).toBe(2); + expect(registry.getItems("bar").length).toBe(1); + expect(registry.getItems("foo")[0].$label).toBe("1"); + }); +}); + +describe("NavigationItemDeferredRegistrationTransactionalScope", () => { + test("can add a single item", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + scope.addItem("foo", { + $label: "Bar", + to: "/bar" + }); + + expect(scope.getItems("foo")[0]).toBeDefined(); + expect(scope.getItems("foo")[0].$label).toBe("Bar"); + expect(scope.getItems("foo")[0].to).toBe("/bar"); + }); + + test("can add multiple items", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + scope.addItem("foo", { + $label: "1", + to: "/1" + }); + + scope.addItem("foo", { + $label: "2", + to: "/2" + }); + + scope.addItem("foo", { + $label: "3", + to: "/3" + }); + + expect(scope.getItems("foo").length).toBe(3); + }); + + test("can add items for different menus", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + scope.addItem("foo", { + $label: "1", + to: "/1" + }); + + scope.addItem("bar", { + $label: "2", + to: "/2" + }); + + expect(scope.getItems("foo").length).toBe(1); + expect(scope.getItems("bar").length).toBe(1); + }); + + test("adding an item doesn't add the item to the registry", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + expect(registry.getItems("foo").length).toBe(0); + + scope.addItem("foo", { + $label: "bar", + to: "/bar" + }); + + expect(registry.getItems("foo").length).toBe(0); + }); + + test("when there's no items for the provided menu id, return an empty array", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + scope.addItem("foo", { + $label: "bar", + to: "/bar" + }); + + expect(Array.isArray(registry.getItems("toto"))).toBeTruthy(); + expect(registry.getItems("toto").length).toBe(0); + }); + + test("completing the scope add all the active items to the registry", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + expect(registry.getItems("foo").length).toBe(0); + + scope.addItem("foo", { + $label: "Bar", + to: "/bar" + }); + + scope.complete(); + + expect(registry.getItems("foo").length).toBe(1); + }); + + test("completing the scope clears the previously registered deferred items", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + registry.add("foo", "deferred", { + $label: "1", + to: "/1" + }); + + registry.add("bar", "deferred", { + $label: "2", + to: "/2" + }); + + expect(registry.getItems("foo").length).toBe(1); + expect(registry.getItems("bar").length).toBe(1); + + scope.addItem("foo", { + $label: "3", + to: "3" + }); + + scope.complete(); + + expect(registry.getItems("foo").length).toBe(1); + expect(registry.getItems("bar").length).toBe(0); + expect(registry.getItems("foo")[0].$label).toBe("3"); + }); + + test("completing the scope clears the scope active items", () => { + const registry = new NavigationItemRegistry(); + const scope = new NavigationItemDeferredRegistrationTransactionalScope(registry); + + scope.addItem("foo", { + $label: "1", + to: "/1" + }); + + scope.addItem("bar", { + $label: "2", + to: "/2" + }); + + scope.complete(); + + expect(scope.getItems("foo").length).toBe(0); + expect(scope.getItems("bar").length).toBe(0); + }); +}); diff --git a/packages/react-router/tests/reactRouterRuntime.test.tsx b/packages/react-router/tests/reactRouterRuntime.test.tsx index 33621c426..7ac744619 100644 --- a/packages/react-router/tests/reactRouterRuntime.test.tsx +++ b/packages/react-router/tests/reactRouterRuntime.test.tsx @@ -201,7 +201,7 @@ describe("registerRoute", () => { expect(routes[0].$visibility).toBe("protected"); }); - test("when a root route has no visibility property, it is considered as an \"protected\" route", () => { + test("when a root route has no visibility property, it is considered as a \"protected\" route", () => { const runtime = new ReactRouterRuntime(); registerManagedRoutesOutlet(runtime); @@ -1131,7 +1131,103 @@ describe("getNavigationItems", () => { }); }); -describe("_completeRegistration", () => { +describe("startDeferredRegistrationScope & completeDeferredRegistrationScope", () => { + test("can start and complete a scope", () => { + const runtime = new ReactRouterRuntime(); + + expect(() => { + runtime.startDeferredRegistrationScope(); + runtime.completeDeferredRegistrationScope(); + }).not.toThrow(); + }); + + test("when a scope is started, can register a navigation item", () => { + const runtime = new ReactRouterRuntime(); + + runtime.startDeferredRegistrationScope(); + + runtime.registerNavigationItem({ + $label: "Foo", + to: "foo" + }); + + expect(runtime.getNavigationItems().length).toBe(1); + + runtime.completeDeferredRegistrationScope(); + + expect(runtime.getNavigationItems().length).toBe(1); + }); + + test("when a scope is started, can register a route", () => { + const runtime = new ReactRouterRuntime(); + + runtime.startDeferredRegistrationScope(); + + runtime.registerRoute({ + path: "/foo", + element:
                                    Hello!
                                    + }, { + hoist: true + }); + + expect(runtime.routes.length).toBe(1); + + runtime.completeDeferredRegistrationScope(); + + expect(runtime.routes.length).toBe(1); + }); + + test("when a scope is completed, can register a navigation item", () => { + const runtime = new ReactRouterRuntime(); + + runtime.startDeferredRegistrationScope(); + + runtime.registerNavigationItem({ + $label: "Foo", + to: "foo" + }); + + expect(runtime.getNavigationItems().length).toBe(1); + + runtime.completeDeferredRegistrationScope(); + + runtime.registerNavigationItem({ + $label: "Bar", + to: "bar" + }); + + expect(runtime.getNavigationItems().length).toBe(2); + }); + + test("when a scope is completed, can register a route", () => { + const runtime = new ReactRouterRuntime(); + + runtime.startDeferredRegistrationScope(); + + runtime.registerRoute({ + path: "/foo", + element:
                                    Hello!
                                    + }, { + hoist: true + }); + + expect(runtime.routes.length).toBe(1); + + runtime.completeDeferredRegistrationScope(); + + runtime.registerRoute({ + path: "/bar", + element:
                                    Hello!
                                    + }, { + hoist: true + }); + + + expect(runtime.routes.length).toBe(2); + }); +}); + +describe("_validateRegistrations", () => { describe("managed routes", () => { test("when the outlet is missing, the error message mentions the ManagedRoutes outlet", () => { const runtime = new ReactRouterRuntime(); @@ -1143,7 +1239,7 @@ describe("_completeRegistration", () => { }); try { - runtime._completeRegistration(); + runtime._validateRegistrations(); } catch (error: unknown) { errorMessage = (error as Error).message; } @@ -1153,7 +1249,7 @@ describe("_completeRegistration", () => { }); describe("parentPath", () => { - test("when the registration is completed and there are no pending registrations, do nothing", () => { + test("when there are no pending registrations, do nothing", () => { const runtime = new ReactRouterRuntime(); runtime.registerRoute({ @@ -1170,10 +1266,10 @@ describe("_completeRegistration", () => { hoist: true }); - expect(() => runtime._completeRegistration()).not.toThrow(); + expect(() => runtime._validateRegistrations()).not.toThrow(); }); - test("when the registration is completed and there are pending registrations, throw an error", () => { + test("when there are pending registrations, throw an error", () => { const runtime = new ReactRouterRuntime(); runtime.registerRoute({ @@ -1183,12 +1279,12 @@ describe("_completeRegistration", () => { parentPath: "/layout" }); - expect(() => runtime._completeRegistration()).toThrow(); + expect(() => runtime._validateRegistrations()).toThrow(); }); }); describe("parentName", () => { - test("when the registration is completed and there are no pending registrations, do nothing", () => { + test("when there are no pending registrations, do nothing", () => { const runtime = new ReactRouterRuntime(); runtime.registerRoute({ @@ -1205,10 +1301,10 @@ describe("_completeRegistration", () => { hoist: true }); - expect(() => runtime._completeRegistration()).not.toThrow(); + expect(() => runtime._validateRegistrations()).not.toThrow(); }); - test("when the registration is completed and there are pending registrations, throw an error", () => { + test("when there are pending registrations, throw an error", () => { const runtime = new ReactRouterRuntime(); runtime.registerRoute({ @@ -1218,7 +1314,7 @@ describe("_completeRegistration", () => { parentName: "layout" }); - expect(() => runtime._completeRegistration()).toThrow(); + expect(() => runtime._validateRegistrations()).toThrow(); }); }); }); diff --git a/packages/react-router/tests/useNavigationItems.test.tsx b/packages/react-router/tests/useNavigationItems.test.tsx index b44b5af27..f17a10763 100644 --- a/packages/react-router/tests/useNavigationItems.test.tsx +++ b/packages/react-router/tests/useNavigationItems.test.tsx @@ -2,10 +2,10 @@ import { RuntimeContext } from "@squide/core"; import { renderHook } from "@testing-library/react"; import type { ReactNode } from "react"; import { ReactRouterRuntime } from "../src/reactRouterRuntime.ts"; -import { useNavigationItems } from "../src/useNavigationItems.ts"; +import { useRuntimeNavigationItems } from "../src/useRuntimeNavigationItems.ts"; -function renderWithRuntime(runtime: ReactRouterRuntime, menuId?: string) { - return renderHook(() => useNavigationItems({ menuId }), { +function renderUseNavigationItemsHook(runtime: ReactRouterRuntime, menuId?: string) { + return renderHook(() => useRuntimeNavigationItems({ menuId }), { wrapper: ({ children }: { children?: ReactNode }) => ( {children} @@ -46,7 +46,7 @@ test("when no menu id is specified, returns all the registered navigation items menuId: "menu-2" }); - const { result } = renderWithRuntime(runtime); + const { result } = renderUseNavigationItemsHook(runtime); expect(result.current.length).toBe(3); }); @@ -83,7 +83,7 @@ test("when a menu id is specified, returns all the registered navigation items f menuId: "menu-2" }); - const { result } = renderWithRuntime(runtime, "menu-1"); + const { result } = renderUseNavigationItemsHook(runtime, "menu-1"); expect(result.current.length).toBe(1); }); @@ -96,7 +96,7 @@ test("returned array is immutable", () => { to: "/foo" }); - const { result, rerender } = renderWithRuntime(runtime); + const { result, rerender } = renderUseNavigationItemsHook(runtime); const array1 = result.current; diff --git a/packages/react-router/tests/useRenderedNavigationItems.test.tsx b/packages/react-router/tests/useRenderedNavigationItems.test.tsx index d9b5edd96..43fd081e7 100644 --- a/packages/react-router/tests/useRenderedNavigationItems.test.tsx +++ b/packages/react-router/tests/useRenderedNavigationItems.test.tsx @@ -4,16 +4,16 @@ import renderer from "react-test-renderer"; import type { NavigationItem, RootNavigationItem } from "../src/navigationItemRegistry.ts"; import { isNavigationLink, useRenderedNavigationItems, type NavigationLinkRenderProps, type NavigationSectionRenderProps, type RenderItemFunction, type RenderSectionFunction } from "../src/useRenderedNavigationItems.tsx"; -type RenderLinkItemFunction = (item: NavigationLinkRenderProps, index: number, level: number) => ReactNode; +type RenderLinkItemFunction = (item: NavigationLinkRenderProps, key: string, index: number, level: number) => ReactNode; -type RenderSectionItemFunction = (item: NavigationSectionRenderProps, index: number, level: number) => ReactNode; +type RenderSectionItemFunction = (item: NavigationSectionRenderProps, key: string, index: number, level: number) => ReactNode; interface TestComponentProps { navigationItems: RootNavigationItem[]; } // Not the prettiest mock but it's simpler than using createMemoryRouter and -// it provides an adequate testing when combined with snapshot tests. +// it provides an adequate testing experience when combined with snapshot tests. function Link(props: Record) { return (
                                    @@ -21,9 +21,9 @@ function Link(props: Record) { } function TestComponent({ navigationItems }: TestComponentProps) { - const renderLinkItem: RenderLinkItemFunction = useCallback(({ label, linkProps, additionalProps }, index, level) => { + const renderLinkItem: RenderLinkItemFunction = useCallback(({ label, linkProps, additionalProps }, key, index, level) => { return ( -
                                  • +
                                  • {label} @@ -31,22 +31,24 @@ function TestComponent({ navigationItems }: TestComponentProps) { ); }, []); - const renderLinkSection: RenderSectionItemFunction = useCallback(({ label, section, additionalProps }, index, level) => { + const renderLinkSection: RenderSectionItemFunction = useCallback(({ label, section, additionalProps }, key, index, level) => { return ( -
                                  • +
                                  • {label} {section}
                                  • ); }, []); - const renderItem: RenderItemFunction = useCallback((item, index, level) => { - return isNavigationLink(item) ? renderLinkItem(item, index, level) : renderLinkSection(item, index, level); + const renderItem: RenderItemFunction = useCallback((item, key, index, level) => { + if (!item.canRender || (item.canRender && item.canRender())) { + return isNavigationLink(item) ? renderLinkItem(item, key, index, level) : renderLinkSection(item, key, index, level); + } }, [renderLinkItem, renderLinkSection]); - const renderSection: RenderSectionFunction = useCallback((elements, index, level) => { + const renderSection: RenderSectionFunction = useCallback((elements, key, index, level) => { return ( -
                                      +
                                        {elements}
                                      ); @@ -178,9 +180,55 @@ test("support 3 section levels", () => { expect(tree).toMatchSnapshot(); }); -test("Link item additionalProps are rendered", () => { +test("link item additionalProps are rendered", () => { + const navigationItems: RootNavigationItem[] = [ + { + $label: "Foo", + $additionalProps: { + style: { color: "red" } + }, + to: "/foo" + }, + { + $label: "Bar", + to: "/bar" + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("section item additionalProps are rendered", () => { + const navigationItems: RootNavigationItem[] = [ + { + $label: "Foo", + children: [ + { + $label: "Bar", + to: "/bar" + } + ], + $additionalProps: { + style: { color: "red" } + } + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("link item custom keys are rendered", () => { const navigationItems: RootNavigationItem[] = [ { + $key: "foo", $label: "Foo", $additionalProps: { style: { color: "red" } @@ -188,6 +236,7 @@ test("Link item additionalProps are rendered", () => { to: "/foo" }, { + $key: "bar", $label: "Bar", to: "/bar" } @@ -200,12 +249,37 @@ test("Link item additionalProps are rendered", () => { expect(tree).toMatchSnapshot(); }); -test("Section item additionalProps are rendered", () => { +test("section item custom keys are rendered", () => { + const navigationItems: RootNavigationItem[] = [ + { + $key: "foo", + $label: "Foo", + children: [ + { + $label: "Bar", + to: "/bar" + } + ], + $additionalProps: { + style: { color: "red" } + } + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("nested item custom keys are rendered", () => { const navigationItems: RootNavigationItem[] = [ { $label: "Foo", children: [ { + $key: "bar", $label: "Bar", to: "/bar" } @@ -223,6 +297,108 @@ test("Section item additionalProps are rendered", () => { expect(tree).toMatchSnapshot(); }); +test("when a link item canRender prop return false, the item is not rendered", () => { + const navigationItems: RootNavigationItem[] = [ + { + $canRender: () => false, + $label: "Foo", + to: "/foo" + }, + { + $label: "Bar", + to: "/bar" + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("when a section item canRender prop return false, the item is not rendered", () => { + const navigationItems: RootNavigationItem[] = [ + { + $canRender: () => false, + $label: "Foo", + children: [ + { + $label: "Bar", + to: "/bar" + } + ] + }, + { + $label: "acme", + to: "/acme" + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("when the canRender prop of all the root items return false, do not render the root section", () => { + const navigationItems: RootNavigationItem[] = [ + { + $canRender: () => false, + $label: "Foo", + to: "/foo" + }, + { + $canRender: () => false, + $label: "Bar", + to: "/bar" + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +test("when the canRender prop of all the items of a nested section return false, do not render the section", () => { + const navigationItems: RootNavigationItem[] = [ + { + $label: "Foo", + children: [ + { + $canRender: () => false, + $label: "Bar", + to: "/bar" + } + ] + }, + { + $label: "John", + children: [ + { + $label: "Doe", + children: [ + { + $canRender: () => false, + $label: "Acme", + to: "/acme" + } + ] + } + ] + } + ]; + + const tree = renderer + .create() + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + test("doesn't rerender when the navigation items haven't changed", () => { const initialItems: NavigationItem[] = [ { diff --git a/packages/react-router/tests/useRoutes.test.tsx b/packages/react-router/tests/useRoutes.test.tsx index 33c04659b..78c4913f5 100644 --- a/packages/react-router/tests/useRoutes.test.tsx +++ b/packages/react-router/tests/useRoutes.test.tsx @@ -3,7 +3,7 @@ import { renderHook, type RenderHookOptions } from "@testing-library/react"; import { ReactRouterRuntime } from "../src/reactRouterRuntime.ts"; import { useRoutes } from "../src/useRoutes.ts"; -function renderWithRuntime(runtime: ReactRouterRuntime, additionalProps: RenderHookOptions = {}) { +function renderUseRoutesHook(runtime: ReactRouterRuntime, additionalProps: RenderHookOptions = {}) { return renderHook(() => useRoutes(), { wrapper: ({ children }) => ( @@ -31,7 +31,7 @@ test("returns all the registered routes", () => { hoist: true }); - const { result } = renderWithRuntime(runtime); + const { result } = renderUseRoutesHook(runtime); expect(result.current.length).toBe(2); }); @@ -46,7 +46,7 @@ test("returned array is immutable", () => { hoist: true }); - const { result, rerender } = renderWithRuntime(runtime); + const { result, rerender } = renderUseRoutesHook(runtime); const array1 = result.current; diff --git a/packages/webpack-configs/package.json b/packages/webpack-configs/package.json index bd6f3196c..935c87367 100644 --- a/packages/webpack-configs/package.json +++ b/packages/webpack-configs/package.json @@ -40,10 +40,10 @@ "webpack-dev-server": ">=5.0.0" }, "devDependencies": { - "@swc/core": "1.4.17", + "@swc/core": "1.7.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@types/node": "20.12.7", + "@types/node": "20.14.11", "@types/semver": "7.5.8", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", @@ -52,16 +52,16 @@ "eslint": "8.57.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "tsup": "8.0.2", - "typescript": "5.4.5", - "webpack": "5.91.0" + "tsup": "8.1.2", + "typescript": "5.5.3", + "webpack": "5.93.0" }, "dependencies": { - "@module-federation/enhanced": "0.1.11", + "@module-federation/enhanced": "0.2.6", "@workleap/webpack-configs": "1.5.1", "deepmerge": "4.3.1", "html-webpack-plugin": "5.6.0", - "semver": "7.6.0" + "semver": "7.6.3" }, "engines": { "node": ">=20.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 954930008..bcc344b9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,20 +12,20 @@ importers: specifier: 0.5.0 version: 0.5.0 '@changesets/cli': - specifier: 2.27.1 - version: 2.27.1 + specifier: 2.27.7 + version: 2.27.7 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.11 + version: 20.14.11 '@typescript-eslint/parser': - specifier: 7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) + specifier: 7.16.1 + version: 7.16.1(eslint@8.57.0)(typescript@5.5.3) '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) cross-env: specifier: 7.0.3 version: 7.0.3 @@ -37,22 +37,22 @@ importers: version: 9.3.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) knip: - specifier: 5.12.3 - version: 5.12.3(@types/node@20.12.7)(typescript@5.4.5) + specifier: 5.26.0 + version: 5.26.0(@types/node@20.14.11)(typescript@5.5.3) retypeapp: specifier: 3.5.0 version: 3.5.0 ts-node: specifier: 10.9.2 - version: 10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + version: 10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3) turbo: specifier: 1.13.3 version: 1.13.3 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/core: dependencies: @@ -64,44 +64,44 @@ importers: version: 18.3.1(react@18.3.1) devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) react: specifier: 18.3.1 version: 18.3.1 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/fakes: dependencies: @@ -111,22 +111,22 @@ importers: devDependencies: '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/firefly: dependencies: @@ -142,73 +142,73 @@ importers: '@squide/react-router': specifier: workspace:* version: link:../react-router + '@tanstack/react-query': + specifier: '*' + version: 5.51.9(react@18.3.1) devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@testing-library/jest-dom': - specifier: 6.4.2 - version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))) + specifier: 6.4.6 + version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3))) '@testing-library/react': - specifier: 15.0.5 - version: 15.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 16.0.0 + version: 16.0.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.4.5) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) react: specifier: 18.3.1 version: 18.3.1 react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ts-jest: - specifier: 29.1.2 - version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + specifier: 29.2.3 + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/firefly-webpack-configs: dependencies: @@ -217,65 +217,65 @@ importers: version: link:../webpack-configs '@swc/helpers': specifier: '*' - version: 0.5.11 + version: 0.5.12 '@workleap/webpack-configs': specifier: 1.5.1 - version: 1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(esbuild@0.19.12)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(type-fest@4.25.0)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) browserslist: specifier: '*' - version: 4.23.0 + version: 4.23.2 postcss: specifier: '*' - version: 8.4.38 + version: 8.4.39 webpack-dev-server: specifier: '>=5.0.0' - version: 5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) devDependencies: '@module-federation/enhanced': - specifier: 0.1.11 - version: 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + specifier: 0.2.6 + version: 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 ts-jest: - specifier: 29.1.2 - version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + specifier: 29.2.3 + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) packages/i18next: dependencies: @@ -287,44 +287,44 @@ importers: version: link:../core devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 i18next: - specifier: 23.11.3 - version: 23.11.3 + specifier: 23.12.1 + version: 23.12.1 i18next-browser-languagedetector: - specifier: 7.2.1 - version: 7.2.1 + specifier: 8.0.0 + version: 8.0.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 @@ -335,63 +335,63 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) react-i18next: - specifier: 14.1.1 - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 15.0.0 + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ts-jest: - specifier: 29.1.2 - version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + specifier: 29.2.3 + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/module-federation: dependencies: '@module-federation/enhanced': - specifier: 0.1.11 - version: 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + specifier: 0.2.6 + version: 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) '@squide/core': specifier: workspace:* version: link:../core devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.11 + version: 20.14.11 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 @@ -402,14 +402,14 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) ts-jest: - specifier: 29.1.2 - version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + specifier: 29.2.3 + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/msw: dependencies: @@ -418,26 +418,26 @@ importers: version: link:../core devDependencies: '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.4.5) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) react: specifier: 18.3.1 version: 18.3.1 @@ -445,33 +445,36 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/react-router: dependencies: '@squide/core': specifier: workspace:* version: link:../core + memoize: + specifier: 10.0.0 + version: 10.0.0 devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@testing-library/react': - specifier: 15.0.5 - version: 15.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 16.0.0 + version: 16.0.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -480,22 +483,22 @@ importers: version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 @@ -506,96 +509,96 @@ importers: specifier: 18.3.1 version: 18.3.1(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-test-renderer: specifier: 18.3.1 version: 18.3.1(react@18.3.1) ts-jest: - specifier: 29.1.2 - version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + specifier: 29.2.3 + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 packages/webpack-configs: dependencies: '@module-federation/enhanced': - specifier: 0.1.11 - version: 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + specifier: 0.2.6 + version: 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) '@swc/helpers': specifier: '*' - version: 0.5.11 + version: 0.5.12 '@workleap/webpack-configs': specifier: 1.5.1 - version: 1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(esbuild@0.19.12)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(type-fest@4.25.0)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) browserslist: specifier: '*' - version: 4.23.0 + version: 4.23.2 deepmerge: specifier: 4.3.1 version: 4.3.1 html-webpack-plugin: specifier: 5.6.0 - version: 5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) postcss: specifier: '*' - version: 8.4.38 + version: 8.4.39 semver: - specifier: 7.6.0 - version: 7.6.0 + specifier: 7.6.3 + version: 7.6.3 webpack-dev-server: specifier: '>=5.0.0' - version: 5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) devDependencies: '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) + version: 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.11 + version: 20.14.11 '@types/semver': specifier: 7.5.8 version: 7.5.8 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) samples/basic/another-remote-module: dependencies: @@ -606,11 +609,11 @@ importers: specifier: workspace:* version: link:../shell '@react-aria/toast': - specifier: 3.0.0-beta.10 - version: 3.0.0-beta.10(react@18.3.1) + specifier: 3.0.0-beta.12 + version: 3.0.0-beta.12(react@18.3.1) '@react-stately/toast': - specifier: 3.0.0-beta.2 - version: 3.0.0-beta.2(react@18.3.1) + specifier: 3.0.0-beta.4 + version: 3.0.0-beta.4(react@18.3.1) '@squide/fakes': specifier: workspace:* version: link:../../../packages/fakes @@ -623,12 +626,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) useless-lib: specifier: 3.0.0 version: 3.0.0 @@ -637,14 +637,14 @@ importers: specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -653,16 +653,16 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 cross-env: specifier: 7.0.3 version: 7.0.3 @@ -673,23 +673,23 @@ importers: specifier: 14.1.1 version: 14.1.1 netlify-cli: - specifier: 17.23.1 - version: 17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2) + specifier: 17.33.4 + version: 17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/basic/host: dependencies: @@ -703,11 +703,11 @@ importers: specifier: workspace:* version: link:../shell '@react-aria/toast': - specifier: 3.0.0-beta.10 - version: 3.0.0-beta.10(react@18.3.1) + specifier: 3.0.0-beta.12 + version: 3.0.0-beta.12(react@18.3.1) '@react-stately/toast': - specifier: 3.0.0-beta.2 - version: 3.0.0-beta.2(react@18.3.1) + specifier: 3.0.0-beta.4 + version: 3.0.0-beta.4(react@18.3.1) '@squide/fakes': specifier: workspace:* version: link:../../../packages/fakes @@ -720,12 +720,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) useless-lib: specifier: ^2.0.0 version: 2.1.0 @@ -734,14 +731,14 @@ importers: specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -750,16 +747,16 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 copyfiles: specifier: 2.4.1 version: 2.4.1 @@ -770,23 +767,23 @@ importers: specifier: 14.1.1 version: 14.1.1 netlify-cli: - specifier: 17.23.1 - version: 17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2) + specifier: 17.33.4 + version: 17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/basic/local-module: dependencies: @@ -808,31 +805,28 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@react-aria/toast': - specifier: 3.0.0-beta.10 - version: 3.0.0-beta.10(react@18.3.1) + specifier: 3.0.0-beta.12 + version: 3.0.0-beta.12(react@18.3.1) '@react-stately/toast': - specifier: 3.0.0-beta.2 - version: 3.0.0-beta.2(react@18.3.1) + specifier: 3.0.0-beta.4 + version: 3.0.0-beta.4(react@18.3.1) '@squide/firefly-webpack-configs': specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -841,40 +835,40 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/basic/remote-module: dependencies: @@ -885,11 +879,11 @@ importers: specifier: workspace:* version: link:../shell '@react-aria/toast': - specifier: 3.0.0-beta.10 - version: 3.0.0-beta.10(react@18.3.1) + specifier: 3.0.0-beta.12 + version: 3.0.0-beta.12(react@18.3.1) '@react-stately/toast': - specifier: 3.0.0-beta.2 - version: 3.0.0-beta.2(react@18.3.1) + specifier: 3.0.0-beta.4 + version: 3.0.0-beta.4(react@18.3.1) '@squide/fakes': specifier: workspace:* version: link:../../../packages/fakes @@ -902,12 +896,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) useless-lib: specifier: ^2.1.0 version: 2.1.0 @@ -916,14 +907,14 @@ importers: specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -932,16 +923,16 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 cross-env: specifier: 7.0.3 version: 7.0.3 @@ -952,23 +943,23 @@ importers: specifier: 14.1.1 version: 14.1.1 netlify-cli: - specifier: 17.23.1 - version: 17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2) + specifier: 17.33.4 + version: 17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/basic/shared: dependencies: @@ -978,98 +969,95 @@ importers: react-dom: specifier: '*' version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: '*' - version: 4.0.13(react@18.3.1) react-router-dom: specifier: '*' - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly': specifier: workspace:* version: link:../../../packages/firefly '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 samples/basic/shell: dependencies: '@react-aria/toast': specifier: '*' - version: 3.0.0-beta.11(react@18.3.1) + version: 3.0.0-beta.15(react@18.3.1) '@react-stately/toast': specifier: '*' - version: 3.0.0-beta.3(react@18.3.1) + version: 3.0.0-beta.5(react@18.3.1) react: specifier: '*' version: 18.3.1 react-dom: specifier: '*' version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: '*' - version: 4.0.13(react@18.3.1) react-router-dom: specifier: '*' - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@basic/shared': specifier: workspace:* version: link:../shared + '@squide/fakes': + specifier: workspace:* + version: link:../../../packages/fakes '@squide/firefly': specifier: workspace:* version: link:../../../packages/firefly '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 samples/endpoints/host: dependencies: @@ -1098,14 +1086,14 @@ importers: specifier: workspace:* version: link:../../../packages/i18next i18next: - specifier: 23.11.3 - version: 23.11.3 + specifier: 23.12.1 + version: 23.12.1 i18next-browser-languagedetector: - specifier: 7.2.1 - version: 7.2.1 + specifier: 8.0.0 + version: 8.0.0 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.4.5) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) react: specifier: 18.3.1 version: 18.3.1 @@ -1116,27 +1104,27 @@ importers: specifier: 4.0.13 version: 4.0.13(react@18.3.1) react-i18next: - specifier: 14.1.1 - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 15.0.0 + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly-webpack-configs': specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@tanstack/react-query': - specifier: 5.32.0 - version: 5.32.0(react@18.3.1) + specifier: 5.51.9 + version: 5.51.9(react@18.3.1) '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -1145,16 +1133,16 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 copyfiles: specifier: 2.4.1 version: 2.4.1 @@ -1168,32 +1156,32 @@ importers: specifier: 14.1.1 version: 14.1.1 netlify-cli: - specifier: 17.23.1 - version: 17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2) + specifier: 17.33.4 + version: 17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/endpoints/i18next: dependencies: i18next: specifier: '*' - version: 23.11.3 + version: 23.12.1 i18next-browser-languagedetector: specifier: '*' - version: 7.2.1 + version: 8.0.0 react: specifier: '*' version: 18.3.1 @@ -1202,7 +1190,7 @@ importers: version: 18.3.1(react@18.3.1) react-i18next: specifier: '*' - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@endpoints/shared': specifier: workspace:* @@ -1212,34 +1200,34 @@ importers: version: link:../../../packages/i18next '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 samples/endpoints/layouts: dependencies: i18next: specifier: '*' - version: 23.11.3 + version: 23.12.1 i18next-browser-languagedetector: specifier: '*' - version: 7.2.1 + version: 8.0.0 react: specifier: '*' version: 18.3.1 @@ -1251,10 +1239,10 @@ importers: version: 4.0.13(react@18.3.1) react-i18next: specifier: '*' - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: specifier: '*' - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@endpoints/i18next': specifier: workspace:* @@ -1269,32 +1257,32 @@ importers: specifier: workspace:* version: link:../../../packages/i18next '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 samples/endpoints/local-module: dependencies: @@ -1320,17 +1308,17 @@ importers: specifier: workspace:* version: link:../../../packages/i18next '@tanstack/react-query': - specifier: 5.32.0 - version: 5.32.0(react@18.3.1) + specifier: 5.51.9 + version: 5.51.9(react@18.3.1) i18next: - specifier: 23.11.3 - version: 23.11.3 + specifier: 23.12.1 + version: 23.12.1 i18next-browser-languagedetector: - specifier: 7.2.1 - version: 7.2.1 + specifier: 8.0.0 + version: 8.0.0 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.4.5) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) react: specifier: 18.3.1 version: 18.3.1 @@ -1341,27 +1329,27 @@ importers: specifier: 4.0.13 version: 4.0.13(react@18.3.1) react-i18next: - specifier: 14.1.1 - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 15.0.0 + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly-webpack-configs': specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@tanstack/react-query-devtools': - specifier: 5.32.0 - version: 5.32.0(@tanstack/react-query@5.32.0(react@18.3.1))(react@18.3.1) + specifier: 5.51.9 + version: 5.51.9(@tanstack/react-query@5.51.9(react@18.3.1))(react@18.3.1) '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -1370,19 +1358,19 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 cross-env: specifier: 7.0.3 version: 7.0.3 @@ -1393,23 +1381,23 @@ importers: specifier: 14.1.1 version: 14.1.1 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/endpoints/remote-module: dependencies: @@ -1435,17 +1423,17 @@ importers: specifier: workspace:* version: link:../../../packages/i18next '@tanstack/react-query': - specifier: 5.32.0 - version: 5.32.0(react@18.3.1) + specifier: 5.51.9 + version: 5.51.9(react@18.3.1) i18next: - specifier: 23.11.3 - version: 23.11.3 + specifier: 23.12.1 + version: 23.12.1 i18next-browser-languagedetector: - specifier: 7.2.1 - version: 7.2.1 + specifier: 8.0.0 + version: 8.0.0 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.4.5) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) react: specifier: 18.3.1 version: 18.3.1 @@ -1456,27 +1444,27 @@ importers: specifier: 4.0.13 version: 4.0.13(react@18.3.1) react-i18next: - specifier: 14.1.1 - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 15.0.0 + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly-webpack-configs': specifier: workspace:* version: link:../../../packages/firefly-webpack-configs '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@tanstack/react-query-devtools': - specifier: 5.32.0 - version: 5.32.0(@tanstack/react-query@5.32.0(react@18.3.1))(react@18.3.1) + specifier: 5.51.9 + version: 5.51.9(@tanstack/react-query@5.51.9(react@18.3.1))(react@18.3.1) '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -1485,16 +1473,16 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 copyfiles: specifier: 2.4.1 version: 2.4.1 @@ -1508,23 +1496,23 @@ importers: specifier: 14.1.1 version: 14.1.1 netlify-cli: - specifier: 17.23.1 - version: 17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2) + specifier: 17.33.4 + version: 17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) samples/endpoints/shared: dependencies: @@ -1535,48 +1523,54 @@ importers: specifier: '*' version: 18.3.1(react@18.3.1) devDependencies: + '@squide/fakes': + specifier: workspace:* + version: link:../../../packages/fakes '@squide/firefly': specifier: workspace:* version: link:../../../packages/firefly '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 samples/endpoints/shell: dependencies: + '@tanstack/react-query': + specifier: '*' + version: 5.51.9(react@18.3.1) i18next: specifier: '*' - version: 23.11.3 + version: 23.12.1 i18next-browser-languagedetector: specifier: '*' - version: 7.2.1 + version: 8.0.0 msw: specifier: '*' - version: 2.2.14(typescript@5.4.5) + version: 2.3.1(typescript@5.5.3) react: specifier: '*' version: 18.3.1 @@ -1588,10 +1582,10 @@ importers: version: 4.0.13(react@18.3.1) react-i18next: specifier: '*' - version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: specifier: '*' - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@endpoints/i18next': specifier: workspace:* @@ -1612,53 +1606,53 @@ importers: specifier: workspace:* version: link:../../../packages/i18next '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.11 + version: 20.14.11 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 templates/getting-started: devDependencies: '@typescript-eslint/parser': - specifier: 7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) + specifier: 7.16.1 + version: 7.16.1(eslint@8.57.0)(typescript@5.5.3) '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 templates/getting-started/apps/host: dependencies: @@ -1667,32 +1661,29 @@ importers: version: link:../local-module '@squide/firefly': specifier: 8.0.0 - version: 8.0.0(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + version: 8.0.0(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) react: specifier: 18.3.1 version: 18.3.1 react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly-webpack-configs': specifier: 3.0.0 - version: 3.0.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0))(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + version: 3.0.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2))(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -1701,105 +1692,99 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 eslint: specifier: 8.57.0 version: 8.57.0 postcss: - specifier: 8.4.38 - version: 8.4.38 + specifier: 8.4.39 + version: 8.4.39 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) templates/getting-started/apps/local-module: dependencies: '@squide/firefly': specifier: 8.0.0 - version: 8.0.0(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + version: 8.0.0(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) react: specifier: 18.3.1 version: 18.3.1 react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/tsup-configs': specifier: 3.0.6 - version: 3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5) + version: 3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3) eslint: specifier: 8.57.0 version: 8.57.0 tsup: - specifier: 8.0.2 - version: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) + specifier: 8.1.2 + version: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 templates/getting-started/apps/remote-module: dependencies: '@squide/firefly': specifier: 8.0.0 - version: 8.0.0(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + version: 8.0.0(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) react: specifier: 18.3.1 version: 18.3.1 react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-error-boundary: - specifier: 4.0.13 - version: 4.0.13(react@18.3.1) react-router-dom: - specifier: 6.23.0 - version: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@squide/firefly-webpack-configs': specifier: 3.0.0 - version: 3.0.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0))(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + version: 3.0.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2))(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) '@swc/core': - specifier: 1.4.17 - version: 1.4.17(@swc/helpers@0.5.11) + specifier: 1.7.0 + version: 1.7.0(@swc/helpers@0.5.12) '@swc/helpers': - specifier: 0.5.11 - version: 0.5.11 + specifier: 0.5.12 + version: 0.5.12 '@types/react': - specifier: 18.3.1 - version: 18.3.1 + specifier: 18.3.3 + version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 @@ -1808,80 +1793,80 @@ importers: version: 2.0.1 '@workleap/eslint-plugin': specifier: 3.2.2 - version: 3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) + version: 3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) '@workleap/swc-configs': specifier: 2.2.3 - version: 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) + version: 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) '@workleap/typescript-configs': specifier: 3.0.2 - version: 3.0.2(typescript@5.4.5) + version: 3.0.2(typescript@5.5.3) browserslist: - specifier: 4.23.0 - version: 4.23.0 + specifier: 4.23.2 + version: 4.23.2 eslint: specifier: 8.57.0 version: 8.57.0 postcss: - specifier: 8.4.38 - version: 8.4.38 + specifier: 8.4.39 + version: 8.4.39 typescript: - specifier: 5.4.5 - version: 5.4.5 + specifier: 5.5.3 + version: 5.5.3 webpack: - specifier: 5.91.0 - version: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + specifier: 5.93.0 + version: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-cli: specifier: 5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) webpack-dev-server: specifier: 5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + version: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) packages: - '@adobe/css-tools@4.3.3': - resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} + '@adobe/css-tools@4.4.0': + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.24.2': - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.24.4': - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + '@babel/compat-data@7.25.4': + resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.5': - resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} + '@babel/core@7.25.2': + resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.24.5': - resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} + '@babel/generator@7.25.5': + resolution: {integrity: sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.22.5': - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + '@babel/helper-annotate-as-pure@7.24.7': + resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': + resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.23.6': - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + '@babel/helper-compilation-targets@7.25.2': + resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.24.5': - resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==} + '@babel/helper-create-class-features-plugin@7.25.4': + resolution: {integrity: sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.22.15': - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + '@babel/helper-create-regexp-features-plugin@7.25.2': + resolution: {integrity: sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1891,113 +1876,103 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-environment-visitor@7.22.20': - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.23.0': - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.22.5': - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-member-expression-to-functions@7.24.5': - resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==} + '@babel/helper-member-expression-to-functions@7.24.8': + resolution: {integrity: sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.24.3': - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.24.5': - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} + '@babel/helper-module-transforms@7.25.2': + resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.22.5': - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-optimise-call-expression@7.24.7': + resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.24.5': - resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} + '@babel/helper-plugin-utils@7.24.8': + resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.22.20': - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + '@babel/helper-remap-async-to-generator@7.25.0': + resolution: {integrity: sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.24.1': - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} + '@babel/helper-replace-supers@7.25.0': + resolution: {integrity: sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.24.5': - resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + '@babel/helper-skip-transparent-expression-wrappers@7.24.7': + resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.24.5': - resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.1': - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.5': - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + '@babel/helper-validator-option@7.24.8': + resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.23.5': - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + '@babel/helper-wrap-function@7.25.0': + resolution: {integrity: sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.24.5': - resolution: {integrity: sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==} + '@babel/helpers@7.25.0': + resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.24.5': - resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.24.5': - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.24.5': - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} + '@babel/parser@7.25.4': + resolution: {integrity: sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5': - resolution: {integrity: sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.3': + resolution: {integrity: sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.0': + resolution: {integrity: sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1': - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0': + resolution: {integrity: sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1': - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7': + resolution: {integrity: sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1': - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.0': + resolution: {integrity: sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -2039,14 +2014,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.24.1': - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} + '@babel/plugin-syntax-import-assertions@7.24.7': + resolution: {integrity: sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.24.1': - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} + '@babel/plugin-syntax-import-attributes@7.24.7': + resolution: {integrity: sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2061,8 +2036,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.24.1': - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + '@babel/plugin-syntax-jsx@7.24.7': + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2109,8 +2084,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.24.1': - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + '@babel/plugin-syntax-typescript@7.25.4': + resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2121,332 +2096,338 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.24.1': - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} + '@babel/plugin-transform-arrow-functions@7.24.7': + resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.24.3': - resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} + '@babel/plugin-transform-async-generator-functions@7.25.4': + resolution: {integrity: sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.24.1': - resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} + '@babel/plugin-transform-async-to-generator@7.24.7': + resolution: {integrity: sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.24.1': - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} + '@babel/plugin-transform-block-scoped-functions@7.24.7': + resolution: {integrity: sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.24.5': - resolution: {integrity: sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==} + '@babel/plugin-transform-block-scoping@7.25.0': + resolution: {integrity: sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.24.1': - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} + '@babel/plugin-transform-class-properties@7.25.4': + resolution: {integrity: sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.24.4': - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} + '@babel/plugin-transform-class-static-block@7.24.7': + resolution: {integrity: sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.24.5': - resolution: {integrity: sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==} + '@babel/plugin-transform-classes@7.25.4': + resolution: {integrity: sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.24.1': - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} + '@babel/plugin-transform-computed-properties@7.24.7': + resolution: {integrity: sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.24.5': - resolution: {integrity: sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==} + '@babel/plugin-transform-destructuring@7.24.8': + resolution: {integrity: sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.24.1': - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} + '@babel/plugin-transform-dotall-regex@7.24.7': + resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.24.1': - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} + '@babel/plugin-transform-duplicate-keys@7.24.7': + resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dynamic-import@7.24.1': - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0': + resolution: {integrity: sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.24.7': + resolution: {integrity: sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.24.1': - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} + '@babel/plugin-transform-exponentiation-operator@7.24.7': + resolution: {integrity: sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.24.1': - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} + '@babel/plugin-transform-export-namespace-from@7.24.7': + resolution: {integrity: sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.24.1': - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} + '@babel/plugin-transform-for-of@7.24.7': + resolution: {integrity: sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.24.1': - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} + '@babel/plugin-transform-function-name@7.25.1': + resolution: {integrity: sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.24.1': - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} + '@babel/plugin-transform-json-strings@7.24.7': + resolution: {integrity: sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.24.1': - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} + '@babel/plugin-transform-literals@7.25.2': + resolution: {integrity: sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.24.1': - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} + '@babel/plugin-transform-logical-assignment-operators@7.24.7': + resolution: {integrity: sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-member-expression-literals@7.24.1': - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} + '@babel/plugin-transform-member-expression-literals@7.24.7': + resolution: {integrity: sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-amd@7.24.1': - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} + '@babel/plugin-transform-modules-amd@7.24.7': + resolution: {integrity: sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.24.1': - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} + '@babel/plugin-transform-modules-commonjs@7.24.8': + resolution: {integrity: sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.24.1': - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} + '@babel/plugin-transform-modules-systemjs@7.25.0': + resolution: {integrity: sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-umd@7.24.1': - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} + '@babel/plugin-transform-modules-umd@7.24.7': + resolution: {integrity: sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5': - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-named-capturing-groups-regex@7.24.7': + resolution: {integrity: sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.24.1': - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} + '@babel/plugin-transform-new-target@7.24.7': + resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.24.1': - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} + '@babel/plugin-transform-nullish-coalescing-operator@7.24.7': + resolution: {integrity: sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.24.1': - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} + '@babel/plugin-transform-numeric-separator@7.24.7': + resolution: {integrity: sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.24.5': - resolution: {integrity: sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==} + '@babel/plugin-transform-object-rest-spread@7.24.7': + resolution: {integrity: sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.24.1': - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} + '@babel/plugin-transform-object-super@7.24.7': + resolution: {integrity: sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.24.1': - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} + '@babel/plugin-transform-optional-catch-binding@7.24.7': + resolution: {integrity: sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.24.5': - resolution: {integrity: sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==} + '@babel/plugin-transform-optional-chaining@7.24.8': + resolution: {integrity: sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.24.5': - resolution: {integrity: sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==} + '@babel/plugin-transform-parameters@7.24.7': + resolution: {integrity: sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.24.1': - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} + '@babel/plugin-transform-private-methods@7.25.4': + resolution: {integrity: sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.24.5': - resolution: {integrity: sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==} + '@babel/plugin-transform-private-property-in-object@7.24.7': + resolution: {integrity: sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.24.1': - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} + '@babel/plugin-transform-property-literals@7.24.7': + resolution: {integrity: sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-constant-elements@7.24.1': - resolution: {integrity: sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA==} + '@babel/plugin-transform-react-constant-elements@7.25.1': + resolution: {integrity: sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-display-name@7.24.1': - resolution: {integrity: sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==} + '@babel/plugin-transform-react-display-name@7.24.7': + resolution: {integrity: sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-development@7.22.5': - resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} + '@babel/plugin-transform-react-jsx-development@7.24.7': + resolution: {integrity: sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx@7.23.4': - resolution: {integrity: sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==} + '@babel/plugin-transform-react-jsx@7.25.2': + resolution: {integrity: sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-pure-annotations@7.24.1': - resolution: {integrity: sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==} + '@babel/plugin-transform-react-pure-annotations@7.24.7': + resolution: {integrity: sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.24.1': - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} + '@babel/plugin-transform-regenerator@7.24.7': + resolution: {integrity: sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-reserved-words@7.24.1': - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} + '@babel/plugin-transform-reserved-words@7.24.7': + resolution: {integrity: sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.24.1': - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} + '@babel/plugin-transform-shorthand-properties@7.24.7': + resolution: {integrity: sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.24.1': - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} + '@babel/plugin-transform-spread@7.24.7': + resolution: {integrity: sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-sticky-regex@7.24.1': - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} + '@babel/plugin-transform-sticky-regex@7.24.7': + resolution: {integrity: sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-template-literals@7.24.1': - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} + '@babel/plugin-transform-template-literals@7.24.7': + resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.24.5': - resolution: {integrity: sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==} + '@babel/plugin-transform-typeof-symbol@7.24.8': + resolution: {integrity: sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.24.5': - resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==} + '@babel/plugin-transform-typescript@7.25.2': + resolution: {integrity: sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.24.1': - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} + '@babel/plugin-transform-unicode-escapes@7.24.7': + resolution: {integrity: sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.24.1': - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} + '@babel/plugin-transform-unicode-property-regex@7.24.7': + resolution: {integrity: sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-regex@7.24.1': - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} + '@babel/plugin-transform-unicode-regex@7.24.7': + resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.24.1': - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} + '@babel/plugin-transform-unicode-sets-regex@7.25.4': + resolution: {integrity: sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.24.5': - resolution: {integrity: sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==} + '@babel/preset-env@7.25.4': + resolution: {integrity: sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2456,14 +2437,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/preset-react@7.24.1': - resolution: {integrity: sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==} + '@babel/preset-react@7.24.7': + resolution: {integrity: sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-typescript@7.24.1': - resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} + '@babel/preset-typescript@7.24.7': + resolution: {integrity: sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2471,43 +2452,47 @@ packages: '@babel/regjsgen@0.8.0': resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - '@babel/runtime@7.24.5': - resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + '@babel/runtime@7.25.4': + resolution: {integrity: sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.25.0': + resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} - '@babel/template@7.24.0': - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + '@babel/traverse@7.25.4': + resolution: {integrity: sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.5': - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} + '@babel/types@7.24.8': + resolution: {integrity: sha512-SkSBEHwwJRU52QEVZBmMBnE5Ux2/6WU1grdYyOhpbCNxbmJrDuDCphBzKZSO3taf0zztp+qkWlymE5tVL5l0TA==} engines: {node: '>=6.9.0'} - '@babel/types@7.23.6': - resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + '@babel/types@7.25.2': + resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.5': - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + '@babel/types@7.25.4': + resolution: {integrity: sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@bugsnag/browser@7.22.7': - resolution: {integrity: sha512-70jFkWKscK2osm7bnFbPLevrzHClrygM3UcKetKs/l81Xuzlxnu1SS3onN5OUl9kd9RN4XMFr46Pv5jSqWqImQ==} + '@bugsnag/browser@7.25.0': + resolution: {integrity: sha512-PzzWy5d9Ly1CU1KkxTB6ZaOw/dO+CYSfVtqxVJccy832e6+7rW/dvSw5Jy7rsNhgcKSKjZq86LtNkPSvritOLA==} - '@bugsnag/core@7.22.7': - resolution: {integrity: sha512-9DPWBkkBjhFJc5dCFy/wVC3HE0Aw3ZiLJKjyAxgywSKbILgtpD+qT1Xe8sacWyxU92znamlZ8H8ziQOe7jhhbA==} + '@bugsnag/core@7.25.0': + resolution: {integrity: sha512-JZLak1b5BVzy77CPcklViZrppac/pE07L3uSDmfSvFYSCGReXkik2txOgV05VlF9EDe36dtUAIIV7iAPDfFpQQ==} '@bugsnag/cuid@3.1.1': resolution: {integrity: sha512-d2z4b0rEo3chI07FNN1Xds8v25CNeekecU6FC/2Fs9MxY2EipkZTThVcV2YinMn8dvRUlViKOyC50evoUxg8tw==} - '@bugsnag/js@7.22.7': - resolution: {integrity: sha512-Qq8l06rSDTZtxgNIDpTeXHrin9C30INNbPfnR2CNcEsCmfqyVQb4USPEuRb0xg5wiaLKU9r4IAatMqiCgdzG6A==} + '@bugsnag/js@7.25.0': + resolution: {integrity: sha512-d8n8SyKdRUz8jMacRW1j/Sj/ckhKbIEp49+Dacp3CS8afRgfMZ//NXhUFFXITsDP5cXouaejR9fx4XVapYXNgg==} - '@bugsnag/node@7.22.7': - resolution: {integrity: sha512-Ud8vpX9UkGxoWAk7OigyR7w1eycbsE5uv5KZx0aWiqDPXylvICd42V5ZiWstpkdm9IVFo9AQ4+gmerHPe4Lwrg==} + '@bugsnag/node@7.25.0': + resolution: {integrity: sha512-KlxBaJ8EREEsfKInybAjTO9LmdDXV3cUH5+XNXyqUZrcRVuPOu4j4xvljh+n24ifok/wbFZTKVXUzrN4iKIeIA==} '@bugsnag/safe-json-stringify@6.0.0': resolution: {integrity: sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==} @@ -2518,11 +2503,11 @@ packages: '@bundled-es-modules/statuses@1.0.1': resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} - '@changesets/apply-release-plan@7.0.0': - resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} + '@changesets/apply-release-plan@7.0.4': + resolution: {integrity: sha512-HLFwhKWayKinWAul0Vj+76jVx1Pc2v55MGPVjZ924Y/ROeSsBMFutv9heHmCUj48lJyRfOTJG5+ar+29FUky/A==} - '@changesets/assemble-release-plan@6.0.0': - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + '@changesets/assemble-release-plan@6.0.3': + resolution: {integrity: sha512-bLNh9/Lgl1VwkjWZTq8JmRqH+hj7/Yzfz0jsQ/zJJ+FTmVqmqPj3szeKOri8O/hEM8JmHW019vh2gTO9iq5Cuw==} '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} @@ -2530,24 +2515,24 @@ packages: '@changesets/changelog-github@0.5.0': resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - '@changesets/cli@2.27.1': - resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} + '@changesets/cli@2.27.7': + resolution: {integrity: sha512-6lr8JltiiXPIjDeYg4iM2MeePP6VN/JkmqBsVA5XRiy01hGS3y629LtSDvKcycj/w/5Eur1rEwby/MjcYS+e2A==} hasBin: true - '@changesets/config@3.0.0': - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + '@changesets/config@3.0.2': + resolution: {integrity: sha512-cdEhS4t8woKCX2M8AotcV2BOWnBp09sqICxKapgLHf9m5KdENpWjyrFNMjkLqGJtUys9U+w93OxWT0czorVDfw==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - '@changesets/get-dependents-graph@2.0.0': - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + '@changesets/get-dependents-graph@2.1.1': + resolution: {integrity: sha512-LRFjjvigBSzfnPU2n/AhFsuWR5DK++1x47aq6qZ8dzYsPtS/I5mNhIGAS68IAxh1xjO9BTtz55FwefhANZ+FCA==} '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.0': - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + '@changesets/get-release-plan@4.0.3': + resolution: {integrity: sha512-6PLgvOIwTSdJPTtpdcr3sLtGatT+Jr22+cQwEBJBy6wP0rjB4yJ9lv583J9fVpn1bfQlBkDa8JxbS2g/n9lIyA==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -2567,14 +2552,17 @@ packages: '@changesets/read@0.6.0': resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + '@changesets/should-skip-package@0.1.0': + resolution: {integrity: sha512-FxG6Mhjw7yFStlSM7Z0Gmg3RiyQ98d/9VpQAZ3Fzr59dCOM9G6ZdYbjiSAt0XtFr9JR5U2tBaJWPjrkGGc618g==} + '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} '@changesets/types@6.0.0': resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - '@changesets/write@0.3.0': - resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} + '@changesets/write@0.3.1': + resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} @@ -2595,25 +2583,21 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@ericcornelissen/bash-parser@0.5.2': - resolution: {integrity: sha512-4pIMTa1nEFfMXitv7oaNEWOdM+zpOZavesa5GaiWTgda6Zk32CFGxjUp/iIaN0PwgUW1yTq/fztSjbpE8SLGZQ==} - engines: {node: '>=4'} - '@esbuild/aix-ppc64@0.19.11': resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.19.12': - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + '@esbuild/aix-ppc64@0.21.2': + resolution: {integrity: sha512-/c7hocx0pm14bHQlqUVKmxwdT/e5/KkyoY1W8F9lk/8CkE037STDDz8PXUP/LE6faj2HqchvDs9GcShxFhI78Q==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.20.2': - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -2623,15 +2607,15 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.19.12': - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + '@esbuild/android-arm64@0.21.2': + resolution: {integrity: sha512-SGZKngoTWVUriO5bDjI4WDGsNx2VKZoXcds+ita/kVYB+8IkSCKDRDaK+5yu0b5S0eq6B3S7fpiEvpsa2ammlQ==} engines: {node: '>=12'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.20.2': - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -2641,15 +2625,15 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.19.12': - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + '@esbuild/android-arm@0.21.2': + resolution: {integrity: sha512-G1ve3b4FeyJeyCjB4MX1CiWyTaIJwT9wAYE+8+IRA53YoN/reC/Bf2GDRXAzDTnh69Fpl+1uIKg76DiB3U6vwQ==} engines: {node: '>=12'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.20.2': - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} cpu: [arm] os: [android] @@ -2659,15 +2643,15 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.19.12': - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + '@esbuild/android-x64@0.21.2': + resolution: {integrity: sha512-1wzzNoj2QtNkAYwIcWJ66UTRA80+RTQ/kuPMtEuP0X6dp5Ar23Dn566q3aV61h4EYrrgGlOgl/HdcqN/2S/2vg==} engines: {node: '>=12'} cpu: [x64] os: [android] - '@esbuild/android-x64@0.20.2': - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} cpu: [x64] os: [android] @@ -2677,15 +2661,15 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.19.12': - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + '@esbuild/darwin-arm64@0.21.2': + resolution: {integrity: sha512-ZyMkPWc5eTROcLOA10lEqdDSTc6ds6nuh3DeHgKip/XJrYjZDfnkCVSty8svWdy+SC1f77ULtVeIqymTzaB6/Q==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.20.2': - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -2695,15 +2679,15 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.19.12': - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + '@esbuild/darwin-x64@0.21.2': + resolution: {integrity: sha512-K4ZdVq1zP9v51h/cKVna7im7G0zGTKKB6bP2yJiSmHjjOykbd8DdhrSi8V978sF69rkwrn8zCyL2t6I3ei6j9A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.20.2': - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -2713,15 +2697,15 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.19.12': - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + '@esbuild/freebsd-arm64@0.21.2': + resolution: {integrity: sha512-4kbOGdpA61CXqadD+Gb/Pw3YXamQGiz9mal/h93rFVSjr5cgMnmJd/gbfPRm+3BMifvnaOfS1gNWaIDxkE2A3A==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.20.2': - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -2731,15 +2715,15 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.19.12': - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + '@esbuild/freebsd-x64@0.21.2': + resolution: {integrity: sha512-ShS+R09nuHzDBfPeMUliKZX27Wrmr8UFp93aFf/S8p+++x5BZ+D344CLKXxmY6qzgTL3mILSImPCNJOzD6+RRg==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.20.2': - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -2749,15 +2733,15 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.19.12': - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + '@esbuild/linux-arm64@0.21.2': + resolution: {integrity: sha512-Hdu8BL+AmO+eCDvvT6kz/fPQhvuHL8YK4ExKZfANWsNe1kFGOHw7VJvS/FKSLFqheXmB3rTF3xFQIgUWPYsGnA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.20.2': - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -2767,15 +2751,15 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.19.12': - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + '@esbuild/linux-arm@0.21.2': + resolution: {integrity: sha512-nnGXjOAv+7cM3LYRx4tJsYdgy8dGDGkAzF06oIDGppWbUkUKN9SmgQA8H0KukpU0Pjrj9XmgbWqMVSX/U7eeTA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.20.2': - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -2785,15 +2769,15 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.19.12': - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + '@esbuild/linux-ia32@0.21.2': + resolution: {integrity: sha512-m73BOCW2V9lcj7RtEMi+gBfHC6n3+VHpwQXP5offtQMPLDkpVolYn1YGXxOZ9hp4h3UPRKuezL7WkBsw+3EB3Q==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.20.2': - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -2803,15 +2787,15 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.19.12': - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + '@esbuild/linux-loong64@0.21.2': + resolution: {integrity: sha512-84eYHwwWHq3myIY/6ikALMcnwkf6Qo7NIq++xH0x+cJuUNpdwh8mlpUtRY+JiGUc60yu7ElWBbVHGWTABTclGw==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.20.2': - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -2821,15 +2805,15 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.19.12': - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + '@esbuild/linux-mips64el@0.21.2': + resolution: {integrity: sha512-9siSZngT0/ZKG+AH+/agwKF29LdCxw4ODi/PiE0F52B2rtLozlDP92umf8G2GPoVV611LN4pZ+nSTckebOscUA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.20.2': - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -2839,15 +2823,15 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.19.12': - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + '@esbuild/linux-ppc64@0.21.2': + resolution: {integrity: sha512-y0T4aV2CA+ic04ULya1A/8M2RDpDSK2ckgTj6jzHKFJvCq0jQg8afQQIn4EM0G8u2neyOiNHgSF9YKPfuqKOVw==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.20.2': - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -2857,15 +2841,15 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.19.12': - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + '@esbuild/linux-riscv64@0.21.2': + resolution: {integrity: sha512-x5ssCdXmZC86L2Li1qQPF/VaC4VP20u/Zm8jlAu9IiVOVi79YsSz6cpPDYZl1rfKSHYCJW9XBfFCo66S5gVPSA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.20.2': - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -2875,15 +2859,15 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.19.12': - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + '@esbuild/linux-s390x@0.21.2': + resolution: {integrity: sha512-NP7fTpGSFWdXyvp8iAFU04uFh9ARoplFVM/m+8lTRpaYG+2ytHPZWyscSsMM6cvObSIK2KoPHXiZD4l99WaxbQ==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.20.2': - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -2893,15 +2877,15 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.19.12': - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + '@esbuild/linux-x64@0.21.2': + resolution: {integrity: sha512-giZ/uOxWDKda44ZuyfKbykeXznfuVNkTgXOUOPJIjbayJV6FRpQ4zxUy9JMBPLaK9IJcdWtaoeQrYBMh3Rr4vQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.20.2': - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -2911,33 +2895,39 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.19.12': - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + '@esbuild/netbsd-x64@0.21.2': + resolution: {integrity: sha512-IeFMfGFSQfIj1d4XU+6lkbFzMR+mFELUUVYrZ+jvWzG4NGvs6o53ReEHLHpYkjRbdEjJy2W3lTekTxrFHW7YJg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.20.2': - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.19.11': resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.19.12': - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + '@esbuild/openbsd-x64@0.21.2': + resolution: {integrity: sha512-48QhWD6WxcebNNaE4FCwgvQVUnAycuTd+BdvA/oZu+/MmbpU8pY2dMEYlYzj5uNHWIG5jvdDmFXu0naQeOWUoA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.20.2': - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -2947,15 +2937,15 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.19.12': - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + '@esbuild/sunos-x64@0.21.2': + resolution: {integrity: sha512-90r3nTBLgdIgD4FCVV9+cR6Hq2Dzs319icVsln+NTmTVwffWcCqXGml8rAoocHuJ85kZK36DCteii96ba/PX8g==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.20.2': - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -2965,15 +2955,15 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.19.12': - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + '@esbuild/win32-arm64@0.21.2': + resolution: {integrity: sha512-sNndlsBT8OeE/MZDSGpRDJlWuhjuUz/dn80nH0EP4ZzDUYvMDVa7G87DVpweBrn4xdJYyXS/y4CQNrf7R2ODXg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.20.2': - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -2983,15 +2973,15 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.19.12': - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + '@esbuild/win32-ia32@0.21.2': + resolution: {integrity: sha512-Ti2QChGNFzWhUNNVuU4w21YkYTErsNh3h+CzvlEhzgRbwsJ7TrWQqRzW3bllLKKvTppuF3DJ3XP1GEg11AfrEQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.20.2': - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -3001,15 +2991,15 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.19.12': - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + '@esbuild/win32-x64@0.21.2': + resolution: {integrity: sha512-VEfTCZicoZnZ6sGkjFPGRFFJuL2fZn2bLhsekZl1CJslflp2cJS/VoKs1jMk+3pDfsGW6CfQVUckP707HwbXeQ==} engines: {node: '>=12'} cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.20.2': - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -3019,8 +3009,8 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/eslintrc@2.1.4': @@ -3035,8 +3025,8 @@ packages: resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} engines: {node: '>=14'} - '@fastify/ajv-compiler@3.5.0': - resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} + '@fastify/ajv-compiler@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} '@fastify/error@3.4.1': resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} @@ -3050,20 +3040,20 @@ packages: '@fastify/send@2.1.0': resolution: {integrity: sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==} - '@fastify/static@6.12.0': - resolution: {integrity: sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ==} + '@fastify/static@7.0.4': + resolution: {integrity: sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==} - '@formatjs/ecma402-abstract@1.18.2': - resolution: {integrity: sha512-+QoPW4csYALsQIl8GbN14igZzDbuwzcpWrku9nyMXlaqAlwRBgl5V+p0vWMGFqHOw37czNXaP/lEk4wbLgcmtA==} + '@formatjs/ecma402-abstract@2.0.0': + resolution: {integrity: sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==} '@formatjs/fast-memoize@2.2.0': resolution: {integrity: sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==} - '@formatjs/icu-messageformat-parser@2.7.6': - resolution: {integrity: sha512-etVau26po9+eewJKYoiBKP6743I1br0/Ie00Pb/S/PtmYfmjTcOn2YCh2yNkSZI12h6Rg+BOgQYborXk46BvkA==} + '@formatjs/icu-messageformat-parser@2.7.8': + resolution: {integrity: sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==} - '@formatjs/icu-skeleton-parser@1.8.0': - resolution: {integrity: sha512-QWLAYvM0n8hv7Nq5BEs4LKIjevpVpbGLAJgOaYzg9wABEoX1j0JO1q2/jVkO6CVlq0dbsxZCngS5aXbysYueqA==} + '@formatjs/icu-skeleton-parser@1.8.2': + resolution: {integrity: sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==} '@formatjs/intl-localematcher@0.5.4': resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==} @@ -3071,6 +3061,7 @@ packages: '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -3082,6 +3073,7 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} @@ -3089,33 +3081,33 @@ packages: '@import-maps/resolve@1.0.1': resolution: {integrity: sha512-tWZNBIS1CoekcwlMuyG2mr0a1Wo5lb5lEHwwWvZo+5GLgr3e9LLDTtmgtCWEwBpXMkxn9D+2W9j2FY6eZQq0tA==} - '@inquirer/confirm@3.1.6': - resolution: {integrity: sha512-Mj4TU29g6Uy+37UtpA8UpEOI2icBfpCwSW1QDtfx60wRhUy90s/kHPif2OXSSvuwDQT1lhAYRWUfkNf9Tecxvg==} + '@inquirer/confirm@3.1.22': + resolution: {integrity: sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==} engines: {node: '>=18'} - '@inquirer/core@8.1.0': - resolution: {integrity: sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==} + '@inquirer/core@9.0.10': + resolution: {integrity: sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==} engines: {node: '>=18'} - '@inquirer/figures@1.0.1': - resolution: {integrity: sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==} + '@inquirer/figures@1.0.5': + resolution: {integrity: sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==} engines: {node: '>=18'} - '@inquirer/type@1.3.1': - resolution: {integrity: sha512-Pe3PFccjPVJV1vtlfVvm9OnlbxqdnP5QcscFEFEnK5quChf1ufZtM0r8mR5ToWHMxZOh0s8o/qp9ANGRTo/DAw==} + '@inquirer/type@1.5.2': + resolution: {integrity: sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==} engines: {node: '>=18'} - '@internationalized/date@3.5.3': - resolution: {integrity: sha512-X9bi8NAEHAjD8yzmPYT2pdJsbe+tYSEBAfowtlxJVJdZR3aK8Vg7ZUT1Fm5M47KLzp/M1p1VwAaeSma3RT7biw==} + '@internationalized/date@3.5.5': + resolution: {integrity: sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==} - '@internationalized/message@3.1.3': - resolution: {integrity: sha512-jba3kGxnh4hN4zoeJZuMft99Ly1zbmon4fyDz3VAmO39Kb5Aw+usGub7oU/sGoBIcVQ7REEwsvjIWtIO1nitbw==} + '@internationalized/message@3.1.4': + resolution: {integrity: sha512-Dygi9hH1s7V9nha07pggCkvmRfDd3q2lWnMGvrJyrOwYMe1yj4D2T9BoH9I6MGR7xz0biQrtLPsqUkqXzIrBOw==} - '@internationalized/number@3.5.2': - resolution: {integrity: sha512-4FGHTi0rOEX1giSkt5MH4/te0eHBq3cvAYsfLlpguV6pzJAReXymiYpE5wPCqKqjkUO3PIsyvk+tBiIV1pZtbA==} + '@internationalized/number@3.5.3': + resolution: {integrity: sha512-rd1wA3ebzlp0Mehj5YTuTI50AQEx80gWFyHcQu+u91/5NgdwBecO8BH6ipPfE+lmQ9d63vpB3H9SHoIUiupllw==} - '@internationalized/string@3.2.2': - resolution: {integrity: sha512-5xy2JfSQyGqL9FDIdJXVjoKSBBDJR4lvwoCbqKhc5hQZ/qSLU/OlONCmrJPcSH0zxh88lXJMzbOAk8gJ48JBFw==} + '@internationalized/string@3.2.3': + resolution: {integrity: sha512-9kpfLoA8HegiWTeCbR2livhdVeKobCnVv8tlJ6M2jF+4tcMqDo94ezwlnrUANBWPgd8U7OXIHCk2Ov2qhk4KXw==} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -3218,8 +3210,8 @@ packages: '@jridgewell/source-map@0.3.6': resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -3227,20 +3219,20 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@jsonjoy.com/base64@1.1.1': - resolution: {integrity: sha512-LnFjVChaGY8cZVMwAIMjvA1XwQjZ/zIXHyh28IyJkyNkzof4Dkm1+KN9UIm3lHhREH4vs7XwZ0NpkZKnwOtEfg==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/json-pack@1.0.3': - resolution: {integrity: sha512-Q0SPAdmK6s5Fe3e1kcNvwNyk6e2+CxM8XZdGbf4abZG7nUO05KSie3/iX29loTBuY+75uVP6RixDSPVpotfzmQ==} + '@jsonjoy.com/json-pack@1.1.0': + resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/util@1.1.2': - resolution: {integrity: sha512-HOGa9wtE6LEz2I5mMQ2pMSjth85PmD71kPbsecs02nEUq3/Kw0wRK3gmZn5BCEB8mFLXByqPxjHgApoMwIPMKQ==} + '@jsonjoy.com/util@1.3.0': + resolution: {integrity: sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -3262,12 +3254,24 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true + '@module-federation/bridge-react-webpack-plugin@0.2.6': + resolution: {integrity: sha512-AVpUEqZesRF4MJivq8bgYZOJaGccvD2CT4uBdsnTfLy3JZumi3v+l6A6LzxLWMOVroHN9KZ9JjfOWz/mCKAI2w==} + '@module-federation/dts-plugin@0.1.11': resolution: {integrity: sha512-Lv8oTNOFx4MEXBCOYtpecWzQGsUXG8QxHXMUGQwAPNeYvdtnR+l38m04Jc9bM/jlvVt+ScM7mV5EybnvmcS3cw==} peerDependencies: typescript: ^4.9.0 || ^5.0.0 vue-tsc: ^1.0.24 + '@module-federation/dts-plugin@0.2.6': + resolution: {integrity: sha512-I086OwfTaIoVrH/SZ0pMFEJFQ1PvE04a8ggrsB1qu1mJ38Rb7r/OgD4zv8qomYa7oLf7BEPDHQ2I1N9RqzKssA==} + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ^1.0.24 + peerDependenciesMeta: + vue-tsc: + optional: true + '@module-federation/enhanced@0.1.11': resolution: {integrity: sha512-wVeovWMgHsu5uBZI3u7G/lBlA3JWjDy7hyLGeT38/jcD2WPx8U66W9jIqiVI0sn+4Yznznb2K+rNFeD7hTYBGQ==} peerDependencies: @@ -3276,56 +3280,90 @@ packages: webpack: optional: true + '@module-federation/enhanced@0.2.6': + resolution: {integrity: sha512-8RWNx9a50FkG+l2cux8prIzIt26RFku4sGdTF6wGnlUtvRLkgzhr17GxXPX1pEwq64kjdRD3+3QmZrne8XCPZA==} + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ^1.0.24 + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + webpack: + optional: true + '@module-federation/managers@0.1.11': resolution: {integrity: sha512-29mP2rZVFMu10CAiljZiD19r1ynHreF4fBaXWSrLRCRRZSgRv4XMJV5s9RJ8OetygI6j9OuZmPG1RTUsSZLTmw==} + '@module-federation/managers@0.2.6': + resolution: {integrity: sha512-zg8nwAIMkO9SrQbf78Pxtb3fmABSpauDxtmTUQxNVE1PD6DnF83Ph7z4B6F2IbblfP8SijgxKrdOF5bh/5t9GQ==} + '@module-federation/manifest@0.1.11': resolution: {integrity: sha512-RM4ef0Za0DD7QCGp9eR6gy1B5VX3DxkjRgJpZ04Kh/Xaa1ewnKkSejzYpEvD+bLCir8QViv0lrnH55ln7pLn/Q==} + '@module-federation/manifest@0.2.6': + resolution: {integrity: sha512-mhQvbmewAQHmEsocAqWIxAJdhvTJ0Y+1mDBLHIhXaz7ToXxFtO6rbnTJ5A+iTqqLKSUPrjhtNqffr3wkDHn9Sg==} + '@module-federation/rspack@0.1.11': resolution: {integrity: sha512-+2uYviFL8mib8iBYd9kNBPmkOUxmH66XjZyN9ZZMtIo6znqfkIQrWZ1H0VRULTUp/EQilzYZ4bf33NU+V5DS7Q==} + '@module-federation/rspack@0.2.6': + resolution: {integrity: sha512-iAVFUtLo4G7S5RQkq3ov/816dNIV1bOUgIU8+1lSZx3eHSveRmndZ/+4fAwBwgYJd98X4LschCqN/lr6IcQ1rQ==} + '@module-federation/runtime-tools@0.1.11': resolution: {integrity: sha512-CvEF35WF5mmadH2qXdgDYa1M+AWNh3Tu+krVTegngixmEYX8OIaB0x4U+9QNA3Bs4GHsR86f7VrT29TY4elUCA==} + '@module-federation/runtime-tools@0.2.6': + resolution: {integrity: sha512-L7ovmhPn+cx/VY3J042KpmcZzu0h3VNtZRoQ1dmP+oKRtbKtvKTXiUH2MTbwMd6p4e9bVdwdXVXUK5zR1o3V7A==} + '@module-federation/runtime@0.1.11': resolution: {integrity: sha512-oHsPHAzIKM2arTZZaa22Xn0A189q/bxxX93YJjIawyms/NMaIhEvs7PDz5loOgEuAWP4q1h960hG/aRwFuxwAA==} + '@module-federation/runtime@0.2.6': + resolution: {integrity: sha512-G0vIZC6H5cmAa71vu7163CmnYFoZ5rAUDqYqQMMFLJ7ndw+QtrB3FLkgG99Smr+HTZECpt3s8HX7A40eHhTRUA==} + '@module-federation/sdk@0.1.11': resolution: {integrity: sha512-IdJmRX+WGmKDrXq3jEOvjB11YrVmysjSnostY5u5tBz7cSO1nTZz+oEBqQdkXvNyPY2R8FErtD7G5gdtQH1k7Q==} + '@module-federation/sdk@0.2.6': + resolution: {integrity: sha512-PvMWzEILKRKrmB3olRWNTfCJVoNHbDMa1l3/mE4eZUlerTjeP+H5QIxHXstFz7679WZ1Cq/cMrku/L+jP6NXxw==} + '@module-federation/third-party-dts-extractor@0.1.11': resolution: {integrity: sha512-Sly7k9qBaoexFG66N57ppHzuWYaYABqydMzzgmSg8OlHYhfckC7ug949xpw1oq0gj+i6WE+8Ork4wtyzDXJTiw==} + '@module-federation/third-party-dts-extractor@0.2.6': + resolution: {integrity: sha512-ro2fFJbGTNHmxreVhugC5ju8GGJZGFVayKqDrrRLjj600gt8vDDnwkqQPuNyc37w7eIHP06Y2ixzkk3FvW3paA==} + '@module-federation/webpack-bundler-runtime@0.1.11': resolution: {integrity: sha512-xgQoCCwv+5Vjv7pKtQh9LTBZOvyVdhs7D80oOdJbN1YXL0PRoNE20RjOH7CwGcu8/Yc99PVCAKS25rai+DzEGw==} - '@mswjs/cookies@1.1.0': - resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} - engines: {node: '>=18'} + '@module-federation/webpack-bundler-runtime@0.2.6': + resolution: {integrity: sha512-OEhoQr6OZxHfO/ZNuLqNF6THAXqP3WSySajW/oDmX20MGaFOXFCldeDOQz7+Kqaio5sICHWnhXKbNfR7/+686A==} - '@mswjs/interceptors@0.26.15': - resolution: {integrity: sha512-HM47Lu1YFmnYHKMBynFfjCp0U/yRskHj/8QEJW0CBEPOlw8Gkmjfll+S9b8M7V5CNDw2/ciRxjjnWeaCiblSIQ==} + '@mswjs/cookies@1.1.1': + resolution: {integrity: sha512-W68qOHEjx1iD+4VjQudlx26CPIoxmIAtK4ZCexU0/UJBG6jYhcuyzKJx+Iw8uhBIGd9eba64XgWVgo20it1qwA==} engines: {node: '>=18'} - '@mswjs/interceptors@0.27.2': - resolution: {integrity: sha512-mE6PhwcoW70EX8+h+Y/4dLfHk33GFt/y5PzDJz56ktMyaVGFXMJ5BYLbUjdmGEABfE0x5GgAGyKbrbkYww2s3A==} + '@mswjs/interceptors@0.29.1': + resolution: {integrity: sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==} engines: {node: '>=18'} '@netlify/binary-info@1.0.0': resolution: {integrity: sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw==} - '@netlify/blobs@7.3.0': - resolution: {integrity: sha512-wN/kNTZo4xjlUM/C0WILOkJbe8p4AFquSGkZEIoIcgnsx5ikp2GyqGiq1WMLee7QdbnqeIV2g2hn/PjT324E5w==} + '@netlify/blobs@7.4.0': + resolution: {integrity: sha512-7rdPzo8bggt3D2CVO+U1rmEtxxs8X7cLusDbHZRJaMlxqxBD05mXgThj5DUJMFOvmfVjhEH/S/3AyiLUbDQGDg==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/build-info@7.13.2': - resolution: {integrity: sha512-smzhIgcms6Z/v2cct90l8ncBbnA5kvknj5/quhwyM6UHUycgMKFlA22qkB0KLj9shwL1Lkh7iQW751JwhSaP9g==} + '@netlify/build-info@7.14.1': + resolution: {integrity: sha512-0FhHK8+v80pDt0hkN4s5+sFUL5OF8bVU4bqwqDx04NiSQ/jOUSwCZ70F5MHkbvjuqf4RoP0vVKqrvIB3EP0wyA==} engines: {node: ^14.16.0 || >=16.0.0} hasBin: true - '@netlify/build@29.41.2': - resolution: {integrity: sha512-txcYS00PXfmfw9hIxc4Q5c8p4DLkaGqgX3yjGUH2y/2NXxJQxpZiZBBVYeVW5q0rwb+17trE2gQJ/xnOXo3O5Q==} + '@netlify/build@29.51.3': + resolution: {integrity: sha512-bHnQLeMv6yHsENU9HQw1JQ+I4RikgjIiqtWo5pPgLAt0ktm+UH+5eFrPZ61zdkSwqMWup06364+wUqTlj4q1hQ==} engines: {node: ^14.16.0 || >=16.0.0} hasBin: true peerDependencies: @@ -3335,28 +3373,28 @@ packages: '@netlify/opentelemetry-sdk-setup': optional: true - '@netlify/cache-utils@5.1.5': - resolution: {integrity: sha512-lMNdFmy2Yu3oVquSPooRDLxJ8QOsIX6X6vzA2pKz/9V2LQFJiqBukggXM+Rnqzk1regPpdJ0jK3dPGvOKaRQgg==} + '@netlify/cache-utils@5.1.6': + resolution: {integrity: sha512-0K1+5umxENy9H3CC+v5qGQbeTmKv/PBAhOxPKK6GPykOVa7OxT26KGMU7Jozo6pVNeLPJUvCCMw48ycwtQ1fvw==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/config@20.12.3': - resolution: {integrity: sha512-E+oiGEm6zIvyFJ2kQC1IV5Ipiv7Ar84RuP2K+aVMSgu/raOn7ZfN9lM5TC43qboF3bDrJd6EuYDxVIAuxVkMCA==} + '@netlify/config@20.17.1': + resolution: {integrity: sha512-uZuEYooSWVnyx54AdLwPd7mgHy/PrWjHvPy5AO0ApPYsokNVceuk7NX6xqkD0CuGwcc5K9oRQx91XDWQoWd2zQ==} engines: {node: ^14.16.0 || >=16.0.0} hasBin: true - '@netlify/edge-bundler@12.0.0': - resolution: {integrity: sha512-whAeq2gQxWz8Bt85XN8VJRBwhHpGlbmu7LRX4bFBgXPNWVi1a9UrQ+F51gHj9p+B01tsztVrKlxqA555Sg0dgg==} + '@netlify/edge-bundler@12.2.2': + resolution: {integrity: sha512-esaM7H/lViceghUR84ZTuNk3VkeVNy2BaCeV+/nWHFOXbEpMmlNML31hJswk79QRztV2XO1oLWu8PxtmURd7DA==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/edge-functions@2.5.1': - resolution: {integrity: sha512-6YGlbzxPaSqc/D2LhP4T4PXrim/vRmqpO1RwQKqVod6WCWlkdtJcAd3mGoI7efrjfND8twh7TqXtL7RRCI23qA==} + '@netlify/edge-functions@2.9.0': + resolution: {integrity: sha512-W1kdwLpvUlhfI2FTOe6SEcoobW7Fw+Vm9WN5Gwb5lTCG6QXBE3gpCZk+NVQ4p/XoOcXYwWAS5pfOTMKUoYNQnA==} - '@netlify/framework-info@9.8.11': - resolution: {integrity: sha512-8NuvzQQVeU36PRilWqijiIWmjy6JZcqbKooGQ4bNgH/26YNdS+tN5gOWGWVYnRHgdmBUCycyYrM5h1Srwnq3hQ==} + '@netlify/framework-info@9.8.13': + resolution: {integrity: sha512-ZZXCggokY/y5Sz93XYbl/Lig1UAUSWPMBiQRpkVfbrrkjmW2ZPkYS/BgrM2/MxwXRvYhc/TQpZX6y5JPe3quQg==} engines: {node: ^14.14.0 || >=16.0.0} - '@netlify/functions-utils@5.2.55': - resolution: {integrity: sha512-4xTb/zuUT5SFpZH+RGKUV6pwrYyGS3L4emcrVi5u/nbJ/8yU8v8MdUdTGxoUhyeFw1kIp5C6vsru1fpU0ti0XA==} + '@netlify/functions-utils@5.2.79': + resolution: {integrity: sha512-lpHlxN1LmRo/ah6thRQ2IeOYpXmRh5Eh3bZE/gSlCsKT4uOCwBQFI5lVXVXS2ZpNiGPydYgIzCblF18/w2drFg==} engines: {node: ^14.16.0 || >=16.0.0} '@netlify/git-utils@5.1.1': @@ -3442,30 +3480,35 @@ packages: resolution: {integrity: sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/open-api@2.30.0': - resolution: {integrity: sha512-SMRzNwaG6/2MTIBe/RThLQRm3kNpiwb90te+iDJgMLLfTdVA33P/oiinTypBMyQU4Cm3IvQm7P5zD2mXZacSsg==} + '@netlify/open-api@2.34.0': + resolution: {integrity: sha512-C4v7Od/vnGgZ1P4JK3Fn9uUi9HkTxeUqUtj4OLnGD+rGyaVrl4JY89xMCoVksijDtO8XylYFU59CSTnQNeNw7g==} engines: {node: '>=14'} - '@netlify/opentelemetry-utils@1.2.0': - resolution: {integrity: sha512-sdeYmvUHXzs7bfoh7f32WVh2wLMOdF3d2Xdcg2FG1lCySXOJ4V6F3n8vPoPXwO7S5iSzJbfO2RPJsTtZCmbIcg==} + '@netlify/opentelemetry-utils@1.2.1': + resolution: {integrity: sha512-A6nQBvUn/avHQopLOOjX8rY2eua//jufbx4NZZODACEHtfXAEmOjCoDe2m+cQPRq+jNa98nvCy/sJh2RwuCQog==} engines: {node: '>=18.0.0'} peerDependencies: '@opentelemetry/api': ~1.8.0 - '@netlify/plugins-list@6.78.0': - resolution: {integrity: sha512-VHd1G7oQKJ0oTowb2Sohu91CcYBR2lpLJ0E5Ep5NTwWYR7ymuoP+DAHlIbWlBznSS/AfHFR6SKdcShBOhqdgww==} + '@netlify/plugins-list@6.80.0': + resolution: {integrity: sha512-bCKLI51UZ70ziIWsf2nvgPd4XuG6m8AMCoHiYtl/BSsiaSBfmryZnTTqdRXerH09tBRpbPPwzaEgUJwyU9o8Qw==} engines: {node: ^14.14.0 || >=16.0.0} '@netlify/run-utils@5.1.1': resolution: {integrity: sha512-V2B8ZB19heVKa715uOeDkztxLH7uaqZ+9U5fV7BRzbQ2514DO5Vxj9hG0irzuRLfZXZZjp/chPUesv4VVsce/A==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/serverless-functions-api@1.18.0': - resolution: {integrity: sha512-VCU5btoGZ8M6iI7HSwpfZXCpBLKWFmRtq5xYt0K7dY96BZWVBmaZY6Tn+w4L2DrGXwAsIeOFNp8CHjVXfuCAkg==} + '@netlify/serverless-functions-api@1.22.0': + resolution: {integrity: sha512-vv8fWCOIadSvdmR+8UYopdyHO/gOysl+8IBOxUUB0B3y7nnLOiBniE1JBeBR3y7gI/q/cnibBF2RhR3W04Wo/A==} engines: {node: '>=18.0.0'} - '@netlify/zip-it-and-ship-it@9.32.1': - resolution: {integrity: sha512-zLsWEJYCoWbQ7ZM0WcPdXzXtIRp9Y2KvbGpL7iWYmTaLBDrmZtYDnUkoyG0E3b9zmuQp9EAiE6evBdRr6usiRg==} + '@netlify/zip-it-and-ship-it@9.37.7': + resolution: {integrity: sha512-d6PLXNFSjV5Q+maUMpyJeDybS1r8b6c7/qrIFPDpDioLnyxU97ur2gQ2cxn5WrlY0gfzLInRR7ipAa7MXdT3BQ==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + + '@netlify/zip-it-and-ship-it@9.38.0': + resolution: {integrity: sha512-xQK4O0rhAbzboKod/Dw7EwzwDKLki8ui+zTpA8iS5RtLMRtRUPI8P+aSScafwrt3HL3NHmNe8Pdd+0RYSTGQDQ==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -3473,28 +3516,20 @@ packages: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} - '@nodelib/fs.scandir@3.0.0': - resolution: {integrity: sha512-ktI9+PxfHYtKjF3cLTUAh2N+b8MijCRPNwKJNqTVdL0gB0QxLU2rIRaZ1t71oEa3YBDE6bukH1sR0+CDnpp/Mg==} - engines: {node: '>=16.14.0'} - '@nodelib/fs.stat@2.0.5': resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - '@nodelib/fs.stat@3.0.0': - resolution: {integrity: sha512-2tQOI38s19P9i7X/Drt0v8iMA+KMsgdhB/dyPER+e+2Y8L1Z7QvnuRdW/uLuf5YRFUYmnj4bMA6qCuZHFI1GDQ==} - engines: {node: '>=16.14.0'} - '@nodelib/fs.walk@1.2.8': resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@nodelib/fs.walk@2.0.0': - resolution: {integrity: sha512-54voNDBobGdMl3BUXSu7UaDh1P85PGHWlJ5e0XhPugo1JulOyCtp2I+5ri4wplGDJ8QGwPEQW7/x3yTLU7yF1A==} - engines: {node: '>=16.14.0'} + '@npmcli/config@8.3.4': + resolution: {integrity: sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==} + engines: {node: ^16.14.0 || >=18.0.0} - '@npmcli/config@8.3.1': - resolution: {integrity: sha512-lEY3TnkVrNUwI0vCDTFlKTbxK9DxZ83JmXXcQI7kp7pyg7zj/a36xSDmcikXvUbtV2PQpmUwmV0HDAB94NcgNA==} + '@npmcli/git@5.0.8': + resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/map-workspaces@3.0.6': @@ -3505,62 +3540,65 @@ packages: resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@octokit/auth-token@3.0.4': - resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==} - engines: {node: '>= 14'} + '@npmcli/package-json@5.2.0': + resolution: {integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==} + engines: {node: ^16.14.0 || >=18.0.0} - '@octokit/core@4.2.4': - resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==} - engines: {node: '>= 14'} + '@npmcli/promise-spawn@7.0.2': + resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} + engines: {node: ^16.14.0 || >=18.0.0} - '@octokit/endpoint@7.0.6': - resolution: {integrity: sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==} - engines: {node: '>= 14'} + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} - '@octokit/graphql@5.0.6': - resolution: {integrity: sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==} - engines: {node: '>= 14'} + '@octokit/core@5.2.0': + resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==} + engines: {node: '>= 18'} - '@octokit/openapi-types@18.1.1': - resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==} + '@octokit/endpoint@9.0.5': + resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} + engines: {node: '>= 18'} - '@octokit/plugin-paginate-rest@6.1.2': - resolution: {integrity: sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==} - engines: {node: '>= 14'} - peerDependencies: - '@octokit/core': '>=4' + '@octokit/graphql@7.1.0': + resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==} + engines: {node: '>= 18'} - '@octokit/plugin-request-log@1.0.4': - resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} - peerDependencies: - '@octokit/core': '>=3' + '@octokit/openapi-types@22.2.0': + resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} - '@octokit/plugin-rest-endpoint-methods@7.2.3': - resolution: {integrity: sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==} - engines: {node: '>= 14'} + '@octokit/plugin-paginate-rest@11.3.1': + resolution: {integrity: sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==} + engines: {node: '>= 18'} peerDependencies: - '@octokit/core': '>=3' + '@octokit/core': '5' - '@octokit/request-error@3.0.3': - resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==} - engines: {node: '>= 14'} + '@octokit/plugin-request-log@4.0.1': + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' - '@octokit/request@6.2.8': - resolution: {integrity: sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==} - engines: {node: '>= 14'} + '@octokit/plugin-rest-endpoint-methods@13.2.2': + resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5 - '@octokit/rest@19.0.13': - resolution: {integrity: sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==} - engines: {node: '>= 14'} + '@octokit/request-error@5.1.0': + resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} + engines: {node: '>= 18'} - '@octokit/tsconfig@1.0.2': - resolution: {integrity: sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==} + '@octokit/request@8.4.0': + resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} + engines: {node: '>= 18'} - '@octokit/types@10.0.0': - resolution: {integrity: sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==} + '@octokit/rest@20.1.1': + resolution: {integrity: sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==} + engines: {node: '>= 18'} - '@octokit/types@9.3.2': - resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==} + '@octokit/types@13.5.0': + resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -3571,77 +3609,10 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@opentelemetry/api-logs@0.50.0': - resolution: {integrity: sha512-JdZuKrhOYggqOpUljAq4WWNi5nB10PmgoF0y2CvedLGXd0kSawb/UBnWT8gg1ND3bHCNHStAIVT0ELlxJJRqrA==} - engines: {node: '>=14'} - '@opentelemetry/api@1.8.0': resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==} engines: {node: '>=8.0.0'} - '@opentelemetry/core@1.23.0': - resolution: {integrity: sha512-hdQ/a9TMzMQF/BO8Cz1juA43/L5YGtCSiKoOHmrTEf7VMDAZgy8ucpWx3eQTnQ3gBloRcWtzvcrMZABC3PTSKQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/core@1.24.0': - resolution: {integrity: sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/otlp-transformer@0.50.0': - resolution: {integrity: sha512-s0sl1Yfqd5q1Kjrf6DqXPWzErL+XHhrXOfejh4Vc/SMTNqC902xDsC8JQxbjuramWt/+hibfguIvi7Ns8VLolA==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.9.0' - - '@opentelemetry/resources@1.23.0': - resolution: {integrity: sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/resources@1.24.0': - resolution: {integrity: sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/sdk-logs@0.50.0': - resolution: {integrity: sha512-PeUEupBB29p9nlPNqXoa1PUWNLsZnxG0DCDj3sHqzae+8y76B/A5hvZjg03ulWdnvBLYpnJslqzylG9E0IL87g==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.4.0 <1.9.0' - '@opentelemetry/api-logs': '>=0.39.1' - - '@opentelemetry/sdk-metrics@1.23.0': - resolution: {integrity: sha512-4OkvW6+wST4h6LFG23rXSTf6nmTf201h9dzq7bE0z5R9ESEVLERZz6WXwE7PSgg1gdjlaznm1jLJf8GttypFDg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.9.0' - - '@opentelemetry/sdk-trace-base@1.23.0': - resolution: {integrity: sha512-PzBmZM8hBomUqvCddF/5Olyyviayka44O5nDWq673np3ctnvwMOvNrsUORZjKja1zJbwEuD9niAGbnVrz3jwRQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/sdk-trace-base@1.24.0': - resolution: {integrity: sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/semantic-conventions@1.23.0': - resolution: {integrity: sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg==} - engines: {node: '>=14'} - - '@opentelemetry/semantic-conventions@1.24.0': - resolution: {integrity: sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==} - engines: {node: '>=14'} - '@parcel/watcher-android-arm64@2.4.1': resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} engines: {node: '>= 10.0.0'} @@ -3732,8 +3703,8 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@pmmmwh/react-refresh-webpack-plugin@0.5.13': - resolution: {integrity: sha512-odZVYXly+JwzYri9rKqqUAk0cY6zLpv4dxoKinhoJNShV36Gpxf+CyDIILJ4tYsJ1ZxIWs233Y39iVnynvDA/g==} + '@pmmmwh/react-refresh-webpack-plugin@0.5.15': + resolution: {integrity: sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==} engines: {node: '>= 10.13'} peerDependencies: '@types/webpack': 4.x || 5.x @@ -3762,177 +3733,177 @@ packages: resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} - '@pnpm/constants@7.1.1': - resolution: {integrity: sha512-31pZqMtjwV+Vaq7MaPrT1EoDFSYwye3dp6BiHIGRJmVThCQwySRKM7hCvqqI94epNkqFAAYoWrNynWoRYosGdw==} - engines: {node: '>=16.14'} + '@pnpm/constants@8.0.0': + resolution: {integrity: sha512-yQosGUvYPpAjb1jOFcdbwekRjZRVxN6C0hHzfRCZrMKbxGjt/E0g0RcFlEDNVZ95tm4oMMcr7nEPa7H7LX3emw==} + engines: {node: '>=18.12'} - '@pnpm/error@5.0.3': - resolution: {integrity: sha512-ONJU5cUeoeJSy50qOYsMZQHTA/9QKmGgh1ATfEpCLgtbdwqUiwD9MxHNeXUYYI/pocBCz6r1ZCFqiQvO+8SUKA==} - engines: {node: '>=16.14'} + '@pnpm/error@6.0.1': + resolution: {integrity: sha512-7yjO0RgmWYb4OKgcWC33yD4Z2CxE7Tm7vXX1SmS7GDifDT/bgZZhHeS2xq/+W6y9yhwIrRSA+7AlQL1NM2wIvw==} + engines: {node: '>=18.12'} '@pnpm/network.ca-file@1.0.2': resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - '@pnpm/npm-conf@2.2.2': - resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + '@pnpm/npm-conf@2.3.1': + resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} engines: {node: '>=12'} - '@pnpm/workspace.read-manifest@1.0.3': - resolution: {integrity: sha512-AC83sfZze5MzsaZjMzAgOOncOfDx8Edo1Pz5GTAFH7Pjqu1a/wFqgL+1ulyLADH5mfYQnF5olXTp7+EPXpZ4sQ==} - engines: {node: '>=16.14'} + '@pnpm/workspace.read-manifest@2.2.0': + resolution: {integrity: sha512-8rWN1LjG8qCqR32UcDVBBaXfmQhl1Ye698KB1L+MlJTa/S568UyQOfINdC8eL5ba6vggoDp4opgUcY8FoEdNhQ==} + engines: {node: '>=18.12'} - '@react-aria/i18n@3.11.0': - resolution: {integrity: sha512-dnopopsYKy2cd2dB2LdnmdJ58evKKcNCtiscWl624XFSbq2laDrYIQ4umrMhBxaKD7nDQkqydVBe6HoQKPzvJw==} + '@react-aria/i18n@3.12.2': + resolution: {integrity: sha512-PvEyC6JWylTpe8dQEWqQwV6GiA+pbTxHQd//BxtMSapRW3JT9obObAnb/nFhj3HthkUvqHyj0oO1bfeN+mtD8A==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-aria/interactions@3.21.2': - resolution: {integrity: sha512-Ju706DtoEmI/2vsfu9DCEIjDqsRBVLm/wmt2fr0xKbBca7PtmK8daajxFWz+eTq+EJakvYfLr7gWgLau9HyWXg==} + '@react-aria/interactions@3.22.2': + resolution: {integrity: sha512-xE/77fRVSlqHp2sfkrMeNLrqf2amF/RyuAS6T5oDJemRSgYM3UoxTbWjucPhfnoW7r32pFPHHgz4lbdX8xqD/g==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-aria/landmark@3.0.0-beta.10': - resolution: {integrity: sha512-qFfAVgCUP/d+sFXCYVJHOMA8fD9VGBWcbJIbfz14X0sdyJ1gj5SL/m4o7cX3OsD9tgPz2A33c1FfmO2gN/qOVg==} + '@react-aria/landmark@3.0.0-beta.12': + resolution: {integrity: sha512-xCAYw0cxn115ZaTXyGXALW2Jebm56s7oX/R0/REubiHwkuDSRxRnYXbaaHxGXNsJWex5LGIZbUYaumGjGrzOnw==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - '@react-aria/landmark@3.0.0-beta.11': - resolution: {integrity: sha512-8fMNmhH4a0tB3KxgiOxL14NAnmIHp4efyO3iDmOkoY+UnfWlVH1oyT9HIXNdEETpQcwysNQkKADYNcOTHLT8UA==} + '@react-aria/landmark@3.0.0-beta.15': + resolution: {integrity: sha512-EEABy0IFzqoS7r11HoD2YwiGR5LFw4kWDFTFUFwJkRP5tHEzsrEgkKPSPJXScQr5m7tenV6j0/Zzl1+w1ki3lA==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-aria/ssr@3.9.3': - resolution: {integrity: sha512-5bUZ93dmvHFcmfUcEN7qzYe8yQQ8JY+nHN6m9/iSDCQ/QmCiE0kWXYwhurjw5ch6I8WokQzx66xKIMHBAa4NNA==} + '@react-aria/ssr@3.9.5': + resolution: {integrity: sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==} engines: {node: '>= 12'} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-aria/toast@3.0.0-beta.10': - resolution: {integrity: sha512-b4PZaCZBc8oiiZ4xxWA0pusPj0VBiNbGJsmyQSe9L0OS7/wL+Z+70xpUMzL+RzhtRuP/lNx7G9a92HwcxFfrog==} + '@react-aria/toast@3.0.0-beta.12': + resolution: {integrity: sha512-cNchqcvK+WJ+CTMzXBk8GzlsqEUUtbyLxz4BUgKHzysac50uhpbjdYbb+5cKetEaU6/wJ75VECk35wiLYkc16w==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - '@react-aria/toast@3.0.0-beta.11': - resolution: {integrity: sha512-0U4wTvP3zhsgPhBv5MMVbj7iFsoOsefcpvoRiMzlnekBwxOnw8fuq03RCviRDLxOCBjzA38SjphElSSFAaokhw==} + '@react-aria/toast@3.0.0-beta.15': + resolution: {integrity: sha512-bg6ZXq4B5JYVt3GXVlf075tQOakcfumbDLnUMaijez4BhacuxF01+IvBPzAVEsARVNXfELoXa7Frb2K54Wgvtw==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-aria/utils@3.24.0': - resolution: {integrity: sha512-JAxkPhK5fCvFVNY2YG3TW3m1nTzwRcbz7iyTSkUzLFat4N4LZ7Kzh7NMHsgeE/oMOxd8zLY+XsUxMu/E/2GujA==} + '@react-aria/utils@3.25.2': + resolution: {integrity: sha512-GdIvG8GBJJZygB4L2QJP1Gabyn2mjFsha73I2wSe+o4DYeGWoJiMZRM06PyTIxLH4S7Sn7eVDtsSBfkc2VY/NA==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-stately/toast@3.0.0-beta.2': - resolution: {integrity: sha512-LJT3VJ01VeQHTDt+6NwmRn4ma0plZWcWByAeJ24dLYJ0gUpHhHyCCIBB/C1BwZ3/eaNKn7/Crp5FONA6bBzDaA==} + '@react-stately/toast@3.0.0-beta.4': + resolution: {integrity: sha512-YzEyFNAAQqZ+7pZpRiejotxDzp5CHagN21btVGGwU2jHu/oQRR+todtB3wADAp7EF5lfAlAsLABiD9ZNWQeDTw==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - '@react-stately/toast@3.0.0-beta.3': - resolution: {integrity: sha512-49QXvRiVSy2sjNYEHWEzdi2+2OxkQi2ZkmG5oDUWIiOEKsjkmQJkWjp3E4cyrgh1Ph7/sAtURH5bcPMOywUCLQ==} + '@react-stately/toast@3.0.0-beta.5': + resolution: {integrity: sha512-MEdQwcKsexlcJ4YQZ9cN5QSIqTlGGdgC5auzSKXXoq15DHuo4mtHfLzXPgcMDYOhOdmyphMto8Vt+21UL2FOrw==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-stately/utils@3.10.0': - resolution: {integrity: sha512-nji2i9fTYg65ZWx/3r11zR1F2tGya+mBubRCbMTwHyRnsSLFZaeq/W6lmrOyIy1uMJKBNKLJpqfmpT4x7rw6pg==} + '@react-stately/utils@3.10.3': + resolution: {integrity: sha512-moClv7MlVSHpbYtQIkm0Cx+on8Pgt1XqtPx6fy9rQFb2DNc9u1G3AUVnqA17buOkH1vLxAtX4MedlxMWyRCYYA==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-types/button@3.9.3': - resolution: {integrity: sha512-YHlSeH85FhasJXOmkY4x+6If74ZpUh88C2fMlw0HUA/Bq/KGckUoriV8cnMqSnB1OwPqi8dpBZGfFVj6f6lh9A==} + '@react-types/button@3.9.6': + resolution: {integrity: sha512-8lA+D5JLbNyQikf8M/cPP2cji91aVTcqjrGpDqI7sQnaLFikM8eFR6l1ZWGtZS5MCcbfooko77ha35SYplSQvw==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@react-types/shared@3.23.0': - resolution: {integrity: sha512-GQm/iPiii3ikcaMNR4WdVkJ4w0mKtV3mLqeSfSqzdqbPr6vONkqXbh3RhPlPmAJs1b4QHnexd/wZQP3U9DHOwQ==} + '@react-types/shared@3.24.1': + resolution: {integrity: sha512-AUQeGYEm/zDTN6zLzdXolDxz3Jk5dDL7f506F07U8tBwxNNI3WRdhU84G0/AaFikOZzDXhOZDr3MhQMzyE7Ydw==} peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - '@remix-run/router@1.16.0': - resolution: {integrity: sha512-Quz1KOffeEf/zwkCBM3kBtH4ZoZ+pT3xIXBG4PPW/XFtDP7EGhtTiC2+gpL9GnR7+Qdet5Oa6cYSvwKYg6kN9Q==} + '@remix-run/router@1.18.0': + resolution: {integrity: sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==} engines: {node: '>=14.0.0'} '@rollup/pluginutils@4.2.1': resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.21.0': + resolution: {integrity: sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.21.0': + resolution: {integrity: sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.21.0': + resolution: {integrity: sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.21.0': + resolution: {integrity: sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': + resolution: {integrity: sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.21.0': + resolution: {integrity: sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.21.0': + resolution: {integrity: sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.21.0': + resolution: {integrity: sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': + resolution: {integrity: sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.21.0': + resolution: {integrity: sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.21.0': + resolution: {integrity: sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.21.0': + resolution: {integrity: sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.21.0': + resolution: {integrity: sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.21.0': + resolution: {integrity: sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.21.0': + resolution: {integrity: sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.21.0': + resolution: {integrity: sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==} cpu: [x64] os: [win32] @@ -4110,71 +4081,71 @@ packages: resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==} engines: {node: '>=14'} - '@swc/core-darwin-arm64@1.4.17': - resolution: {integrity: sha512-HVl+W4LezoqHBAYg2JCqR+s9ife9yPfgWSj37iIawLWzOmuuJ7jVdIB7Ee2B75bEisSEKyxRlTl6Y1Oq3owBgw==} + '@swc/core-darwin-arm64@1.7.0': + resolution: {integrity: sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.4.17': - resolution: {integrity: sha512-WYRO9Fdzq4S/he8zjW5I95G1zcvyd9yyD3Tgi4/ic84P5XDlSMpBDpBLbr/dCPjmSg7aUXxNQqKqGkl6dQxYlA==} + '@swc/core-darwin-x64@1.7.0': + resolution: {integrity: sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.4.17': - resolution: {integrity: sha512-cgbvpWOvtMH0XFjvwppUCR+Y+nf6QPaGu6AQ5hqCP+5Lv2zO5PG0RfasC4zBIjF53xgwEaaWmGP5/361P30X8Q==} + '@swc/core-linux-arm-gnueabihf@1.7.0': + resolution: {integrity: sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.4.17': - resolution: {integrity: sha512-l7zHgaIY24cF9dyQ/FOWbmZDsEj2a9gRFbmgx2u19e3FzOPuOnaopFj0fRYXXKCmtdx+anD750iBIYnTR+pq/Q==} + '@swc/core-linux-arm64-gnu@1.7.0': + resolution: {integrity: sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.4.17': - resolution: {integrity: sha512-qhH4gr9gAlVk8MBtzXbzTP3BJyqbAfUOATGkyUtohh85fPXQYuzVlbExix3FZXTwFHNidGHY8C+ocscI7uDaYw==} + '@swc/core-linux-arm64-musl@1.7.0': + resolution: {integrity: sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.4.17': - resolution: {integrity: sha512-vRDFATL1oN5oZMImkwbgSHEkp8xG1ofEASBypze01W1Tqto8t+yo6gsp69wzCZBlxldsvPpvFZW55Jq0Rn+UnA==} + '@swc/core-linux-x64-gnu@1.7.0': + resolution: {integrity: sha512-SY3HA0K0Dpqt1HIfMLGpwL4hd4UaL2xHP5oZXPlRQPhUDZrbb4PbI3ZJnh66c63eL4ZR8EJ+HRFI0Alx5p69Zw==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.4.17': - resolution: {integrity: sha512-zQNPXAXn3nmPqv54JVEN8k2JMEcMTQ6veVuU0p5O+A7KscJq+AGle/7ZQXzpXSfUCXlLMX4wvd+rwfGhh3J4cw==} + '@swc/core-linux-x64-musl@1.7.0': + resolution: {integrity: sha512-cEJ2ebtV1v/5Ilb55E05J6F5SrHKQWzUttIhR5Mkayyo+yvPslcpByuFC3D+J7X1ebziTOBpWuMpUdjLfh3SMQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.4.17': - resolution: {integrity: sha512-z86n7EhOwyzxwm+DLE5NoLkxCTme2lq7QZlDjbQyfCxOt6isWz8rkW5QowTX8w9Rdmk34ncrjSLvnHOeLY17+w==} + '@swc/core-win32-arm64-msvc@1.7.0': + resolution: {integrity: sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.4.17': - resolution: {integrity: sha512-JBwuSTJIgiJJX6wtr4wmXbfvOswHFj223AumUrK544QV69k60FJ9q2adPW9Csk+a8wm1hLxq4HKa2K334UHJ/g==} + '@swc/core-win32-ia32-msvc@1.7.0': + resolution: {integrity: sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.4.17': - resolution: {integrity: sha512-jFkOnGQamtVDBm3MF5Kq1lgW8vx4Rm1UvJWRUfg+0gx7Uc3Jp3QMFeMNw/rDNQYRDYPG3yunCC+2463ycd5+dg==} + '@swc/core-win32-x64-msvc@1.7.0': + resolution: {integrity: sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.4.17': - resolution: {integrity: sha512-tq+mdWvodMBNBBZbwFIMTVGYHe9N7zvEaycVVjfvAx20k1XozHbHhRv+9pEVFJjwRxLdXmtvFZd3QZHRAOpoNQ==} + '@swc/core@1.7.0': + resolution: {integrity: sha512-d4vMzH6ICllDwlPuhset2h8gu/USHdbyfJim+2hQEdxC0UONtfpmu38XBgNqRjStrji1Q5M10jfeUZL3cu1i8g==} engines: {node: '>=10'} peerDependencies: - '@swc/helpers': ^0.5.0 + '@swc/helpers': '*' peerDependenciesMeta: '@swc/helpers': optional: true @@ -4182,8 +4153,8 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/helpers@0.5.11': - resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} + '@swc/helpers@0.5.12': + resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} '@swc/jest@0.2.36': resolution: {integrity: sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==} @@ -4191,36 +4162,36 @@ packages: peerDependencies: '@swc/core': '*' - '@swc/types@0.1.6': - resolution: {integrity: sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==} + '@swc/types@0.1.12': + resolution: {integrity: sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==} '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - '@tanstack/query-core@5.32.0': - resolution: {integrity: sha512-Z3flEgCat55DRXU5UMwYU1U+DgFZKA3iufyOKs+II7iRAo0uXkeU7PH5e6sOH1CGEag0IpKmZxlUFpCg6roSKw==} + '@tanstack/query-core@5.51.9': + resolution: {integrity: sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==} - '@tanstack/query-devtools@5.28.10': - resolution: {integrity: sha512-5UN629fKa5/1K/2Pd26gaU7epxRrYiT1gy+V+pW5K6hnf1DeUKK3pANSb2eHKlecjIKIhTwyF7k9XdyE2gREvQ==} + '@tanstack/query-devtools@5.51.9': + resolution: {integrity: sha512-FQqJynaEDuwQxoFLP3/i10HQwNYh4wxgs0NeSoL24BLWvpUdstgHqUm2zgwRov8Tmh5kjndPIWaXenwl0D47EA==} - '@tanstack/react-query-devtools@5.32.0': - resolution: {integrity: sha512-KWrzLoUjs9JtDSH3H2qbm5MjjykyAT8DkvP8tukw3gBG4ziu5WaWHciBjMsYSe1JB79AOxxGovzjW/Cd9+ofVw==} + '@tanstack/react-query-devtools@5.51.9': + resolution: {integrity: sha512-ztS5l75gV4xjDUFfEOtBfzcqW5vyfAQ2haWPpGMwq/Ha/3a4gaOE5DKntq+0+upWxUpp4SSvXXm6fMjV5miUcQ==} peerDependencies: - '@tanstack/react-query': ^5.32.0 - react: ^18.0.0 + '@tanstack/react-query': ^5.51.9 + react: ^18 || ^19 - '@tanstack/react-query@5.32.0': - resolution: {integrity: sha512-+E3UudQtarnx9A6xhpgMZapyF+aJfNBGFMgI459FnduEZqT/9KhOWnMOneZahLRt52yzskSA0AuOyLkXHK0yBA==} + '@tanstack/react-query@5.51.9': + resolution: {integrity: sha512-F8j6i42wfKvFrRcxfOyFyYME+bPfNthAGOSkjdv4UwZZXJjnBnBs/yRQGT0bD23LVCTuBzlIfZ0GKSIyclZ9rQ==} peerDependencies: react: ^18.0.0 - '@testing-library/dom@10.1.0': - resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} - '@testing-library/jest-dom@6.4.2': - resolution: {integrity: sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==} + '@testing-library/jest-dom@6.4.6': + resolution: {integrity: sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} peerDependencies: '@jest/globals': '>= 28' @@ -4240,12 +4211,20 @@ packages: vitest: optional: true - '@testing-library/react@15.0.5': - resolution: {integrity: sha512-ttodVWYA2i2w4hRa6krKrmS1vKxAEkwDz34y+CwbcrbZUxFzUYN3a5xZyFKo+K6LBseCRCUkwcjATpaNn/UsIA==} + '@testing-library/react@16.0.0': + resolution: {integrity: sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==} engines: {node: '>=18'} peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 react: ^18.0.0 react-dom: ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -4285,8 +4264,8 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.5': - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} @@ -4312,8 +4291,8 @@ packages: '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - '@types/eslint@8.56.10': - resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + '@types/eslint@9.6.0': + resolution: {integrity: sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==} '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -4321,8 +4300,8 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/express-serve-static-core@4.19.0': - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} + '@types/express-serve-static-core@4.19.5': + resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -4345,8 +4324,8 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-proxy@1.17.14': - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} + '@types/http-proxy@1.17.15': + resolution: {integrity: sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==} '@types/is-empty@1.2.3': resolution: {integrity: sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==} @@ -4375,8 +4354,8 @@ packages: '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} - '@types/mdast@4.0.3': - resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -4384,9 +4363,6 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/minimist@1.2.5': - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} @@ -4399,8 +4375,11 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + '@types/node@20.14.11': + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + + '@types/node@22.5.0': + resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -4420,8 +4399,8 @@ packages: '@types/react-test-renderer@18.3.0': resolution: {integrity: sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==} - '@types/react@18.3.1': - resolution: {integrity: sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==} + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} '@types/retry@0.12.1': resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} @@ -4459,17 +4438,17 @@ packages: '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@types/unist@2.0.10': - resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.2': - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} '@types/wrap-ansi@3.0.0': resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} - '@types/ws@8.5.10': - resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + '@types/ws@8.5.12': + resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -4477,14 +4456,14 @@ packages: '@types/yargs@16.0.9': resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==} - '@types/yargs@17.0.32': - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@7.8.0': - resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==} + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -4494,8 +4473,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.8.0': - resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==} + '@typescript-eslint/parser@7.16.1': + resolution: {integrity: sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4508,12 +4487,16 @@ packages: resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@typescript-eslint/scope-manager@7.8.0': - resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} + '@typescript-eslint/scope-manager@7.16.1': + resolution: {integrity: sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.8.0': - resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4526,8 +4509,12 @@ packages: resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@typescript-eslint/types@7.8.0': - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} + '@typescript-eslint/types@7.16.1': + resolution: {integrity: sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} '@typescript-eslint/typescript-estree@5.62.0': @@ -4539,8 +4526,17 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@7.8.0': - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} + '@typescript-eslint/typescript-estree@7.16.1': + resolution: {integrity: sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -4554,8 +4550,8 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - '@typescript-eslint/utils@7.8.0': - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4564,20 +4560,19 @@ packages: resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@typescript-eslint/visitor-keys@7.8.0': - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} + '@typescript-eslint/visitor-keys@7.16.1': + resolution: {integrity: sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vercel/nft@0.23.1': - resolution: {integrity: sha512-NE0xSmGWVhgHF1OIoir71XAd0W0C1UE3nzFyhpFiMr3rVhetww7NvM1kc41trBsPG37Bh+dE5FYCTMzM/gBu0w==} - engines: {node: '>=14'} - hasBin: true - - '@vercel/nft@0.26.4': - resolution: {integrity: sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==} + '@vercel/nft@0.27.3': + resolution: {integrity: sha512-oySTdDSzUAFDXpsSLk9Q943o+/Yu/+TCFxnehpFQEf/3khi2stMpTHPVNwFdvZq/Z4Ky93lE+MGHpXCRpMkSCA==} engines: {node: '>=16'} hasBin: true @@ -4598,15 +4593,15 @@ packages: resolution: {integrity: sha512-nDPbVFZ7y7aEMAVRC1LIllMMvwE5Qgd0z+cyd+K4z0NJ7LAjcjydhPw4RYAoYF3JzvZVpra/S0SRN/dCFE8E+A==} engines: {node: '>=18.0.0'} - '@voxpelli/typed-utils@1.10.1': - resolution: {integrity: sha512-HNRZ+rTbjS9MphabJR44JKd+tI+aCQljkdUANHnk6gwE3EJ4w2D3Dodzwjy4x+bndw43JoGqOfUHC+1CRNOHaw==} + '@voxpelli/typed-utils@1.10.2': + resolution: {integrity: sha512-icXQSR6SeGL6kr9koJw9zkDZqWyFXgpJG8kTaDydjZhy9/V0MQB9tYyibvRgJHlk98SDJJhPLCouTdqOdn+riw==} engines: {node: '>=18.0.0'} - '@vue/compiler-core@3.4.26': - resolution: {integrity: sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==} + '@vue/compiler-core@3.4.38': + resolution: {integrity: sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==} - '@vue/compiler-dom@3.4.26': - resolution: {integrity: sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==} + '@vue/compiler-dom@3.4.38': + resolution: {integrity: sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==} '@vue/language-core@1.8.27': resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} @@ -4616,8 +4611,8 @@ packages: typescript: optional: true - '@vue/shared@3.4.26': - resolution: {integrity: sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==} + '@vue/shared@3.4.38': + resolution: {integrity: sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==} '@webassemblyjs/ast@1.12.1': resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} @@ -4802,11 +4797,6 @@ packages: acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - acorn-import-assertions@1.9.0: - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -4817,18 +4807,18 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} engines: {node: '>=0.4.0'} - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true - adm-zip@0.5.12: - resolution: {integrity: sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==} - engines: {node: '>=6.0'} + adm-zip@0.5.15: + resolution: {integrity: sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==} + engines: {node: '>=12.0'} agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} @@ -4880,8 +4870,8 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} all-node-versions@11.3.0: resolution: {integrity: sha512-psMkc5s3qpr+QMfires9bC4azRYciPWql1wqZKMsYRh1731qefQDH2X4+O19xSBX6u0Ra/8Y5diG6y/fEmqKsw==} @@ -4910,11 +4900,20 @@ packages: resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} engines: {node: '>=14.16'} + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + ansi-html-community@0.0.8: resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} engines: {'0': node >= 0.8.0} hasBin: true + ansi-html@0.0.9: + resolution: {integrity: sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==} + engines: {'0': node >= 0.8.0} + hasBin: true + ansi-regex@3.0.1: resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} engines: {node: '>=4'} @@ -4962,20 +4961,18 @@ packages: aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - archiver-utils@4.0.1: - resolution: {integrity: sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==} - engines: {node: '>= 12.0.0'} - - archiver@6.0.2: - resolution: {integrity: sha512-UQ/2nW7NMl1G+1UnrLypQw1VdT9XZg/ECcKPq7l+STzStrSivFIXIp34D8M5zeNGW5NoOupdYCHv6VySCPNNlw==} - engines: {node: '>= 12.0.0'} + archiver-utils@5.0.2: + resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} + engines: {node: '>= 14'} - archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} + archiver@7.0.1: + resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==} + engines: {node: '>= 14'} are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} + deprecated: This package is no longer supported. arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -4986,24 +4983,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - arity-n@1.0.4: - resolution: {integrity: sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ==} - - arr-diff@4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - - arr-flatten@1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - - arr-union@3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -5015,10 +5000,6 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} - array-last@1.3.0: - resolution: {integrity: sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==} - engines: {node: '>=0.10.0'} - array-timsort@1.0.3: resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} @@ -5026,10 +5007,6 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array-unique@0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -5046,20 +5023,14 @@ packages: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} - array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - - array.prototype.tosorted@1.1.3: - resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} arraybuffer.prototype.slice@1.0.3: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - arrify@3.0.0: resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} engines: {node: '>=12'} @@ -5067,10 +5038,6 @@ packages: ascii-table@0.0.9: resolution: {integrity: sha512-xpkr6sCDIYTPqzvjG8M3ncw1YOTaloWZOyrUmicoEifBEKzQzt+ooUpRpQ/AbOoJfO/p2ZKiyp79qHThzJDulQ==} - assign-symbols@1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - ast-module-types@5.0.0: resolution: {integrity: sha512-JvqziE0Wc0rXQfma0HZC/aY7URXHFuZV84fJRtP8u+lhp0JYCNd5wJzVXP45t0PH0Mej3ynlzvdyITYIu0G4LQ==} engines: {node: '>=14'} @@ -5087,8 +5054,8 @@ packages: async@2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} - async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -5097,11 +5064,6 @@ packages: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} - atob@2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -5110,18 +5072,18 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - avvio@8.3.0: - resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} + avvio@8.4.0: + resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} - axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + axe-core@4.10.0: + resolution: {integrity: sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==} engines: {node: '>=4'} - axios@1.6.8: - resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + axios@1.7.5: + resolution: {integrity: sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==} - axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + axobject-query@3.1.1: + resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} @@ -5145,8 +5107,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.10.4: - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} + babel-plugin-polyfill-corejs3@0.10.6: + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -5155,8 +5117,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-preset-current-node-syntax@1.0.1: - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} peerDependencies: '@babel/core': ^7.0.0 @@ -5166,10 +5128,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - babylon@6.18.0: - resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} - hasBin: true - backoff@2.5.0: resolution: {integrity: sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==} engines: {node: '>= 0.6'} @@ -5180,28 +5138,24 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.2.2: - resolution: {integrity: sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==} + bare-events@2.4.2: + resolution: {integrity: sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==} - bare-fs@2.3.0: - resolution: {integrity: sha512-TNFqa1B4N99pds2a5NYHR15o0ZpdNKbAeKTE/+G6ED/UeOavv8RY3dr/Fu99HW3zU3pXpo2kDNO8Sjsm2esfOw==} + bare-fs@2.3.1: + resolution: {integrity: sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==} - bare-os@2.3.0: - resolution: {integrity: sha512-oPb8oMM1xZbhRQBngTgpcQ5gXw6kjOaRsSWsIeNyRxGed2w/ARyP7ScBYpWR1qfX2E5rS3gBw6OWcSQo+s+kUg==} + bare-os@2.4.0: + resolution: {integrity: sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==} - bare-path@2.1.2: - resolution: {integrity: sha512-o7KSt4prEphWUHa3QUwCxUI00R86VdjiuxmJK0iNVDHYPGo+HsDaVCnqCmPbf/MiW1ok8F4p3m8RTHlWk8K2ig==} + bare-path@2.1.3: + resolution: {integrity: sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==} - bare-stream@1.0.0: - resolution: {integrity: sha512-KhNUoDL40iP4gFaLSsoGE479t0jHijfYdIcxRn/XtezA2BaUD0NRf/JGRpsMq6dMNM+SrCrB0YSSo/5wBY4rOQ==} + bare-stream@2.1.3: + resolution: {integrity: sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - base@0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} @@ -5239,9 +5193,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - blueimp-md5@2.19.0: resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} @@ -5265,19 +5216,17 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + browserslist@4.23.2: + resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true - browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -5288,9 +5237,18 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + btoa@1.2.1: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -5303,8 +5261,8 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - buffered-async-iterable@0.3.0: - resolution: {integrity: sha512-McUDFN18nTngbI9EPqHXyifF3iReQtEeoCdukNtrypmPWMRxsJO6KbBihQ88PI+CIFhbCmm2cTkhgxmKADwFNA==} + buffered-async-iterable@1.0.1: + resolution: {integrity: sha512-QqoUm0XP17Bu6zzyvpK92K7jNYMoFYgKM0ZKr0OkoDlElpTTeucGmdJL8I7W+reFIfvgUWOm1PgJC+OxM2lMEQ==} engines: {node: '>=18.6.0'} builtin-modules@3.3.0: @@ -5318,11 +5276,11 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - bundle-require@4.1.0: - resolution: {integrity: sha512-FeArRFM+ziGkRViKRnSTbHZc35dgmR9yNog05Kn0+ItI59pOAISGvnnIwW1WgFZQW59IxD9QpJnUPkdIPfZuXg==} + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: - esbuild: '>=0.17' + esbuild: '>=0.18' byline@5.0.0: resolution: {integrity: sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==} @@ -5340,10 +5298,6 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cache-base@1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - cache-content-type@1.0.1: resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} engines: {node: '>= 6.0.0'} @@ -5374,10 +5328,6 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -5390,8 +5340,8 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-lite@1.0.30001615: - resolution: {integrity: sha512-1IpazM5G3r38meiae0bHRnPhz+CBQ3ZLqbQMtrg+AsTPKAXgW38JNsXkyZ+v8waCsDmPq87lmfun5Q2AGysNEQ==} + caniuse-lite@1.0.30001651: + resolution: {integrity: sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5408,10 +5358,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.2.0: - resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -5444,10 +5390,6 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -5459,14 +5401,10 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - ci-info@3.8.0: - resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} - engines: {node: '>=8'} - ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -5481,10 +5419,6 @@ packages: cjs-module-lexer@1.3.1: resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} - class-utils@0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} - clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} @@ -5521,9 +5455,9 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} - cli-truncate@3.1.0: - resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} cli-width@2.2.1: resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} @@ -5536,9 +5470,6 @@ packages: resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} engines: {node: '>=18'} - cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} @@ -5565,10 +5496,6 @@ packages: collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - collection-visit@1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -5648,15 +5575,9 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - - compose-function@3.0.3: - resolution: {integrity: sha512-xzhzTJ5eC+gmIzvZq+C3kCJHsp9os6tJkrigDRZclyGtOKINbZtE8n1Tzmeh32jW+BUDPbvZpibwvJHBLGMVwg==} - - compress-commons@5.0.3: - resolution: {integrity: sha512-/UIcLWvwAQyVibgpQDPtfNM3SvqN7G9elAPAV7GM0L53EbNWwWiCsWtK8Fwed/APEbptPHXs5PuW+y8Bq8lFTA==} - engines: {node: '>= 12.0.0'} + compress-commons@6.0.2: + resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} + engines: {node: '>= 14'} compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} @@ -5712,8 +5633,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie-es@1.1.0: - resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==} + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} @@ -5730,22 +5651,15 @@ packages: resolution: {integrity: sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==} engines: {node: '>= 0.8'} - copy-descriptor@0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - - copy-template-dir@1.4.0: - resolution: {integrity: sha512-xkXSJhvKz4MfLbVkZ7GyCaFo4ciB3uKI/HHzkGwj1eyTH5+7RTFxW5CE0irWAZgV5oFcO9hd6+NVXAtY9hlo7Q==} - copyfiles@2.4.1: resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} hasBin: true - core-js-compat@3.37.0: - resolution: {integrity: sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==} + core-js-compat@3.38.1: + resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} - core-js-pure@3.37.0: - resolution: {integrity: sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==} + core-js-pure@3.38.1: + resolution: {integrity: sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -5789,9 +5703,9 @@ packages: engines: {node: '>=0.8'} hasBin: true - crc32-stream@5.0.1: - resolution: {integrity: sha512-lO1dFui+CEUh/ztYIpgpKItKW9Bb4NWakCRJrnqAbFIYD+OZAwb2VfD5T5eXMw2FNcsDHkQcNl/Wh3iVXYwU6g==} - engines: {node: '>= 12.0.0'} + crc32-stream@6.0.0: + resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} + engines: {node: '>= 14'} create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} @@ -5801,10 +5715,6 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cron-parser@4.8.1: - resolution: {integrity: sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==} - engines: {node: '>=12.0.0'} - cron-parser@4.9.0: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} @@ -5891,19 +5801,6 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - - csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - - csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - - csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - cyclist@1.0.2: resolution: {integrity: sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==} @@ -5968,8 +5865,17 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -5980,24 +5886,12 @@ packages: decache@4.6.2: resolution: {integrity: sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw==} - decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - - decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -6013,13 +5907,14 @@ packages: deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - deep-freeze@0.0.1: - resolution: {integrity: sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -6062,18 +5957,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - define-property@0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - - define-property@1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - - define-property@2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} @@ -6238,9 +6121,9 @@ packages: resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dotenv@16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} + dot-prop@9.0.0: + resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} + engines: {node: '>=18'} dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} @@ -6262,8 +6145,13 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.4.756: - resolution: {integrity: sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.13: + resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -6292,8 +6180,8 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -6320,10 +6208,12 @@ packages: engines: {node: '>=4'} hasBin: true - envinfo@7.8.1: - resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} - engines: {node: '>=4'} - hasBin: true + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -6346,12 +6236,15 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-iterator-helpers@1.0.19: resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} engines: {node: '>= 0.4'} - es-module-lexer@1.5.2: - resolution: {integrity: sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} @@ -6376,14 +6269,14 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + esbuild@0.21.2: + resolution: {integrity: sha512-LmHPAa5h4tSxz+g/D8IHY6wCjtIiFx8I7/Q0Aq+NmvtoYvyMnJU0KQJcqB6QH30X9x/W4CemgUtPgQDZFca5SA==} engines: {node: '>=12'} hasBin: true - esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} hasBin: true escalade@3.1.2: @@ -6418,8 +6311,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-compat-utils@0.5.0: - resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==} + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} engines: {node: '>=12'} peerDependencies: eslint: '>=6.0.0' @@ -6477,8 +6370,8 @@ packages: jest: optional: true - eslint-plugin-jsx-a11y@6.8.0: - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + eslint-plugin-jsx-a11y@6.9.0: + resolution: {integrity: sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==} engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 @@ -6508,11 +6401,11 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react@7.34.1: - resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + eslint-plugin-react@7.35.0: + resolution: {integrity: sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==} engines: {node: '>=4'} peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint-plugin-storybook@0.8.0: resolution: {integrity: sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==} @@ -6520,8 +6413,8 @@ packages: peerDependencies: eslint: '>=6' - eslint-plugin-testing-library@6.2.2: - resolution: {integrity: sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==} + eslint-plugin-testing-library@6.3.0: + resolution: {integrity: sha512-GYcEErTt6EGwE0bPDY+4aehfEBpB2gDBFKohir8jlATSUvzStEyzCx8QWB/14xeKc/AwyXkzScSzMHnFojkWrA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} peerDependencies: eslint: ^7.5.0 || ^8.0.0 @@ -6558,8 +6451,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -6621,10 +6514,6 @@ packages: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} - expand-brackets@2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -6653,14 +6542,6 @@ packages: resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} engines: {node: '>=4'} - extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - - extend-shallow@3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -6671,10 +6552,6 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - extglob@2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -6705,8 +6582,8 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-json-stringify@5.15.0: - resolution: {integrity: sha512-BUEAAyDKb64u+kmkINYfXUUiKjBKerSmVu/dzotfaWSHBxR44JFrOZgkhMO6VxDhDfiuAoi8mx4drd5nvNdA4Q==} + fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} @@ -6721,8 +6598,11 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@2.3.0: - resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + + fast-uri@3.0.1: + resolution: {integrity: sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==} fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} @@ -6731,8 +6611,8 @@ packages: fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} - fastify@4.17.0: - resolution: {integrity: sha512-tzuY1tgWJo2Y6qEKwmLhFvACUmr68Io2pqP/sDKU71KRM6A6R3DrCDqLGqANbeLZcKUfdfY58ut35CGqemcTgg==} + fastify@4.28.1: + resolution: {integrity: sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -6747,10 +6627,10 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - fdir@6.1.1: - resolution: {integrity: sha512-QfKBVg453Dyn3mr0Q0O+Tkr1r79lOTAKSi9f/Ot4+qVEwxWhav2Z+SudrG9vQjM2aYRMQQZ2/Q1zdA8ACM1pDg==} + fdir@6.2.0: + resolution: {integrity: sha512-9XaWcDl0riOX5j2kYfy0kKdg7skw3IY6kA4LFT8Tk2yF9UdrADUy8D6AJuBLtf7ISm/MksumwAHE3WVbMRyCLw==} peerDependencies: - picomatch: 3.x + picomatch: ^3 || ^4 peerDependenciesMeta: picomatch: optional: true @@ -6786,10 +6666,6 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - file-type@18.7.0: resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} engines: {node: '>=14.16'} @@ -6797,6 +6673,9 @@ packages: file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filename-reserved-regex@3.0.0: resolution: {integrity: sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6805,21 +6684,10 @@ packages: resolution: {integrity: sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==} engines: {node: '>=12.20'} - fill-range@4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - filter-iterator@0.0.1: - resolution: {integrity: sha512-v4lhL7Qa8XpbW3LN46CEnmhGk3eHZwxfNl5at20aEkreesht4YKb/Ba3BUIbnPhAC/r3dmu7ABaGk6MAvh2alA==} - - filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - filter-obj@3.0.0: resolution: {integrity: sha512-oQZM+QmVni8MsYzcq9lgTHD/qeLqaG8XaOPOW7dzuSafVxSUlH1+1ZDefj2OD9f2XsmG5lFl2Euc9NI4jgwFWg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6836,8 +6704,8 @@ packages: resolution: {integrity: sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==} engines: {node: '>=8'} - find-my-way@7.7.0: - resolution: {integrity: sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==} + find-my-way@8.2.0: + resolution: {integrity: sha512-HdWXgFYc6b1BJcOBDBwjqWuHJj1WYiqrxSh25qtU4DabpMFdj/gSunNBQb83t+8Zt67D7CXEzJWTkxaShMTMOA==} engines: {node: '>=14'} find-pkg@2.0.0: @@ -6860,6 +6728,10 @@ packages: resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + find-yarn-workspace-root2@1.2.16: resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} @@ -6867,10 +6739,6 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true @@ -6899,12 +6767,8 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - for-in@1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - - foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} form-data-encoder@2.1.4: @@ -6923,10 +6787,6 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - fragment-cache@0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -6981,6 +6841,7 @@ packages: gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'} + deprecated: This package is no longer supported. gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -6994,6 +6855,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -7033,10 +6898,6 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-value@2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - gh-release-fetch@4.0.3: resolution: {integrity: sha512-TOiP1nwLsH5shG85Yt6v6Kjq5JU/44jXyEpbcfPgmj3C829yeXIlx9nAEwQRaxtRF3SJinn2lz7XUkfG9W/U4g==} engines: {node: ^14.18.0 || ^16.13.0 || >=18.0.0} @@ -7065,17 +6926,18 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported global-cache-dir@4.4.0: resolution: {integrity: sha512-bk0gI6IbbphRjAaCJJn5H+T/CcEck5B3a5KBO2BXSDzjFSV+API17w8GA7YPJ6IXJiasW8M0VsEIig1PCHdfOQ==} @@ -7135,26 +6997,19 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphql@16.8.1: - resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + graphql@16.9.0: + resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - h3@1.11.1: - resolution: {integrity: sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==} + h3@1.12.0: + resolution: {integrity: sha512-Zi/CcNeWBXDrFNlV0hUBJQR9F7a96RjMeAZweW/ZWkR9fuXrMcvKnSA63f/zZ9l0GgQOZDVHGvXivNN9PWOwhA==} handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} - hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -7170,9 +7025,6 @@ packages: resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} engines: {node: '>=8'} - has-own-property@0.1.0: - resolution: {integrity: sha512-14qdBKoonU99XDhWcFKZTShK+QV47qU97u8zzoVo9cL5TZ3BmBHXogItSt9qJjR0KUMFRhcCW8uGIGl8nkl7Aw==} - has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -7191,26 +7043,6 @@ packages: has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - has-value@0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - - has-value@1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - - has-values@0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - - has-values@1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - - has-yarn@3.0.0: - resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasbin@1.2.3: resolution: {integrity: sha512-CCd8e/w2w28G8DyZvKgiHnQJ/5XXDz6qiUHnthvtag/6T5acUeN5lqq+HMoBqcmgWueWDhiCplrw0Kb1zDACRg==} engines: {node: '>=0.10'} @@ -7234,15 +7066,12 @@ packages: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - hosted-git-info@7.0.1: - resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} hot-shots@10.0.0: @@ -7344,8 +7173,8 @@ packages: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} - https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + https-proxy-agent@7.0.5: + resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} engines: {node: '>= 14'} human-id@1.0.2: @@ -7367,11 +7196,11 @@ packages: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} - i18next-browser-languagedetector@7.2.1: - resolution: {integrity: sha512-h/pM34bcH6tbz8WgGXcmWauNpQupCGr25XPp9cZwZInR9XHSjIFDYp1SIok7zSPsTOMxdvuLyu86V+g2Kycnfw==} + i18next-browser-languagedetector@8.0.0: + resolution: {integrity: sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==} - i18next@23.11.3: - resolution: {integrity: sha512-Pq/aSKowir7JM0rj+Wa23Kb6KKDUGno/HjG+wRQu0PxoTbpQ4N89MAT0rFGvXmLkRLNMb1BbBOKGozl01dabzg==} + i18next@23.12.1: + resolution: {integrity: sha512-l4y291ZGRgUhKuqVSiqyuU2DDzxKStlIWSaoNBR4grYmh0X+pRYbFpTMs3CnJ5ECKbOI8sQcJ3PbTUfLgPRaMA==} iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} @@ -7387,21 +7216,18 @@ packages: peerDependencies: postcss: ^8.1.0 - identity-function@1.0.0: - resolution: {integrity: sha512-kNrgUK0qI+9qLTBidsH85HjDLpZfrrS0ElquKKe/fJFdB3D7VeKdXXEvOPDUHSHOzdZKCAAaQIWWyp0l2yq6pw==} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} ignore-by-default@1.0.1: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - image-meta@0.2.0: - resolution: {integrity: sha512-ZBGjl0ZMEMeOC3Ns0wUF/5UdUmr3qQhBSCniT0LxOgGGIRHiNFOkMtIHB7EOznRU47V2AxPgiVP+s+0/UCU0Hg==} + image-meta@0.2.1: + resolution: {integrity: sha512-K6acvFaelNxx8wc2VjbIzXKDVB0Khs0QT35U6NkGfTdCmjLNcO2945m7RFNR9/RPVFm48hq7QPzK8uGH18HCGw==} import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -7411,8 +7237,8 @@ packages: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} - import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} hasBin: true @@ -7437,6 +7263,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.3: resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} @@ -7451,8 +7278,8 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} inquirer-autocomplete-prompt@1.4.0: @@ -7485,8 +7312,8 @@ packages: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} - intl-messageformat@10.5.11: - resolution: {integrity: sha512-eYq5fkFBVxc7GIFDzpFQkDOZgNayNTQn4Oufe8jw6YY6OHVw70/4pA3FyCsQ0Gb2DnvEJEMmN2tOaXUGByM+kg==} + intl-messageformat@10.5.14: + resolution: {integrity: sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==} ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -7500,12 +7327,8 @@ packages: resolution: {integrity: sha512-AVnPGXJ8L41vjd11Z4akIF2yd14636Klxul3tBySxHA6PKfCOQPxBDkCFK5zcWh0z/keR6toh1eg8qzdBVUgdA==} hasBin: true - iron-webcrypto@1.1.1: - resolution: {integrity: sha512-5xGwQUWHQSy039rFr+5q/zOmj7GP0Ypzvo34Ep+61bPIhaLduEDp/PvLGlU3awD2mzWUR0weN2vJ1mILydFPEg==} - - is-accessor-descriptor@1.0.1: - resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} - engines: {node: '>= 0.10'} + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} @@ -7519,6 +7342,10 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.4: resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} engines: {node: '>= 0.4'} @@ -7544,9 +7371,6 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} - is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -7555,15 +7379,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true - - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - - is-data-descriptor@1.0.1: - resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} is-data-view@1.0.1: @@ -7580,14 +7397,6 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-descriptor@0.1.7: - resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} - engines: {node: '>= 0.4'} - - is-descriptor@1.0.3: - resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} - engines: {node: '>= 0.4'} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -7601,14 +7410,6 @@ packages: is-empty@1.2.0: resolution: {integrity: sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==} - is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - - is-extendable@1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -7628,6 +7429,10 @@ packages: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} @@ -7646,6 +7451,11 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-in-ci@0.1.0: + resolution: {integrity: sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==} + engines: {node: '>=18'} + hasBin: true + is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -7659,10 +7469,6 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} - is-iterable@1.1.1: - resolution: {integrity: sha512-EdOZCr0NsGE00Pot+x1ZFx9MJK3C6wy91geZpXwvwexDLJvA4nzYyZf7r+EIwSeVsOLDdBz7ATg9NqKTzuNYuQ==} - engines: {node: '>= 4'} - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -7686,14 +7492,6 @@ packages: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} - is-number@3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - - is-number@4.0.0: - resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} - engines: {node: '>=0.10.0'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -7730,10 +7528,6 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} - is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -7757,6 +7551,10 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -7780,6 +7578,10 @@ packages: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} + is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + is-url-superb@4.0.0: resolution: {integrity: sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==} engines: {node: '>=10'} @@ -7810,10 +7612,6 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} - is-yarn-global@0.4.1: - resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} - engines: {node: '>=12'} - is64bit@2.0.0: resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} engines: {node: '>=18'} @@ -7833,9 +7631,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isobject@2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} @@ -7854,8 +7652,8 @@ packages: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} - istanbul-lib-instrument@6.0.2: - resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} engines: {node: '>=10'} istanbul-lib-report@3.0.1: @@ -7870,16 +7668,16 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - iterable-lookahead@1.0.0: - resolution: {integrity: sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ==} - engines: {node: '>=4'} - iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} @@ -8031,8 +7829,8 @@ packages: node-notifier: optional: true - jiti@1.21.0: - resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true joycon@3.1.1: @@ -8078,8 +7876,8 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@3.0.1: - resolution: {integrity: sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==} + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} json-schema-ref-resolver@1.0.1: @@ -8107,8 +7905,8 @@ packages: resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -8138,8 +7936,9 @@ packages: jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} - jwt-decode@3.1.2: - resolution: {integrity: sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==} + jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} keep-func-props@4.0.1: resolution: {integrity: sha512-87ftOIICfdww3SxR5P1veq3ThBNyRPG0JGL//oaR08v0k2yTicEIHd7s0GqSJfQvlb+ybC3GiDepOweo0LDhvw==} @@ -8152,14 +7951,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - - kind-of@4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -8172,8 +7963,8 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - knip@5.12.3: - resolution: {integrity: sha512-LL+NsE+3H0TkUnQW6icHQ+5qSrPENmjHJyMHgzjiZPmunstrIsaRG+QjahnzoH/FjMjVJwrdwVOSvksa8ixFbw==} + knip@5.26.0: + resolution: {integrity: sha512-vOp+Wk86aqlPwElrUpxXyg6Q8w+j0j6wuzyu5p6k/mBWUI8iP91PCAz1Jzz9PGq5JYdptV7rFBYB9vHr7AFgqg==} engines: {node: '>=18.6.0'} hasBin: true peerDependencies: @@ -8197,13 +7988,13 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} - lambda-local@2.1.2: - resolution: {integrity: sha512-nGTJn2JxZWcLGpNwXFmXC7UEXL7QCLieQWDiXs46vIv9y/gSPm/uHygEMCaym+HIziniAw0XIm+1VTrXCvG1Zw==} + lambda-local@2.2.0: + resolution: {integrity: sha512-bPcgpIXbHnVGfI/omZIlgucDqlf4LrsunwoKue5JdZeGybt8L6KyJz2Zu19ffuZwIwLj2NAI2ZyaqNT6/cetcg==} engines: {node: '>=8'} hasBin: true - language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} language-tags@1.0.9: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} @@ -8213,8 +8004,8 @@ packages: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} - launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} + launch-editor@2.8.1: + resolution: {integrity: sha512-elBx2l/tp9z99X5H/qev8uyDywVh0VXAwEbjk8kJhnc5grOFkGh7aW6q55me9xnYbss261XtnUrysZ+XvGbhQA==} lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} @@ -8231,8 +8022,8 @@ packages: light-my-request@5.13.0: resolution: {integrity: sha512-9IjUN9ZyCS9pTG+KqTDEQo68Sui2lHsYBrfMyVUTTZ3XhH8PMZq7xO94Kr+eP9dhi/kcKsx4N41p2IXEBil1pQ==} - lilconfig@3.1.1: - resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} lines-and-columns@1.2.4: @@ -8242,17 +8033,17 @@ packages: resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - list-installed@5.3.0: - resolution: {integrity: sha512-Xl8DLrhmA/X9HRBexQOOQsMaM8eg9pzYWgyi+mGBkegKM+tJmU3ictpRbp0q3hsqFFoWvTaWbsu9F599fguK2w==} + list-installed@5.3.1: + resolution: {integrity: sha512-MLK5hj3vViLbs/RDgi/tY7rhi9ifiwnKppUF21mH2DqqMznvZhZ8TnjI0W6ZS0iCsl1qGAiHrUIMhjK7xrJstg==} engines: {node: '>=18.6.0'} listhen@1.7.2: resolution: {integrity: sha512-7/HamOm5YD9Wb7CFgAZkKgVPA96WwhcTQoqtm2VTZGVbVVn3IWKRBTgrU7cchA3Q8k9iCsG8Osoi9GX4JsGM9g==} hasBin: true - listr2@7.0.2: - resolution: {integrity: sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==} - engines: {node: '>=16.0.0'} + listr2@8.2.3: + resolution: {integrity: sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==} + engines: {node: '>=18.0.0'} load-plugin@6.0.3: resolution: {integrity: sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==} @@ -8291,9 +8082,6 @@ packages: lodash.clonedeepwith@4.5.0: resolution: {integrity: sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==} - lodash.curry@4.1.1: - resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} - lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -8343,20 +8131,20 @@ packages: resolution: {integrity: sha512-+SNGqNC1gCMJfhwYzAHr/YgNT/ZJc+V2nCkvtPnjrENMeCe+B/jgShBW0lmWoh6uVV2edFAPc/IUOkDdsjTbTg==} engines: {node: '>=12.20.0'} - log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} - log-update@5.0.1: - resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} log4js@6.9.1: resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} engines: {node: '>=8.0'} - logform@2.6.0: - resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} + logform@2.6.1: + resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} engines: {node: '>= 12.0.0'} long-timeout@0.1.1: @@ -8376,9 +8164,8 @@ packages: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -8390,21 +8177,18 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - luxon@3.4.4: - resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} engines: {node: '>=12'} lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true - macos-release@3.2.0: - resolution: {integrity: sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==} + macos-release@3.3.0: + resolution: {integrity: sha512-tPJQ1HeyiU2vRruNGhZ+VleWuMQRro8iFtJxYgnS4NQe+EukKF6aGiIT+7flZhISAt2iaXBCfFGvAyif7/f8nQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - magic-string@0.16.0: - resolution: {integrity: sha512-c4BEos3y6G2qO0B9X7K0FVLOPT9uGrjYwYRLFmDqyl5YMboUviyecnXWp94fJTSMwPw2/sf+CEYt5AGpmklkkQ==} - make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -8419,30 +8203,10 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - - map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - - map-obj@2.0.0: - resolution: {integrity: sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ==} - engines: {node: '>=4'} - - map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - map-obj@5.0.2: resolution: {integrity: sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - map-visit@1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - maxstache-stream@1.0.4: resolution: {integrity: sha512-v8qlfPN0pSp7bdSoLo1NTjG43GXGqk5W2NWFnOCq2GlmFFqebGzPCjLKSbShuqIOVorOtZSAy7O/S1OCCRONUw==} @@ -8456,8 +8220,8 @@ packages: mdast-util-from-markdown@0.8.5: resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} - mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + mdast-util-from-markdown@2.0.1: + resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} mdast-util-mdx-expression@2.0.0: resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} @@ -8493,21 +8257,21 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - memfs@4.9.2: - resolution: {integrity: sha512-f16coDZlTG1jskq3mxarwB+fGRrd0uXWt+o1WIhRfOwbXQZqUDsTVxQBFK9JjRQHblg8eAG2JSbprDXKjc7ijQ==} + memfs@4.11.1: + resolution: {integrity: sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==} engines: {node: '>= 4.0.0'} memoize-one@6.0.0: resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + memoize@10.0.0: + resolution: {integrity: sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==} + engines: {node: '>=18'} + meow@12.1.1: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} - meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} @@ -8619,18 +8383,18 @@ packages: micromark@4.0.0: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - micromatch@3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} @@ -8657,6 +8421,10 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -8669,8 +8437,8 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - mini-css-extract-plugin@2.9.0: - resolution: {integrity: sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==} + mini-css-extract-plugin@2.9.1: + resolution: {integrity: sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 @@ -8685,14 +8453,10 @@ packages: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} - minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - minimist@0.0.10: resolution: {integrity: sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==} @@ -8707,22 +8471,14 @@ packages: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - mixin-deep@1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - - mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -8735,8 +8491,8 @@ packages: engines: {node: '>=10'} hasBin: true - mlly@1.7.0: - resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} + mlly@1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} module-definition@5.0.1: resolution: {integrity: sha512-kvw3B4G19IXk+BOXnYq/D/VeO9qfHaapMeuS7w7sNUqmGaA6hywdFHMi+VWeR9wUScXM7XjoryTffCZ5B0/8IA==} @@ -8763,8 +8519,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.2.14: - resolution: {integrity: sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==} + msw@2.3.1: + resolution: {integrity: sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -8794,18 +8550,14 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nan@2.19.0: - resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==} + nan@2.20.0: + resolution: {integrity: sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==} nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanomatch@1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} @@ -8822,8 +8574,8 @@ packages: nested-error-stacks@2.1.1: resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} - netlify-cli@17.23.1: - resolution: {integrity: sha512-MISg7qb1wVP0umvB0Tn6KhZUIB/HPph0w1OzzV4DP+Mm0MS+/t0wqzcYx0WJeLdJsLzywq2lfL2smttQz/6lwQ==} + netlify-cli@17.33.4: + resolution: {integrity: sha512-wXWWxOHMab7ztaqNY1lq2OHq3lT31SW36O2upekyTekMI8KriSAGnfXQEXC8ddD4DwAViNUdBpxvjc6WaMjuug==} engines: {node: '>=18.14.0'} hasBin: true @@ -8831,30 +8583,29 @@ packages: resolution: {integrity: sha512-fTVQf8u65vS4YTP2Qt1K6Np01q3yecRKXf6VMONMlWbfl5n3M/on7pZlZISNAXHNOtnVt+6Kpwfl+RIeALC8Kg==} engines: {node: ^14.16.0 || >=16.0.0} - netlify-redirect-parser@14.2.2: - resolution: {integrity: sha512-LS3cbHZfATtfZFeJr8RLBREAjCE1rEG1CybKnA6dTLgXez0lGJE/QTPzjn6GqfNmiMowo15YQe4+UjRhbzQ04w==} + netlify-redirect-parser@14.3.0: + resolution: {integrity: sha512-/Oqq+SrTXk8hZqjCBy0AkWf5qAhsgcsdxQA09uYFdSSNG5w9rhh17a7dp77o5Q5XoHCahm8u4Kig/lbXkl4j2g==} engines: {node: ^14.16.0 || >=16.0.0} netlify-redirector@0.5.0: resolution: {integrity: sha512-4zdzIP+6muqPCuE8avnrgDJ6KW/2+UpHTRcTbMXCIRxiRmyrX+IZ4WSJGZdHPWF3WmQpXpy603XxecZ9iygN7w==} - netlify@13.1.15: - resolution: {integrity: sha512-6gZ2lMcjqiXqirwbxeXoNyQn1LcW18s8zdR9eTS8Dtuqg/h4JxI7y9ahV9fypfp0bdaTt8hkBoopBJXLQPsJmA==} + netlify@13.1.20: + resolution: {integrity: sha512-pfYUCfaywrzkMzN8If4IVM58DqsAYq2JroAFziuYK7m0LKYPzlbuSNYWhlfQL/zoBmRm8kxzRxEiK6fj1tvOOw==} engines: {node: ^14.16.0 || >=16.0.0} no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abi@3.62.0: - resolution: {integrity: sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==} + node-abi@3.67.0: + resolution: {integrity: sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==} engines: {node: '>=10'} node-addon-api@6.1.0: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} - node-addon-api@7.1.0: - resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==} - engines: {node: ^16 || ^18 || >= 20} + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} @@ -8863,15 +8614,6 @@ packages: node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} - node-fetch@2.6.12: - resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -8896,8 +8638,8 @@ packages: node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} node-schedule@2.1.1: resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==} @@ -8915,28 +8657,21 @@ packages: resolution: {integrity: sha512-Kf3L9spAL6lEHMPyqpwHSTNG3LPkOXBfSUnBMG/YE2TdoC8Qoqf0+qg01nr6K9MFQEcXtWUyTQzLJByRixSBsA==} engines: {node: '>=14.18.0'} - nodemon@3.1.0: - resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} + nodemon@3.1.4: + resolution: {integrity: sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==} engines: {node: '>=10'} hasBin: true noms@0.0.0: resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} - noop2@2.0.0: - resolution: {integrity: sha512-2bu7Pfpf6uNqashWV8P7yYeutQ3XkLY9MBSYI5sOAFZxuWcW/uJfLbKj5m6SvMDT9U1Y0C+7UFG+7VSiIdXjtA==} - - nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true - nopt@5.0.0: resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} engines: {node: '>=6'} hasBin: true - nopt@7.2.0: - resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true @@ -8944,15 +8679,12 @@ packages: resolution: {integrity: sha512-0oLZN5xcyKVrSHMk8/9RuNblEe7HEsXAt5Te2xmMiZD9VX7bqWYe0HMyfqSYFD3xv0949lZuXaEwjTqle1uWWQ==} engines: {node: '>=14.18.0'} - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - normalize-package-data@3.0.3: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} - normalize-package-data@6.0.0: - resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} engines: {node: ^16.14.0 || >=18.0.0} normalize-path@2.1.1: @@ -8967,10 +8699,22 @@ packages: resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} engines: {node: '>=14.16'} + npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-normalize-package-bin@3.0.1: resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-package-arg@11.0.3: + resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-pick-manifest@9.1.0: + resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==} + engines: {node: ^16.14.0 || >=18.0.0} + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -8981,39 +8725,30 @@ packages: npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.9: - resolution: {integrity: sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==} + nwsapi@2.2.12: + resolution: {integrity: sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-copy@0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object-pairs@0.1.0: - resolution: {integrity: sha512-3ECr6K831I4xX/Mduxr9UC+HPOz/d6WKKYj9p4cmC8Lg8p7g8gitzsxNX5IWlSIgFWN/a4JgrJaoAMKn20oKwA==} - - object-values@1.0.0: - resolution: {integrity: sha512-+8hwcz/JnQ9EpLIXzN0Rs7DLsBpJNT/xYehtB/jU93tHYr5BFEO8E+JGQNOSqE7opVzz5cGksKFHt7uUJVLSjQ==} - engines: {node: '>=0.10.0'} - - object-visit@1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - object.assign@4.1.5: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} @@ -9030,14 +8765,6 @@ packages: resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} engines: {node: '>= 0.4'} - object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - - object.pick@1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - object.values@1.2.0: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} @@ -9106,9 +8833,9 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + ora@8.0.1: + resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==} + engines: {node: '>=18'} os-name@5.1.0: resolution: {integrity: sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==} @@ -9121,8 +8848,8 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - outvariant@1.4.2: - resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==} + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} @@ -9148,6 +8875,10 @@ packages: resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-filter@4.1.0: + resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} + engines: {node: '>=18'} + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -9192,6 +8923,10 @@ packages: resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} engines: {node: '>=16'} + p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} + p-reduce@3.0.0: resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==} engines: {node: '>=12'} @@ -9228,8 +8963,11 @@ packages: resolution: {integrity: sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA==} engines: {node: '>=12'} - package-json-validator@0.6.4: - resolution: {integrity: sha512-sp5bWr5eUoVgNV50vsJyil0XCluM+qMvtba8X4ug5Z/0YtYZsePka+tZgqiZnAyFyf5pwXaSDwYncFdSEzX7PA==} + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + + package-json-validator@0.6.5: + resolution: {integrity: sha512-fEG8kM+EfX0j7TbTWAv6/0NRkid0fUHm2afJx35en3+IlrJ6dRQfKUCpuUl/bGM6MvQ0MxAlpaXkJtYVMp0F4A==} hasBin: true package-json@8.1.1: @@ -9252,9 +8990,9 @@ packages: parse-entities@4.0.1: resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} - parse-github-url@1.0.2: - resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} - engines: {node: '>=0.10.0'} + parse-github-url@1.0.3: + resolution: {integrity: sha512-tfalY5/4SqGaV/GIGzWyHnFjlpTPTNpENR9Ea2lLldSJ8EWXMsvacWucqY3m3I4YPtas15IxTLQVQ5NSYXPrww==} + engines: {node: '>= 0.10'} hasBin: true parse-gitignore@2.0.0: @@ -9295,10 +9033,6 @@ packages: pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - pascalcase@0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -9325,9 +9059,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -9346,15 +9080,15 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - peek-readable@5.0.0: - resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} + peek-readable@5.1.4: + resolution: {integrity: sha512-E7mY2VmKqw9jYuXrSWGHFuPCW2SLQenzXLF3amGaY6lXXg4/b3gj5HVM7h8ZjCO/nZS9ICs0Cz285+32FvNd/A==} engines: {node: '>=14.16'} pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -9371,11 +9105,11 @@ packages: pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@8.21.0: - resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} + pino@9.3.2: + resolution: {integrity: sha512-WtARBjgZ7LNEkrGWxMBN/jvlFiE17LTbBoH0konmBU684Kd0uIiDwBXlcTCW7iJnA6HfIKwUssS/2AC6cDEanw==} hasBin: true pirates@4.0.6: @@ -9390,8 +9124,8 @@ packages: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} - pkg-types@1.1.0: - resolution: {integrity: sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==} + pkg-types@1.2.0: + resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} pony-cause@2.1.11: resolution: {integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==} @@ -9401,24 +9135,26 @@ packages: resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} engines: {node: '>= 0.12.0'} - posix-character-classes@0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true postcss-loader@8.1.1: @@ -9458,8 +9194,8 @@ packages: peerDependencies: postcss: ^8.1.0 - postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: @@ -9471,8 +9207,8 @@ packages: peerDependencies: postcss: ^8.2.9 - postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} prebuild-install@7.1.2: @@ -9489,8 +9225,8 @@ packages: resolution: {integrity: sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==} engines: {node: '>= 0.6'} - preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} + preferred-pm@3.1.4: + resolution: {integrity: sha512-lEHd+yEm22jXdCphDrkvIJQU66EuLojPPtvZkpKIkiD+l0DMThF/niqZKJSoU8Vl7iuvtmzyMhir9LdVy5WMnA==} engines: {node: '>=10'} prelude-ls@1.2.1: @@ -9517,8 +9253,8 @@ packages: resolution: {integrity: sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==} engines: {node: '>=14.16'} - pretty-ms@9.0.0: - resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==} + pretty-ms@9.1.0: + resolution: {integrity: sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==} engines: {node: '>=18'} prettyjson@1.2.5: @@ -9532,16 +9268,28 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - process-warning@2.3.2: - resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==} - process-warning@3.0.0: resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -9593,8 +9341,8 @@ packages: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} - qs@6.12.1: - resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} querystringify@2.2.0: @@ -9609,10 +9357,6 @@ packages: quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -9623,8 +9367,8 @@ packages: radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - rambda@9.2.0: - resolution: {integrity: sha512-RjM8TBNPR+iSvWLqbBpFveDfEf2RPRKHuwBHjQdXsYFDwn3MIvgmJiqVVC1CIQKnOwzeDQd44zqDFgSKQ7RT1Q==} + rambda@9.3.0: + resolution: {integrity: sha512-cl/7DCCKNxmsbc0dXZTJTY08rvDdzLhVfE6kPBson1fWzDapLzv0RKSzjpmAqP53fkQqAvq05gpUVHTrUNsuxg==} random-bytes@1.0.0: resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} @@ -9655,8 +9399,8 @@ packages: peerDependencies: react: '>=16.13.1' - react-i18next@14.1.1: - resolution: {integrity: sha512-QSiKw+ihzJ/CIeIYWrarCmXJUySHDwQr5y8uaNIkbxoGRm/5DukkxZs+RPla79IKyyDPzC/DRlgQCABHtrQuQQ==} + react-i18next@15.0.0: + resolution: {integrity: sha512-2O3IgF4zivg57Q6p6i+ChDgJ371IDcEWbuWC6gvoh5NbkDMs0Q+O7RPr4v61+Se32E0V+LmtwePAeqWZW0bi6g==} peerDependencies: i18next: '>= 23.2.3' react: '>= 16.8.0' @@ -9681,15 +9425,15 @@ packages: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} - react-router-dom@6.23.0: - resolution: {integrity: sha512-Q9YaSYvubwgbal2c9DJKfx6hTNoBp3iJDsl+Duva/DwxoJH+OTXkxGpql4iUK2sla/8z4RpjAm6EWx1qUDuopQ==} + react-router-dom@6.25.1: + resolution: {integrity: sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.23.0: - resolution: {integrity: sha512-wPMZ8S2TuPadH0sF5irFGjkNLIcRvOSaEe7v+JER8508dyJumm6XZB1u5kztlX0RVq6AzRVndzqcUh6sFIauzA==} + react-router@6.25.1: + resolution: {integrity: sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -9716,18 +9460,10 @@ packages: resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} engines: {node: '>=18'} - read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - read-pkg-up@9.1.0: resolution: {integrity: sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - read-pkg@7.1.0: resolution: {integrity: sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==} engines: {node: '>=12.20'} @@ -9736,8 +9472,8 @@ packages: resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} engines: {node: '>=18'} - read-workspaces@1.2.0: - resolution: {integrity: sha512-y+I+SL7+p37Kf28AE/P5lXs2JuwXg5DbWJEgOBNuUPc7tfe7b0UiRfgnPsMO/sxDGGD8PPNsymgjbhmX8LwgVA==} + read-workspaces@1.2.2: + resolution: {integrity: sha512-P/girX6N7FDk7mGo/i4DB2HzanhnEhuLIAG2RvBkubQxwtEimtIDtCyA1DcHG4IC22+sr6rCppFyW8IflQ5q+Q==} engines: {node: '>=18.6.0'} read-yaml-file@1.1.0: @@ -9769,10 +9505,6 @@ packages: readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - readdirp@2.2.1: - resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} - engines: {node: '>=0.10'} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -9806,10 +9538,6 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regex-not@1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} @@ -9849,10 +9577,6 @@ packages: renderkid@3.0.0: resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} - repeat-element@1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - repeat-string@1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} @@ -9865,9 +9589,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - require-package-name@2.0.1: resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} @@ -9897,10 +9618,6 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - resolve-url@0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -9925,13 +9642,13 @@ packages: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - ret@0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} + ret@0.4.3: + resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + engines: {node: '>=10'} - ret@0.2.2: - resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} - engines: {node: '>=4'} + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} @@ -9945,23 +9662,20 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - reverse-arguments@1.0.0: - resolution: {integrity: sha512-/x8uIPdTafBqakK0TmPNJzgkLP+3H+yxpUJhCQHsLBg1rYEVNR2D8BRYNWQhVBjyOd7oo1dZRVzIkwMY2oqfYQ==} - - rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.21.0: + resolution: {integrity: sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -10001,11 +9715,8 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} - safe-regex2@2.0.0: - resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} - - safe-regex@1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + safe-regex2@3.1.0: + resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} safe-stable-stringify@2.4.3: resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} @@ -10050,10 +9761,6 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -10063,6 +9770,16 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} @@ -10081,8 +9798,8 @@ packages: set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + set-cookie-parser@2.7.0: + resolution: {integrity: sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==} set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -10092,10 +9809,6 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} - set-value@2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - setprototypeof@1.1.0: resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} @@ -10126,9 +9839,6 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shell-quote-word@1.0.1: - resolution: {integrity: sha512-lT297f1WLAdq0A4O+AknIFRP6kkiI3s8C913eJ0XqBxJbZPGWUNkRQk2u8zk4bEAjUJ5i+fSLwB6z1HzeT+DEg==} - shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} @@ -10171,41 +9881,22 @@ packages: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} - smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} - smol-toml@1.1.4: - resolution: {integrity: sha512-Y0OT8HezWsTNeEOSVxDnKOW/AyNXHQ4BwJNbAXlLTF5wWsBvrcHhIkE5Rf8kQMLmgf7nDX3PVOlgC6/Aiggu3Q==} - engines: {node: '>= 18', pnpm: '>= 8'} + smol-toml@1.3.0: + resolution: {integrity: sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA==} + engines: {node: '>= 18'} snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - snapdragon-node@2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - - snapdragon-util@3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - - snapdragon@0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} - sonic-boom@3.8.1: - resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} - - sonic-forest@1.0.2: - resolution: {integrity: sha512-2rICdwIJi5kVlehMUVtJeHn3ohh5YZV4pDv0P0c1M11cRz/gXNViItpM94HQwfvnXuzybpqK0LZJgTa3lEwtAw==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' + sonic-boom@4.0.1: + resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==} sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} @@ -10229,24 +9920,12 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} - source-map-resolve@0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map-url@0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -10271,8 +9950,8 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} spdy-transport@3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} @@ -10281,10 +9960,6 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} - split-string@3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - split2@1.1.1: resolution: {integrity: sha512-cfurE2q8LamExY+lJ9Ex3ZfBwqAPduzOKVscPDXNCLLMvyaeD3DTz1yk7fVIs6Chco+12XeD0BB6HEoYzPYbXA==} @@ -10308,10 +9983,6 @@ packages: stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - static-extend@0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -10323,19 +9994,20 @@ packages: std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} - stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} streamroller@3.1.5: resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} engines: {node: '>=8.0'} - streamx@2.16.1: - resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} + streamx@2.19.0: + resolution: {integrity: sha512-5z6CNR4gtkPbwlxyEqoDGDmWIzoNJqCBt4Eac1ICP9YaIT08ct712cFj0u1rx4F8luAuL+3Qc+RFIdI4OX00kg==} strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} @@ -10360,13 +10032,20 @@ packages: resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} engines: {node: '>=16'} - string.fromcodepoint@0.2.1: - resolution: {integrity: sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.includes@2.0.0: + resolution: {integrity: sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==} string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + string.prototype.trim@1.2.9: resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} engines: {node: '>= 0.4'} @@ -10448,9 +10127,9 @@ packages: resolution: {integrity: sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - strtok3@7.0.0: - resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==} - engines: {node: '>=14.16'} + strtok3@7.1.1: + resolution: {integrity: sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg==} + engines: {node: '>=16'} style-loader@3.3.4: resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} @@ -10493,8 +10172,8 @@ packages: svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} - svgo@3.2.0: - resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==} + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} engines: {node: '>=14.0.0'} hasBin: true @@ -10507,8 +10186,8 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - synckit@0.9.0: - resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} system-architecture@0.1.0: @@ -10539,12 +10218,12 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - temp-dir@2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} + temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} - tempy@3.0.0: - resolution: {integrity: sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==} + tempy@3.1.0: + resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} engines: {node: '>=14.16'} term-size@2.2.1: @@ -10571,8 +10250,8 @@ packages: uglify-js: optional: true - terser@5.31.0: - resolution: {integrity: sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==} + terser@5.31.6: + resolution: {integrity: sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==} engines: {node: '>=10'} hasBin: true @@ -10580,6 +10259,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-decoder@1.1.1: + resolution: {integrity: sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==} + text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} @@ -10599,18 +10281,23 @@ packages: peerDependencies: tslib: ^2 - thread-stream@2.7.0: - resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} - through2-filter@3.0.0: - resolution: {integrity: sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==} + through2-filter@4.0.0: + resolution: {integrity: sha512-P8IpQL19bSdXqGLvLdbidYRxERXgHEXGcQofPxbLpPkqS1ieOrUrocdYRTNv8YwSukaDJWr71s6F2kZ3bvgEhA==} + engines: {node: '>= 6'} - through2-map@3.0.0: - resolution: {integrity: sha512-Ms68QPbSJKjRYY7fmqZHB0VGt+vD0/tjmDHUWgxltjifCof6hZWWeQAEi27Wjbs7jyNlIIyerQw/TVj7gHkd/Q==} + through2-map@4.0.0: + resolution: {integrity: sha512-+rpmDB5yckiBGEuqJSsWYWMs9e1zdksypDKvByysEyN+knhsPXV9Z6O2mA9meczIa6AON7bi2G3xWk5T8UG4zQ==} + engines: {node: '>= 6'} through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -10621,10 +10308,6 @@ packages: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} engines: {node: '>=4'} - tiny-lru@11.2.6: - resolution: {integrity: sha512-0PU3c9PjMnltZaFo2sGYv/nnJsMjG0Cxx8X6FXHPPGjFyoo1SJDxvUXW1207rdiSxYizf31roo+GrkIByQeZoA==} - engines: {node: '>=12'} - tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} @@ -10643,34 +10326,13 @@ packages: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - to-no-case@1.0.2: - resolution: {integrity: sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==} - - to-object-path@0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} - - to-pascal-case@1.0.0: - resolution: {integrity: sha512-QGMWHqM6xPrcQW57S23c5/3BbYb0Tbe9p+ur98ckRnGDwD4wbbtDiYI38CfmMKNB5Iv0REjs5SNDntTwvDxzZA==} - - to-readable-stream@3.0.0: - resolution: {integrity: sha512-vD2LytT6DxPynBa1xbMtswY9gGqj27wNbh2uvI5OhBe+mrGLurRWRQZyQn3812sqlQRtUJwaKVshG+PoGwbPDQ==} - engines: {node: '>=12'} - - to-regex-range@2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - to-regex@3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - - to-space-case@1.0.0: - resolution: {integrity: sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==} + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} @@ -10686,8 +10348,8 @@ packages: tomlify-j0.4@3.0.0: resolution: {integrity: sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ==} - touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true tough-cookie@4.1.4: @@ -10704,8 +10366,8 @@ packages: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} - tree-dump@1.0.1: - resolution: {integrity: sha512-WCkcRBVPSlHHq1dc/px9iOfqklvzCbdRwvlNfxGZsrHqf6aZttfPrd7DJTt6oR10dwUfpFFQeVTkPbBIZxX/YA==} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -10714,10 +10376,6 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - trim-repeated@2.0.0: resolution: {integrity: sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==} engines: {node: '>=12'} @@ -10742,12 +10400,13 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-jest@29.1.2: - resolution: {integrity: sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==} - engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} + ts-jest@29.2.3: + resolution: {integrity: sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 '@jest/types': ^29.0.0 babel-jest: ^29.0.0 esbuild: '*' @@ -10756,6 +10415,8 @@ packages: peerDependenciesMeta: '@babel/core': optional: true + '@jest/transform': + optional: true '@jest/types': optional: true babel-jest: @@ -10783,15 +10444,15 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} tsscmp@1.0.6: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} - tsup@8.0.2: - resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} + tsup@8.1.2: + resolution: {integrity: sha512-Gzw/PXSX/z0aYMNmkcI54bKKFVFJQbLne+EqTJZeQ3lNT3QpumjtMU4rl+ZwTTp8oRF3ahMbEAxT2sZPJLFSrg==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -10815,11 +10476,6 @@ packages: peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true - tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -10865,10 +10521,6 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -10877,10 +10529,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - type-fest@0.8.1: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} @@ -10897,8 +10545,8 @@ packages: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} - type-fest@4.18.1: - resolution: {integrity: sha512-qXhgeNsX15bM63h5aapNFcQid9jRF/l3ojDoDFmekDQEUufZ9U4ErVt6SjDxnHp48Ltrw616R8yNc3giJ3KvVQ==} + type-fest@4.25.0: + resolution: {integrity: sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw==} engines: {node: '>=16'} type-is@1.6.18: @@ -10927,13 +10575,13 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true - ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} uid-safe@2.1.5: resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} @@ -10958,11 +10606,11 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - unenv@1.9.0: - resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - unescape-js@1.1.4: - resolution: {integrity: sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==} + unenv@1.10.0: + resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} @@ -10987,12 +10635,8 @@ packages: unified-engine@11.2.1: resolution: {integrity: sha512-xBAdZ8UY2X4R9Hm6X6kMne4Nz0PlpOc1oE6DPeqJnewr5Imkb8uT5Eyvy1h7xNekPL3PSWh3ZJyNrMW6jnNQBg==} - unified@11.0.4: - resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} - - union-value@1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} union@0.5.0: resolution: {integrity: sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==} @@ -11002,8 +10646,8 @@ packages: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} engines: {node: '>=12'} - unist-util-inspect@8.0.0: - resolution: {integrity: sha512-/3Wn/wU6/H6UEo4FoYUeo8KUePN8ERiZpQYFWYoihOsr1DoDuv80PeB0hobVZyYSvALa2e556bG1A1/AbwU4yg==} + unist-util-inspect@8.1.0: + resolution: {integrity: sha512-mOlg8Mp33pR0eeFpo5d2902ojqFFOKMMG2hF8bmH7ZlhnmjFgh0NI3/ZDwdaBJNbvrS7LZFVrBVtIE9KZ9s7vQ==} unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} @@ -11053,10 +10697,6 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unset-value@1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} - unstorage@1.10.2: resolution: {integrity: sha512-cULBcwDqrS8UhlIysUJs2Dk0Mmt8h7B0E6mtR+relW9nZvsf/u4SkAYyNliPiPW7XtFNb5u3IUMkxGxFTTRTgQ==} peerDependencies: @@ -11117,15 +10757,15 @@ packages: resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} engines: {node: '>=4'} - update-browserslist-db@1.0.14: - resolution: {integrity: sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==} + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - update-notifier@6.0.2: - resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} - engines: {node: '>=14.16'} + update-notifier@7.0.0: + resolution: {integrity: sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==} + engines: {node: '>=18'} uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} @@ -11133,10 +10773,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urix@0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} @@ -11151,10 +10787,6 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - use@3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - useless-lib@2.1.0: resolution: {integrity: sha512-HxMJ/lOLgSDcQNkI0niuCKzft4IfFy/jyF0ovmEpZvI35zSu+cytwUvj5yRfEM94ABFcpIk96BGojv0QwXFm6A==} @@ -11187,8 +10819,8 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - v8-to-istanbul@9.2.0: - resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} validate-npm-package-license@3.0.4: @@ -11198,8 +10830,8 @@ packages: resolution: {integrity: sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - validate-npm-package-name@5.0.0: - resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} vary@1.1.2: @@ -11222,11 +10854,8 @@ packages: vfile-statistics@3.0.0: resolution: {integrity: sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==} - vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - - vlq@0.2.3: - resolution: {integrity: sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==} + vfile@6.0.2: + resolution: {integrity: sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==} void-elements@3.1.0: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} @@ -11245,8 +10874,8 @@ packages: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} - wait-port@1.0.4: - resolution: {integrity: sha512-w8Ftna3h6XSFWWc2JC5gZEgp64nz8bnaTp5cvzbJSZ53j+omktWTDdwXxEF0jM8YveviLgFWvNGrSvRHnkyHyw==} + wait-port@1.1.0: + resolution: {integrity: sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==} engines: {node: '>=10'} hasBin: true @@ -11256,8 +10885,8 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} engines: {node: '>=10.13.0'} wbuf@1.7.3: @@ -11297,8 +10926,8 @@ packages: webpack-dev-server: optional: true - webpack-dev-middleware@7.2.1: - resolution: {integrity: sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==} + webpack-dev-middleware@7.4.2: + resolution: {integrity: sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==} engines: {node: '>= 18.12.0'} peerDependencies: webpack: ^5.0.0 @@ -11327,8 +10956,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.91.0: - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} + webpack@5.93.0: + resolution: {integrity: sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -11370,19 +10999,16 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + which-builtin-type@1.1.4: + resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} engines: {node: '>= 0.4'} which-collection@1.0.2: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - - which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + which-pm@2.2.0: + resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} which-typed-array@1.1.15: @@ -11398,6 +11024,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -11412,12 +11043,12 @@ packages: resolution: {integrity: sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - winston-transport@4.7.0: - resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} + winston-transport@4.7.1: + resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==} engines: {node: '>= 12.0.0'} - winston@3.13.0: - resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==} + winston@3.14.2: + resolution: {integrity: sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==} engines: {node: '>= 12.0.0'} word-wrap@1.2.5: @@ -11440,6 +11071,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -11454,8 +11089,8 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@8.14.2: - resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -11466,8 +11101,8 @@ packages: utf-8-validate: optional: true - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -11510,9 +11145,6 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -11526,19 +11158,15 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml-eslint-parser@1.2.2: - resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==} + yaml-eslint-parser@1.2.3: + resolution: {integrity: sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==} engines: {node: ^14.17.0 || >=16.0.0} - yaml@2.4.2: - resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==} + yaml@2.5.0: + resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} engines: {node: '>= 14'} hasBin: true - yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} @@ -11547,10 +11175,6 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} @@ -11574,832 +11198,902 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} - zip-stream@5.0.2: - resolution: {integrity: sha512-LfOdrUvPB8ZoXtvOBz6DlNClfvi//b5d56mSWyJi7XbH/HfhOHfUhOqxhT/rUiR7yiktlunqRo+jY6y/cWC/5g==} - engines: {node: '>= 12.0.0'} + yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + + zip-stream@6.0.1: + resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} + engines: {node: '>= 14'} - zod-validation-error@3.2.0: - resolution: {integrity: sha512-cYlPR6zuyrgmu2wRTdumEAJGuwI7eHVHGT+VyneAQxmRAKtGRL1/7pjz4wfLhz4J05f5qoSZc3rGacswgyTjjw==} + zod-validation-error@3.3.1: + resolution: {integrity: sha512-uFzCZz7FQis256dqw4AhPQgD6f3pzNca/Zh62RNELavlumQB3nDIUFbF5JQfFLcMbO1s02Q7Xg/gpcOBlEnYZA==} engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.18.0 - zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - - zod@3.23.6: - resolution: {integrity: sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==} + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} snapshots: - '@adobe/css-tools@4.3.3': {} + '@adobe/css-tools@4.4.0': {} '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.24.2': + '@babel/code-frame@7.24.7': dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 - '@babel/compat-data@7.24.4': {} + '@babel/compat-data@7.25.4': {} - '@babel/core@7.24.5': + '@babel/core@7.25.2': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.5 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helpers': 7.25.0 + '@babel/parser': 7.25.4 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.24.5': + '@babel/generator@7.25.5': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - '@babel/helper-annotate-as-pure@7.22.5': + '@babel/helper-annotate-as-pure@7.24.7': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': + '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-compilation-targets@7.23.6': + '@babel/helper-compilation-targets@7.25.2': dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 + '@babel/compat-data': 7.25.4 + '@babel/helper-validator-option': 7.24.8 + browserslist: 4.23.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 + '@babel/helper-create-class-features-plugin@7.25.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.24.8 + '@babel/helper-optimise-call-expression': 7.24.7 + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/traverse': 7.25.4 semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.5)': + '@babel/helper-create-regexp-features-plugin@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 regexpu-core: 5.3.2 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.5)': + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - debug: 4.3.4(supports-color@5.5.0) + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + debug: 4.3.6(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.22.20': {} - - '@babel/helper-function-name@7.23.0': - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - - '@babel/helper-hoist-variables@7.22.5': + '@babel/helper-member-expression-to-functions@7.24.8': dependencies: - '@babel/types': 7.24.5 - - '@babel/helper-member-expression-to-functions@7.24.5': - dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-module-imports@7.24.3': + '@babel/helper-module-imports@7.24.7': dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)': + '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-optimise-call-expression@7.22.5': + '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 - '@babel/helper-plugin-utils@7.24.5': {} + '@babel/helper-plugin-utils@7.24.8': {} - '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.5)': + '@babel/helper-remap-async-to-generator@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.24.5 - - '@babel/helper-replace-supers@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-wrap-function': 7.25.0 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-simple-access@7.24.5': + '@babel/helper-replace-supers@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/types': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-member-expression-to-functions': 7.24.8 + '@babel/helper-optimise-call-expression': 7.24.7 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-split-export-declaration@7.24.5': + '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: - '@babel/types': 7.24.5 - - '@babel/helper-string-parser@7.24.1': {} + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/helper-validator-identifier@7.24.5': {} + '@babel/helper-string-parser@7.24.8': {} - '@babel/helper-validator-option@7.23.5': {} + '@babel/helper-validator-identifier@7.24.7': {} - '@babel/helper-wrap-function@7.24.5': - dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 + '@babel/helper-validator-option@7.24.8': {} - '@babel/helpers@7.24.5': + '@babel/helper-wrap-function@7.25.0': dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/highlight@7.24.5': + '@babel/helpers@7.25.0': dependencies: - '@babel/helper-validator-identifier': 7.24.5 + '@babel/template': 7.25.0 + '@babel/types': 7.25.4 + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 - '@babel/parser@7.24.5': + '@babel/parser@7.25.4': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.5)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.5)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.5)': + '@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.24.5)': + '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-async-generator-functions@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-block-scoping@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-block-scoping@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.5)': + '@babel/plugin-transform-class-properties@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-classes@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) - '@babel/helper-split-export-declaration': 7.24.5 - globals: 11.12.0 + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-classes@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/template': 7.24.0 + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) + '@babel/traverse': 7.25.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-destructuring@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/template': 7.25.0 - '@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.25.2 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-function-name@7.25.1(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-literals@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-simple-access': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-simple-access': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.5)': + '@babel/plugin-transform-modules-systemjs@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-object-rest-spread@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-transform-optional-chaining@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-parameters@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-optional-chaining@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-private-methods@7.25.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-private-property-in-object@7.24.5(@babel/core@7.24.5)': + '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-react-constant-elements@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-react-constant-elements@7.25.1(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-react-display-name@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-react-display-name@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.24.5)': + '@babel/plugin-transform-react-jsx-development@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.5)': + '@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/types': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/types': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-react-pure-annotations@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-react-pure-annotations@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - - '@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-typeof-symbol@7.24.5(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - - '@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.5)': - dependencies: - '@babel/core': 7.24.5 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.5) - '@babel/helper-plugin-utils': 7.24.5 - - '@babel/preset-env@7.24.5(@babel/core@7.24.5)': - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.5) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.5) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.24.5) - '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.5) - '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.5) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-object-rest-spread': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-typeof-symbol': 7.24.5(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.5) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.5) - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.5) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.5) - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.5) - core-js-compat: 3.37.0 + '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-spread@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-typescript@7.25.2(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-transform-unicode-sets-regex@7.25.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/preset-env@7.25.4(@babel/core@7.25.2)': + dependencies: + '@babel/compat-data': 7.25.4 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-option': 7.24.8 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.3(@babel/core@7.25.2) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.25.2) + '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-async-generator-functions': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoping': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-class-properties': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-classes': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-destructuring': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-function-name': 7.25.1(@babel/core@7.25.2) + '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-literals': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-modules-systemjs': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-private-methods': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-typeof-symbol': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-sets-regex': 7.25.4(@babel/core@7.25.2) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.25.2) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.2) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.2) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.2) + core-js-compat: 3.38.1 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.5)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/types': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/types': 7.25.4 esutils: 2.0.3 - '@babel/preset-react@7.24.1(@babel/core@7.24.5)': + '@babel/preset-react@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-transform-react-display-name': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.5) - '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.5) - '@babel/plugin-transform-react-pure-annotations': 7.24.1(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-option': 7.24.8 + '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-react-jsx-development': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-react-pure-annotations': 7.24.7(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color - '@babel/preset-typescript@7.24.1(@babel/core@7.24.5)': + '@babel/preset-typescript@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-option': 7.24.8 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color '@babel/regjsgen@0.8.0': {} - '@babel/runtime@7.24.5': + '@babel/runtime@7.25.4': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.24.0': + '@babel/template@7.25.0': dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 - '@babel/traverse@7.24.5': + '@babel/traverse@7.25.4': dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4(supports-color@5.5.0) + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.5 + '@babel/parser': 7.25.4 + '@babel/template': 7.25.0 + '@babel/types': 7.25.4 + debug: 4.3.6(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.23.6': + '@babel/types@7.24.8': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@babel/types@7.25.2': dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 - '@babel/types@7.24.5': + '@babel/types@7.25.4': dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 '@bcoe/v8-coverage@0.2.3': {} - '@bugsnag/browser@7.22.7': + '@bugsnag/browser@7.25.0': dependencies: - '@bugsnag/core': 7.22.7 + '@bugsnag/core': 7.25.0 - '@bugsnag/core@7.22.7': + '@bugsnag/core@7.25.0': dependencies: '@bugsnag/cuid': 3.1.1 '@bugsnag/safe-json-stringify': 6.0.0 @@ -12409,14 +12103,14 @@ snapshots: '@bugsnag/cuid@3.1.1': {} - '@bugsnag/js@7.22.7': + '@bugsnag/js@7.25.0': dependencies: - '@bugsnag/browser': 7.22.7 - '@bugsnag/node': 7.22.7 + '@bugsnag/browser': 7.25.0 + '@bugsnag/node': 7.25.0 - '@bugsnag/node@7.22.7': + '@bugsnag/node@7.25.0': dependencies: - '@bugsnag/core': 7.22.7 + '@bugsnag/core': 7.25.0 byline: 5.0.0 error-stack-parser: 2.1.4 iserror: 0.0.2 @@ -12433,12 +12127,13 @@ snapshots: dependencies: statuses: 2.0.1 - '@changesets/apply-release-plan@7.0.0': + '@changesets/apply-release-plan@7.0.4': dependencies: - '@babel/runtime': 7.24.5 - '@changesets/config': 3.0.0 + '@babel/runtime': 7.25.4 + '@changesets/config': 3.0.2 '@changesets/get-version-range-type': 0.4.0 '@changesets/git': 3.0.0 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 detect-indent: 6.1.0 @@ -12447,16 +12142,17 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.6.0 + semver: 7.6.3 - '@changesets/assemble-release-plan@6.0.0': + '@changesets/assemble-release-plan@6.0.3': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.1 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - semver: 7.6.0 + semver: 7.6.3 '@changesets/changelog-git@0.2.0': dependencies: @@ -12470,22 +12166,23 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.27.1': + '@changesets/cli@2.27.7': dependencies: - '@babel/runtime': 7.24.5 - '@changesets/apply-release-plan': 7.0.0 - '@changesets/assemble-release-plan': 6.0.0 + '@babel/runtime': 7.25.4 + '@changesets/apply-release-plan': 7.0.4 + '@changesets/assemble-release-plan': 6.0.3 '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.2 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 + '@changesets/get-dependents-graph': 2.1.1 + '@changesets/get-release-plan': 4.0.3 '@changesets/git': 3.0.0 '@changesets/logger': 0.1.0 '@changesets/pre': 2.0.0 '@changesets/read': 0.6.0 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 - '@changesets/write': 0.3.0 + '@changesets/write': 0.3.1 '@manypkg/get-packages': 1.1.3 '@types/semver': 7.5.8 ansi-colors: 4.1.3 @@ -12495,37 +12192,36 @@ snapshots: external-editor: 3.1.0 fs-extra: 7.0.1 human-id: 1.0.2 - meow: 6.1.1 + mri: 1.2.0 outdent: 0.5.0 p-limit: 2.3.0 - preferred-pm: 3.1.3 + preferred-pm: 3.1.4 resolve-from: 5.0.0 - semver: 7.6.0 + semver: 7.6.3 spawndamnit: 2.0.0 term-size: 2.2.1 - tty-table: 4.2.3 - '@changesets/config@3.0.0': + '@changesets/config@3.0.2': dependencies: '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.1 '@changesets/logger': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - micromatch: 4.0.5 + micromatch: 4.0.8 '@changesets/errors@0.2.0': dependencies: extendable-error: 0.1.7 - '@changesets/get-dependents-graph@2.0.0': + '@changesets/get-dependents-graph@2.1.1': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.6.0 + semver: 7.6.3 '@changesets/get-github-info@0.6.0': dependencies: @@ -12534,11 +12230,11 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.0': + '@changesets/get-release-plan@4.0.3': dependencies: - '@babel/runtime': 7.24.5 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 + '@babel/runtime': 7.25.4 + '@changesets/assemble-release-plan': 6.0.3 + '@changesets/config': 3.0.2 '@changesets/pre': 2.0.0 '@changesets/read': 0.6.0 '@changesets/types': 6.0.0 @@ -12548,12 +12244,12 @@ snapshots: '@changesets/git@3.0.0': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/errors': 0.2.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 is-subdir: 1.2.0 - micromatch: 4.0.5 + micromatch: 4.0.8 spawndamnit: 2.0.0 '@changesets/logger@0.1.0': @@ -12567,7 +12263,7 @@ snapshots: '@changesets/pre@2.0.0': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/errors': 0.2.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -12575,7 +12271,7 @@ snapshots: '@changesets/read@0.6.0': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/git': 3.0.0 '@changesets/logger': 0.1.0 '@changesets/parse': 0.4.0 @@ -12584,13 +12280,19 @@ snapshots: fs-extra: 7.0.1 p-filter: 2.1.0 + '@changesets/should-skip-package@0.1.0': + dependencies: + '@babel/runtime': 7.25.4 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + '@changesets/types@4.1.0': {} '@changesets/types@6.0.0': {} - '@changesets/write@0.3.0': + '@changesets/write@0.3.1': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/types': 6.0.0 fs-extra: 7.0.1 human-id: 1.0.2 @@ -12615,233 +12317,214 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@ericcornelissen/bash-parser@0.5.2': - dependencies: - array-last: 1.3.0 - babylon: 6.18.0 - compose-function: 3.0.3 - deep-freeze: 0.0.1 - filter-iterator: 0.0.1 - filter-obj: 1.1.0 - has-own-property: 0.1.0 - identity-function: 1.0.0 - is-iterable: 1.1.1 - iterable-lookahead: 1.0.0 - lodash.curry: 4.1.1 - magic-string: 0.16.0 - map-obj: 2.0.0 - object-pairs: 0.1.0 - object-values: 1.0.0 - reverse-arguments: 1.0.0 - shell-quote-word: 1.0.1 - to-pascal-case: 1.0.0 - unescape-js: 1.1.4 - '@esbuild/aix-ppc64@0.19.11': optional: true - '@esbuild/aix-ppc64@0.19.12': + '@esbuild/aix-ppc64@0.21.2': optional: true - '@esbuild/aix-ppc64@0.20.2': + '@esbuild/aix-ppc64@0.23.1': optional: true '@esbuild/android-arm64@0.19.11': optional: true - '@esbuild/android-arm64@0.19.12': + '@esbuild/android-arm64@0.21.2': optional: true - '@esbuild/android-arm64@0.20.2': + '@esbuild/android-arm64@0.23.1': optional: true '@esbuild/android-arm@0.19.11': optional: true - '@esbuild/android-arm@0.19.12': + '@esbuild/android-arm@0.21.2': optional: true - '@esbuild/android-arm@0.20.2': + '@esbuild/android-arm@0.23.1': optional: true '@esbuild/android-x64@0.19.11': optional: true - '@esbuild/android-x64@0.19.12': + '@esbuild/android-x64@0.21.2': optional: true - '@esbuild/android-x64@0.20.2': + '@esbuild/android-x64@0.23.1': optional: true '@esbuild/darwin-arm64@0.19.11': optional: true - '@esbuild/darwin-arm64@0.19.12': + '@esbuild/darwin-arm64@0.21.2': optional: true - '@esbuild/darwin-arm64@0.20.2': + '@esbuild/darwin-arm64@0.23.1': optional: true '@esbuild/darwin-x64@0.19.11': optional: true - '@esbuild/darwin-x64@0.19.12': + '@esbuild/darwin-x64@0.21.2': optional: true - '@esbuild/darwin-x64@0.20.2': + '@esbuild/darwin-x64@0.23.1': optional: true '@esbuild/freebsd-arm64@0.19.11': optional: true - '@esbuild/freebsd-arm64@0.19.12': + '@esbuild/freebsd-arm64@0.21.2': optional: true - '@esbuild/freebsd-arm64@0.20.2': + '@esbuild/freebsd-arm64@0.23.1': optional: true '@esbuild/freebsd-x64@0.19.11': optional: true - '@esbuild/freebsd-x64@0.19.12': + '@esbuild/freebsd-x64@0.21.2': optional: true - '@esbuild/freebsd-x64@0.20.2': + '@esbuild/freebsd-x64@0.23.1': optional: true '@esbuild/linux-arm64@0.19.11': optional: true - '@esbuild/linux-arm64@0.19.12': + '@esbuild/linux-arm64@0.21.2': optional: true - '@esbuild/linux-arm64@0.20.2': + '@esbuild/linux-arm64@0.23.1': optional: true '@esbuild/linux-arm@0.19.11': optional: true - '@esbuild/linux-arm@0.19.12': + '@esbuild/linux-arm@0.21.2': optional: true - '@esbuild/linux-arm@0.20.2': + '@esbuild/linux-arm@0.23.1': optional: true '@esbuild/linux-ia32@0.19.11': optional: true - '@esbuild/linux-ia32@0.19.12': + '@esbuild/linux-ia32@0.21.2': optional: true - '@esbuild/linux-ia32@0.20.2': + '@esbuild/linux-ia32@0.23.1': optional: true '@esbuild/linux-loong64@0.19.11': optional: true - '@esbuild/linux-loong64@0.19.12': + '@esbuild/linux-loong64@0.21.2': optional: true - '@esbuild/linux-loong64@0.20.2': + '@esbuild/linux-loong64@0.23.1': optional: true '@esbuild/linux-mips64el@0.19.11': optional: true - '@esbuild/linux-mips64el@0.19.12': + '@esbuild/linux-mips64el@0.21.2': optional: true - '@esbuild/linux-mips64el@0.20.2': + '@esbuild/linux-mips64el@0.23.1': optional: true '@esbuild/linux-ppc64@0.19.11': optional: true - '@esbuild/linux-ppc64@0.19.12': + '@esbuild/linux-ppc64@0.21.2': optional: true - '@esbuild/linux-ppc64@0.20.2': + '@esbuild/linux-ppc64@0.23.1': optional: true '@esbuild/linux-riscv64@0.19.11': optional: true - '@esbuild/linux-riscv64@0.19.12': + '@esbuild/linux-riscv64@0.21.2': optional: true - '@esbuild/linux-riscv64@0.20.2': + '@esbuild/linux-riscv64@0.23.1': optional: true '@esbuild/linux-s390x@0.19.11': optional: true - '@esbuild/linux-s390x@0.19.12': + '@esbuild/linux-s390x@0.21.2': optional: true - '@esbuild/linux-s390x@0.20.2': + '@esbuild/linux-s390x@0.23.1': optional: true '@esbuild/linux-x64@0.19.11': optional: true - '@esbuild/linux-x64@0.19.12': + '@esbuild/linux-x64@0.21.2': optional: true - '@esbuild/linux-x64@0.20.2': + '@esbuild/linux-x64@0.23.1': optional: true '@esbuild/netbsd-x64@0.19.11': optional: true - '@esbuild/netbsd-x64@0.19.12': + '@esbuild/netbsd-x64@0.21.2': + optional: true + + '@esbuild/netbsd-x64@0.23.1': optional: true - '@esbuild/netbsd-x64@0.20.2': + '@esbuild/openbsd-arm64@0.23.1': optional: true '@esbuild/openbsd-x64@0.19.11': optional: true - '@esbuild/openbsd-x64@0.19.12': + '@esbuild/openbsd-x64@0.21.2': optional: true - '@esbuild/openbsd-x64@0.20.2': + '@esbuild/openbsd-x64@0.23.1': optional: true '@esbuild/sunos-x64@0.19.11': optional: true - '@esbuild/sunos-x64@0.19.12': + '@esbuild/sunos-x64@0.21.2': optional: true - '@esbuild/sunos-x64@0.20.2': + '@esbuild/sunos-x64@0.23.1': optional: true '@esbuild/win32-arm64@0.19.11': optional: true - '@esbuild/win32-arm64@0.19.12': + '@esbuild/win32-arm64@0.21.2': optional: true - '@esbuild/win32-arm64@0.20.2': + '@esbuild/win32-arm64@0.23.1': optional: true '@esbuild/win32-ia32@0.19.11': optional: true - '@esbuild/win32-ia32@0.19.12': + '@esbuild/win32-ia32@0.21.2': optional: true - '@esbuild/win32-ia32@0.20.2': + '@esbuild/win32-ia32@0.23.1': optional: true '@esbuild/win32-x64@0.19.11': optional: true - '@esbuild/win32-x64@0.19.12': + '@esbuild/win32-x64@0.21.2': optional: true - '@esbuild/win32-x64@0.20.2': + '@esbuild/win32-x64@0.23.1': optional: true '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': @@ -12849,15 +12532,15 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.11.0': {} '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) espree: 9.6.1 globals: 13.24.0 - ignore: 5.3.1 + ignore: 5.3.2 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -12869,17 +12552,17 @@ snapshots: '@fastify/accept-negotiator@1.1.0': {} - '@fastify/ajv-compiler@3.5.0': + '@fastify/ajv-compiler@3.6.0': dependencies: - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) - fast-uri: 2.3.0 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + fast-uri: 2.4.0 '@fastify/error@3.4.1': {} '@fastify/fast-json-stringify-compiler@4.3.0': dependencies: - fast-json-stringify: 5.15.0 + fast-json-stringify: 5.16.1 '@fastify/merge-json-schemas@0.1.1': dependencies: @@ -12893,43 +12576,43 @@ snapshots: http-errors: 2.0.0 mime: 3.0.0 - '@fastify/static@6.12.0': + '@fastify/static@7.0.4': dependencies: '@fastify/accept-negotiator': 1.1.0 '@fastify/send': 2.1.0 content-disposition: 0.5.4 fastify-plugin: 4.5.1 - glob: 8.1.0 - p-limit: 3.1.0 + fastq: 1.17.1 + glob: 10.4.5 - '@formatjs/ecma402-abstract@1.18.2': + '@formatjs/ecma402-abstract@2.0.0': dependencies: '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.6.2 + tslib: 2.6.3 '@formatjs/fast-memoize@2.2.0': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 - '@formatjs/icu-messageformat-parser@2.7.6': + '@formatjs/icu-messageformat-parser@2.7.8': dependencies: - '@formatjs/ecma402-abstract': 1.18.2 - '@formatjs/icu-skeleton-parser': 1.8.0 - tslib: 2.6.2 + '@formatjs/ecma402-abstract': 2.0.0 + '@formatjs/icu-skeleton-parser': 1.8.2 + tslib: 2.6.3 - '@formatjs/icu-skeleton-parser@1.8.0': + '@formatjs/icu-skeleton-parser@1.8.2': dependencies: - '@formatjs/ecma402-abstract': 1.18.2 - tslib: 2.6.2 + '@formatjs/ecma402-abstract': 2.0.0 + tslib: 2.6.3 '@formatjs/intl-localematcher@0.5.4': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -12944,47 +12627,49 @@ snapshots: '@import-maps/resolve@1.0.1': {} - '@inquirer/confirm@3.1.6': + '@inquirer/confirm@3.1.22': dependencies: - '@inquirer/core': 8.1.0 - '@inquirer/type': 1.3.1 + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 - '@inquirer/core@8.1.0': + '@inquirer/core@9.0.10': dependencies: - '@inquirer/figures': 1.0.1 - '@inquirer/type': 1.3.1 + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.2 '@types/mute-stream': 0.0.4 - '@types/node': 20.12.7 + '@types/node': 22.5.0 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 - chalk: 4.1.2 cli-spinners: 2.9.2 cli-width: 4.1.0 mute-stream: 1.0.0 signal-exit: 4.1.0 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 - '@inquirer/figures@1.0.1': {} + '@inquirer/figures@1.0.5': {} - '@inquirer/type@1.3.1': {} + '@inquirer/type@1.5.2': + dependencies: + mute-stream: 1.0.0 - '@internationalized/date@3.5.3': + '@internationalized/date@3.5.5': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 - '@internationalized/message@3.1.3': + '@internationalized/message@3.1.4': dependencies: - '@swc/helpers': 0.5.11 - intl-messageformat: 10.5.11 + '@swc/helpers': 0.5.12 + intl-messageformat: 10.5.14 - '@internationalized/number@3.5.2': + '@internationalized/number@3.5.3': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 - '@internationalized/string@3.2.2': + '@internationalized/string@3.2.3': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 '@isaacs/cliui@8.0.2': dependencies: @@ -13008,27 +12693,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))': + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -13040,7 +12725,7 @@ snapshots: jest-util: 29.7.0 jest-validate: 29.7.0 jest-watcher: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 pretty-format: 29.7.0 slash: 3.0.0 strip-ansi: 6.0.1 @@ -13057,7 +12742,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -13075,7 +12760,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -13097,14 +12782,14 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 glob: 7.2.3 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.2 + istanbul-lib-instrument: 6.0.3 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.1.7 @@ -13114,7 +12799,7 @@ snapshots: slash: 3.0.0 string-length: 4.0.2 strip-ansi: 6.0.1 - v8-to-istanbul: 9.2.0 + v8-to-istanbul: 9.3.0 transitivePeerDependencies: - supports-color @@ -13144,7 +12829,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 babel-plugin-istanbul: 6.1.1 @@ -13155,7 +12840,7 @@ snapshots: jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 jest-util: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 pirates: 4.0.6 slash: 3.0.0 write-file-atomic: 4.0.2 @@ -13166,7 +12851,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/yargs': 16.0.9 chalk: 4.1.2 @@ -13175,14 +12860,14 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 - '@types/yargs': 17.0.32 + '@types/node': 20.14.11 + '@types/yargs': 17.0.33 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.2': {} @@ -13194,33 +12879,33 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 - '@jsonjoy.com/base64@1.1.1(tslib@2.6.2)': + '@jsonjoy.com/base64@1.1.2(tslib@2.6.3)': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 - '@jsonjoy.com/json-pack@1.0.3(tslib@2.6.2)': + '@jsonjoy.com/json-pack@1.1.0(tslib@2.6.3)': dependencies: - '@jsonjoy.com/base64': 1.1.1(tslib@2.6.2) - '@jsonjoy.com/util': 1.1.2(tslib@2.6.2) + '@jsonjoy.com/base64': 1.1.2(tslib@2.6.3) + '@jsonjoy.com/util': 1.3.0(tslib@2.6.3) hyperdyperid: 1.2.0 - thingies: 1.21.0(tslib@2.6.2) - tslib: 2.6.2 + thingies: 1.21.0(tslib@2.6.3) + tslib: 2.6.3 - '@jsonjoy.com/util@1.1.2(tslib@2.6.2)': + '@jsonjoy.com/util@1.3.0(tslib@2.6.3)': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 '@leichtgewicht/ip-codec@2.0.5': {} @@ -13228,14 +12913,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -13251,7 +12936,7 @@ snapshots: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.6.0 + semver: 7.6.3 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -13266,20 +12951,24 @@ snapshots: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.6.0 + semver: 7.6.3 tar: 6.2.1 transitivePeerDependencies: - encoding - supports-color - '@module-federation/dts-plugin@0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))': + '@module-federation/bridge-react-webpack-plugin@0.2.6': + dependencies: + '@module-federation/sdk': 0.2.6 + + '@module-federation/dts-plugin@0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': dependencies: '@module-federation/managers': 0.1.11 '@module-federation/sdk': 0.1.11 '@module-federation/third-party-dts-extractor': 0.1.11 - adm-zip: 0.5.12 + adm-zip: 0.5.15 ansi-colors: 4.1.3 - axios: 1.6.8 + axios: 1.7.5 chalk: 3.0.0 fs-extra: 9.1.0 isomorphic-ws: 5.0.0(ws@8.5.0) @@ -13287,9 +12976,9 @@ snapshots: lodash.clonedeepwith: 4.5.0 log4js: 6.9.1 node-schedule: 2.1.1 - rambda: 9.2.0 - typescript: 5.4.5 - vue-tsc: 1.8.27(typescript@5.4.5) + rambda: 9.3.0 + typescript: 5.5.3 + vue-tsc: 1.8.27(typescript@5.5.3) ws: 8.5.0 transitivePeerDependencies: - bufferutil @@ -13297,17 +12986,43 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12))': + '@module-federation/dts-plugin@0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': dependencies: - '@module-federation/dts-plugin': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) + '@module-federation/managers': 0.2.6 + '@module-federation/sdk': 0.2.6 + '@module-federation/third-party-dts-extractor': 0.2.6 + adm-zip: 0.5.15 + ansi-colors: 4.1.3 + axios: 1.7.5 + chalk: 3.0.0 + fs-extra: 9.1.0 + isomorphic-ws: 5.0.0(ws@8.17.1) + koa: 2.11.0 + lodash.clonedeepwith: 4.5.0 + log4js: 6.9.1 + node-schedule: 2.1.1 + rambda: 9.3.0 + typescript: 5.5.3 + ws: 8.17.1 + optionalDependencies: + vue-tsc: 1.8.27(typescript@5.5.3) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + '@module-federation/enhanced@0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': + dependencies: + '@module-federation/dts-plugin': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) '@module-federation/managers': 0.1.11 - '@module-federation/manifest': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) - '@module-federation/rspack': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) + '@module-federation/manifest': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/rspack': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) '@module-federation/runtime-tools': 0.1.11 '@module-federation/sdk': 0.1.11 upath: 2.0.1 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) transitivePeerDependencies: - bufferutil - debug @@ -13316,24 +13031,26 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/enhanced@0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@module-federation/enhanced@0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)))': dependencies: - '@module-federation/dts-plugin': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) - '@module-federation/managers': 0.1.11 - '@module-federation/manifest': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) - '@module-federation/rspack': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) - '@module-federation/runtime-tools': 0.1.11 - '@module-federation/sdk': 0.1.11 + '@module-federation/bridge-react-webpack-plugin': 0.2.6 + '@module-federation/dts-plugin': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/managers': 0.2.6 + '@module-federation/manifest': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/rspack': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/runtime-tools': 0.2.6 + '@module-federation/sdk': 0.2.6 + btoa: 1.2.1 upath: 2.0.1 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + typescript: 5.5.3 + vue-tsc: 1.8.27(typescript@5.5.3) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) transitivePeerDependencies: - bufferutil - debug - supports-color - - typescript - utf-8-validate - - vue-tsc '@module-federation/managers@0.1.11': dependencies: @@ -13341,9 +13058,15 @@ snapshots: find-pkg: 2.0.0 fs-extra: 9.1.0 - '@module-federation/manifest@0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))': + '@module-federation/managers@0.2.6': dependencies: - '@module-federation/dts-plugin': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) + '@module-federation/sdk': 0.2.6 + find-pkg: 2.0.0 + fs-extra: 9.1.0 + + '@module-federation/manifest@0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': + dependencies: + '@module-federation/dts-plugin': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) '@module-federation/managers': 0.1.11 '@module-federation/sdk': 0.1.11 chalk: 3.0.0 @@ -13356,11 +13079,26 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/rspack@0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))': + '@module-federation/manifest@0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': + dependencies: + '@module-federation/dts-plugin': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/managers': 0.2.6 + '@module-federation/sdk': 0.2.6 + chalk: 3.0.0 + find-pkg: 2.0.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + '@module-federation/rspack@0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': dependencies: - '@module-federation/dts-plugin': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) + '@module-federation/dts-plugin': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) '@module-federation/managers': 0.1.11 - '@module-federation/manifest': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5)) + '@module-federation/manifest': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) '@module-federation/runtime-tools': 0.1.11 '@module-federation/sdk': 0.1.11 transitivePeerDependencies: @@ -13371,85 +13109,114 @@ snapshots: - utf-8-validate - vue-tsc + '@module-federation/rspack@0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))': + dependencies: + '@module-federation/bridge-react-webpack-plugin': 0.2.6 + '@module-federation/dts-plugin': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/managers': 0.2.6 + '@module-federation/manifest': 0.2.6(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3)) + '@module-federation/runtime-tools': 0.2.6 + '@module-federation/sdk': 0.2.6 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + '@module-federation/runtime-tools@0.1.11': dependencies: '@module-federation/runtime': 0.1.11 '@module-federation/webpack-bundler-runtime': 0.1.11 + '@module-federation/runtime-tools@0.2.6': + dependencies: + '@module-federation/runtime': 0.2.6 + '@module-federation/webpack-bundler-runtime': 0.2.6 + '@module-federation/runtime@0.1.11': dependencies: '@module-federation/sdk': 0.1.11 + '@module-federation/runtime@0.2.6': + dependencies: + '@module-federation/sdk': 0.2.6 + '@module-federation/sdk@0.1.11': {} + '@module-federation/sdk@0.2.6': {} + '@module-federation/third-party-dts-extractor@0.1.11': dependencies: find-pkg: 2.0.0 fs-extra: 9.1.0 resolve: 1.22.8 + '@module-federation/third-party-dts-extractor@0.2.6': + dependencies: + find-pkg: 2.0.0 + fs-extra: 9.1.0 + resolve: 1.22.8 + '@module-federation/webpack-bundler-runtime@0.1.11': dependencies: '@module-federation/runtime': 0.1.11 '@module-federation/sdk': 0.1.11 - '@mswjs/cookies@1.1.0': {} - - '@mswjs/interceptors@0.26.15': + '@module-federation/webpack-bundler-runtime@0.2.6': dependencies: - '@open-draft/deferred-promise': 2.2.0 - '@open-draft/logger': 0.3.0 - '@open-draft/until': 2.1.0 - is-node-process: 1.2.0 - outvariant: 1.4.2 - strict-event-emitter: 0.5.1 + '@module-federation/runtime': 0.2.6 + '@module-federation/sdk': 0.2.6 - '@mswjs/interceptors@0.27.2': + '@mswjs/cookies@1.1.1': {} + + '@mswjs/interceptors@0.29.1': dependencies: '@open-draft/deferred-promise': 2.2.0 '@open-draft/logger': 0.3.0 '@open-draft/until': 2.1.0 is-node-process: 1.2.0 - outvariant: 1.4.2 + outvariant: 1.4.3 strict-event-emitter: 0.5.1 '@netlify/binary-info@1.0.0': {} - '@netlify/blobs@7.3.0': {} + '@netlify/blobs@7.4.0': {} - '@netlify/build-info@7.13.2': + '@netlify/build-info@7.14.1': dependencies: - '@bugsnag/js': 7.22.7 + '@bugsnag/js': 7.25.0 '@iarna/toml': 2.2.5 dot-prop: 7.2.0 find-up: 6.3.0 - minimatch: 9.0.4 + minimatch: 9.0.5 read-pkg: 7.1.0 - semver: 7.6.0 - yaml: 2.4.2 + semver: 7.6.3 + yaml: 2.5.0 yargs: 17.7.2 - '@netlify/build@29.41.2(@opentelemetry/api@1.8.0)(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(picomatch@4.0.2)': + '@netlify/build@29.51.3(@opentelemetry/api@1.8.0)(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/node@22.5.0)(picomatch@4.0.2)': dependencies: - '@bugsnag/js': 7.22.7 - '@netlify/blobs': 7.3.0 - '@netlify/cache-utils': 5.1.5 - '@netlify/config': 20.12.3 - '@netlify/edge-bundler': 12.0.0(supports-color@9.4.0) - '@netlify/framework-info': 9.8.11 - '@netlify/functions-utils': 5.2.55(@opentelemetry/api@1.8.0)(supports-color@9.4.0) + '@bugsnag/js': 7.25.0 + '@netlify/blobs': 7.4.0 + '@netlify/cache-utils': 5.1.6 + '@netlify/config': 20.17.1 + '@netlify/edge-bundler': 12.2.2(supports-color@9.4.0) + '@netlify/framework-info': 9.8.13 + '@netlify/functions-utils': 5.2.79(supports-color@9.4.0) '@netlify/git-utils': 5.1.1 - '@netlify/opentelemetry-utils': 1.2.0(@opentelemetry/api@1.8.0) - '@netlify/plugins-list': 6.78.0 + '@netlify/opentelemetry-utils': 1.2.1(@opentelemetry/api@1.8.0) + '@netlify/plugins-list': 6.80.0 '@netlify/run-utils': 5.1.1 - '@netlify/zip-it-and-ship-it': 9.32.1(@opentelemetry/api@1.8.0)(supports-color@9.4.0) + '@netlify/zip-it-and-ship-it': 9.37.7(supports-color@9.4.0) '@opentelemetry/api': 1.8.0 '@sindresorhus/slugify': 2.2.1 ansi-escapes: 6.2.1 chalk: 5.3.0 clean-stack: 4.2.0 execa: 6.1.0 - fdir: 6.1.1(picomatch@4.0.2) + fdir: 6.2.0(picomatch@4.0.2) figures: 5.0.0 filter-obj: 5.1.0 got: 12.6.1 @@ -13462,7 +13229,7 @@ snapshots: log-process-errors: 8.0.0 map-obj: 5.0.2 memoize-one: 6.0.0 - minimatch: 9.0.4 + minimatch: 9.0.5 node-fetch: 3.3.2 os-name: 5.1.0 p-event: 5.0.1 @@ -13476,18 +13243,18 @@ snapshots: pkg-dir: 7.0.0 pretty-ms: 8.0.0 ps-list: 8.1.1 - read-pkg-up: 9.1.0 + read-package-up: 11.0.0 readdirp: 3.6.0 resolve: 2.0.0-next.5 - rfdc: 1.3.1 + rfdc: 1.4.1 safe-json-stringify: 1.2.0 - semver: 7.6.0 + semver: 7.6.3 string-width: 5.1.2 strip-ansi: 7.1.0 supports-color: 9.4.0 terminal-link: 3.0.0 - ts-node: 10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) - typescript: 5.4.5 + ts-node: 10.9.2(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/node@22.5.0)(typescript@5.5.3) + typescript: 5.5.3 uuid: 9.0.1 yargs: 17.7.2 transitivePeerDependencies: @@ -13497,7 +13264,7 @@ snapshots: - encoding - picomatch - '@netlify/cache-utils@5.1.5': + '@netlify/cache-utils@5.1.6': dependencies: cpy: 9.0.1 get-stream: 6.0.1 @@ -13508,7 +13275,7 @@ snapshots: path-exists: 5.0.0 readdirp: 3.6.0 - '@netlify/config@20.12.3': + '@netlify/config@20.17.1': dependencies: '@iarna/toml': 2.2.5 chalk: 5.3.0 @@ -13524,9 +13291,9 @@ snapshots: is-plain-obj: 4.1.0 js-yaml: 4.1.0 map-obj: 5.0.2 - netlify: 13.1.15 + netlify: 13.1.20 netlify-headers-parser: 7.1.4 - netlify-redirect-parser: 14.2.2 + netlify-redirect-parser: 14.3.0 node-fetch: 3.3.2 omit.js: 2.0.2 p-locate: 6.0.0 @@ -13535,28 +13302,28 @@ snapshots: validate-npm-package-name: 4.0.0 yargs: 17.7.2 - '@netlify/edge-bundler@12.0.0': + '@netlify/edge-bundler@12.2.2': dependencies: '@import-maps/resolve': 1.0.1 - '@vercel/nft': 0.26.4 - ajv: 8.13.0 - ajv-errors: 3.0.0(ajv@8.13.0) - better-ajv-errors: 1.2.0(ajv@8.13.0) + '@vercel/nft': 0.27.3 + ajv: 8.17.1 + ajv-errors: 3.0.0(ajv@8.17.1) + better-ajv-errors: 1.2.0(ajv@8.17.1) common-path-prefix: 3.0.0 env-paths: 3.0.0 - esbuild: 0.20.2 + esbuild: 0.21.2 execa: 6.1.0 find-up: 6.3.0 get-package-name: 2.2.0 get-port: 6.1.2 is-path-inside: 4.0.0 - jsonc-parser: 3.2.1 + jsonc-parser: 3.3.1 node-fetch: 3.3.2 node-stream-zip: 1.15.0 p-retry: 5.1.2 p-wait-for: 4.1.0 path-key: 4.0.0 - semver: 7.6.0 + semver: 7.6.3 tmp-promise: 3.0.3 urlpattern-polyfill: 8.0.2 uuid: 9.0.1 @@ -13564,28 +13331,28 @@ snapshots: - encoding - supports-color - '@netlify/edge-bundler@12.0.0(supports-color@9.4.0)': + '@netlify/edge-bundler@12.2.2(supports-color@9.4.0)': dependencies: '@import-maps/resolve': 1.0.1 - '@vercel/nft': 0.26.4(supports-color@9.4.0) - ajv: 8.13.0 - ajv-errors: 3.0.0(ajv@8.13.0) - better-ajv-errors: 1.2.0(ajv@8.13.0) + '@vercel/nft': 0.27.3(supports-color@9.4.0) + ajv: 8.17.1 + ajv-errors: 3.0.0(ajv@8.17.1) + better-ajv-errors: 1.2.0(ajv@8.17.1) common-path-prefix: 3.0.0 env-paths: 3.0.0 - esbuild: 0.20.2 + esbuild: 0.21.2 execa: 6.1.0 find-up: 6.3.0 get-package-name: 2.2.0 get-port: 6.1.2 is-path-inside: 4.0.0 - jsonc-parser: 3.2.1 + jsonc-parser: 3.3.1 node-fetch: 3.3.2 node-stream-zip: 1.15.0 p-retry: 5.1.2 p-wait-for: 4.1.0 path-key: 4.0.0 - semver: 7.6.0 + semver: 7.6.3 tmp-promise: 3.0.3 urlpattern-polyfill: 8.0.2 uuid: 9.0.1 @@ -13593,11 +13360,11 @@ snapshots: - encoding - supports-color - '@netlify/edge-functions@2.5.1': {} + '@netlify/edge-functions@2.9.0': {} - '@netlify/framework-info@9.8.11': + '@netlify/framework-info@9.8.13': dependencies: - ajv: 8.13.0 + ajv: 8.17.1 filter-obj: 5.1.0 find-up: 6.3.0 is-plain-obj: 4.1.0 @@ -13606,15 +13373,14 @@ snapshots: p-locate: 6.0.0 process: 0.11.10 read-pkg-up: 9.1.0 - semver: 7.6.0 + semver: 7.6.3 - '@netlify/functions-utils@5.2.55(@opentelemetry/api@1.8.0)(supports-color@9.4.0)': + '@netlify/functions-utils@5.2.79(supports-color@9.4.0)': dependencies: - '@netlify/zip-it-and-ship-it': 9.32.1(@opentelemetry/api@1.8.0)(supports-color@9.4.0) + '@netlify/zip-it-and-ship-it': 9.38.0(supports-color@9.4.0) cpy: 9.0.1 path-exists: 5.0.0 transitivePeerDependencies: - - '@opentelemetry/api' - encoding - supports-color @@ -13622,7 +13388,7 @@ snapshots: dependencies: execa: 6.1.0 map-obj: 5.0.2 - micromatch: 4.0.5 + micromatch: 4.0.8 moize: 6.1.6 path-exists: 5.0.0 @@ -13679,42 +13445,34 @@ snapshots: '@netlify/node-cookies@0.1.0': {} - '@netlify/open-api@2.30.0': {} + '@netlify/open-api@2.34.0': {} - '@netlify/opentelemetry-utils@1.2.0(@opentelemetry/api@1.8.0)': + '@netlify/opentelemetry-utils@1.2.1(@opentelemetry/api@1.8.0)': dependencies: '@opentelemetry/api': 1.8.0 - '@netlify/plugins-list@6.78.0': {} + '@netlify/plugins-list@6.80.0': {} '@netlify/run-utils@5.1.1': dependencies: execa: 6.1.0 - '@netlify/serverless-functions-api@1.18.0(@opentelemetry/api@1.8.0)': + '@netlify/serverless-functions-api@1.22.0': dependencies: - '@mswjs/interceptors': 0.27.2 '@netlify/node-cookies': 0.1.0 - '@opentelemetry/core': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/otlp-transformer': 0.50.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.0 urlpattern-polyfill: 8.0.2 - transitivePeerDependencies: - - '@opentelemetry/api' - '@netlify/zip-it-and-ship-it@9.32.1(@opentelemetry/api@1.8.0)': + '@netlify/zip-it-and-ship-it@9.37.7': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.23.6 + '@babel/parser': 7.25.4 + '@babel/types': 7.24.8 '@netlify/binary-info': 1.0.0 - '@netlify/serverless-functions-api': 1.18.0(@opentelemetry/api@1.8.0) - '@vercel/nft': 0.23.1 - archiver: 6.0.2 + '@netlify/serverless-functions-api': 1.22.0 + '@vercel/nft': 0.27.3 + archiver: 7.0.1 common-path-prefix: 3.0.0 cp-file: 10.0.0 - es-module-lexer: 1.5.2 + es-module-lexer: 1.5.4 esbuild: 0.19.11 execa: 6.1.0 fast-glob: 3.3.2 @@ -13726,35 +13484,35 @@ snapshots: junk: 4.0.1 locate-path: 7.2.0 merge-options: 3.0.4 - minimatch: 9.0.4 + minimatch: 9.0.5 normalize-path: 3.0.0 p-map: 5.5.0 path-exists: 5.0.0 precinct: 11.0.5 require-package-name: 2.0.1 resolve: 2.0.0-next.5 - semver: 7.6.0 + semver: 7.6.3 tmp-promise: 3.0.3 toml: 3.0.0 unixify: 1.0.0 urlpattern-polyfill: 8.0.2 yargs: 17.7.2 + zod: 3.23.8 transitivePeerDependencies: - - '@opentelemetry/api' - encoding - supports-color - '@netlify/zip-it-and-ship-it@9.32.1(@opentelemetry/api@1.8.0)(supports-color@9.4.0)': + '@netlify/zip-it-and-ship-it@9.37.7(supports-color@9.4.0)': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.23.6 + '@babel/parser': 7.25.4 + '@babel/types': 7.24.8 '@netlify/binary-info': 1.0.0 - '@netlify/serverless-functions-api': 1.18.0(@opentelemetry/api@1.8.0) - '@vercel/nft': 0.23.1(supports-color@9.4.0) - archiver: 6.0.2 + '@netlify/serverless-functions-api': 1.22.0 + '@vercel/nft': 0.27.3(supports-color@9.4.0) + archiver: 7.0.1 common-path-prefix: 3.0.0 cp-file: 10.0.0 - es-module-lexer: 1.5.2 + es-module-lexer: 1.5.4 esbuild: 0.19.11 execa: 6.1.0 fast-glob: 3.3.2 @@ -13766,228 +13524,202 @@ snapshots: junk: 4.0.1 locate-path: 7.2.0 merge-options: 3.0.4 - minimatch: 9.0.4 + minimatch: 9.0.5 normalize-path: 3.0.0 p-map: 5.5.0 path-exists: 5.0.0 precinct: 11.0.5(supports-color@9.4.0) require-package-name: 2.0.1 resolve: 2.0.0-next.5 - semver: 7.6.0 + semver: 7.6.3 tmp-promise: 3.0.3 toml: 3.0.0 unixify: 1.0.0 urlpattern-polyfill: 8.0.2 yargs: 17.7.2 + zod: 3.23.8 transitivePeerDependencies: - - '@opentelemetry/api' - encoding - supports-color - '@nodelib/fs.scandir@2.1.5': + '@netlify/zip-it-and-ship-it@9.38.0(supports-color@9.4.0)': dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.2 + '@netlify/binary-info': 1.0.0 + '@netlify/serverless-functions-api': 1.22.0 + '@vercel/nft': 0.27.3(supports-color@9.4.0) + archiver: 7.0.1 + common-path-prefix: 3.0.0 + cp-file: 10.0.0 + es-module-lexer: 1.5.4 + esbuild: 0.19.11 + execa: 6.1.0 + fast-glob: 3.3.2 + filter-obj: 5.1.0 + find-up: 6.3.0 + glob: 8.1.0 + is-builtin-module: 3.2.1 + is-path-inside: 4.0.0 + junk: 4.0.1 + locate-path: 7.2.0 + merge-options: 3.0.4 + minimatch: 9.0.5 + normalize-path: 3.0.0 + p-map: 5.5.0 + path-exists: 5.0.0 + precinct: 11.0.5(supports-color@9.4.0) + require-package-name: 2.0.1 + resolve: 2.0.0-next.5 + semver: 7.6.3 + tmp-promise: 3.0.3 + toml: 3.0.0 + unixify: 1.0.0 + urlpattern-polyfill: 8.0.2 + yargs: 17.7.2 + zod: 3.23.8 + transitivePeerDependencies: + - encoding + - supports-color - '@nodelib/fs.scandir@3.0.0': + '@nodelib/fs.scandir@2.1.5': dependencies: - '@nodelib/fs.stat': 3.0.0 + '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 '@nodelib/fs.stat@2.0.5': {} - '@nodelib/fs.stat@3.0.0': {} - '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@nodelib/fs.walk@2.0.0': - dependencies: - '@nodelib/fs.scandir': 3.0.0 - fastq: 1.17.1 - - '@npmcli/config@8.3.1': + '@npmcli/config@8.3.4': dependencies: '@npmcli/map-workspaces': 3.0.6 + '@npmcli/package-json': 5.2.0 ci-info: 4.0.0 - ini: 4.1.2 - nopt: 7.2.0 + ini: 4.1.3 + nopt: 7.2.1 proc-log: 4.2.0 - read-package-json-fast: 3.0.2 - semver: 7.6.0 + semver: 7.6.3 walk-up-path: 3.0.1 + transitivePeerDependencies: + - bluebird + + '@npmcli/git@5.0.8': + dependencies: + '@npmcli/promise-spawn': 7.0.2 + ini: 4.1.3 + lru-cache: 10.4.3 + npm-pick-manifest: 9.1.0 + proc-log: 4.2.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.6.3 + which: 4.0.0 + transitivePeerDependencies: + - bluebird '@npmcli/map-workspaces@3.0.6': dependencies: '@npmcli/name-from-folder': 2.0.0 - glob: 10.3.12 - minimatch: 9.0.4 + glob: 10.4.5 + minimatch: 9.0.5 read-package-json-fast: 3.0.2 '@npmcli/name-from-folder@2.0.0': {} - '@octokit/auth-token@3.0.4': {} + '@npmcli/package-json@5.2.0': + dependencies: + '@npmcli/git': 5.0.8 + glob: 10.4.5 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + normalize-package-data: 6.0.2 + proc-log: 4.2.0 + semver: 7.6.3 + transitivePeerDependencies: + - bluebird + + '@npmcli/promise-spawn@7.0.2': + dependencies: + which: 4.0.0 + + '@octokit/auth-token@4.0.0': {} - '@octokit/core@4.2.4': + '@octokit/core@5.2.0': dependencies: - '@octokit/auth-token': 3.0.4 - '@octokit/graphql': 5.0.6 - '@octokit/request': 6.2.8 - '@octokit/request-error': 3.0.3 - '@octokit/types': 9.3.2 + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.0 + '@octokit/request': 8.4.0 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.5.0 before-after-hook: 2.2.3 universal-user-agent: 6.0.1 - transitivePeerDependencies: - - encoding - '@octokit/endpoint@7.0.6': + '@octokit/endpoint@9.0.5': dependencies: - '@octokit/types': 9.3.2 - is-plain-object: 5.0.0 + '@octokit/types': 13.5.0 universal-user-agent: 6.0.1 - '@octokit/graphql@5.0.6': + '@octokit/graphql@7.1.0': dependencies: - '@octokit/request': 6.2.8 - '@octokit/types': 9.3.2 + '@octokit/request': 8.4.0 + '@octokit/types': 13.5.0 universal-user-agent: 6.0.1 - transitivePeerDependencies: - - encoding - '@octokit/openapi-types@18.1.1': {} + '@octokit/openapi-types@22.2.0': {} - '@octokit/plugin-paginate-rest@6.1.2(@octokit/core@4.2.4)': + '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.2.0)': dependencies: - '@octokit/core': 4.2.4 - '@octokit/tsconfig': 1.0.2 - '@octokit/types': 9.3.2 + '@octokit/core': 5.2.0 + '@octokit/types': 13.5.0 - '@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.4)': + '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.0)': dependencies: - '@octokit/core': 4.2.4 + '@octokit/core': 5.2.0 - '@octokit/plugin-rest-endpoint-methods@7.2.3(@octokit/core@4.2.4)': + '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.2.0)': dependencies: - '@octokit/core': 4.2.4 - '@octokit/types': 10.0.0 + '@octokit/core': 5.2.0 + '@octokit/types': 13.5.0 - '@octokit/request-error@3.0.3': + '@octokit/request-error@5.1.0': dependencies: - '@octokit/types': 9.3.2 + '@octokit/types': 13.5.0 deprecation: 2.3.1 once: 1.4.0 - '@octokit/request@6.2.8': + '@octokit/request@8.4.0': dependencies: - '@octokit/endpoint': 7.0.6 - '@octokit/request-error': 3.0.3 - '@octokit/types': 9.3.2 - is-plain-object: 5.0.0 - node-fetch: 2.7.0 + '@octokit/endpoint': 9.0.5 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.5.0 universal-user-agent: 6.0.1 - transitivePeerDependencies: - - encoding - '@octokit/rest@19.0.13': + '@octokit/rest@20.1.1': dependencies: - '@octokit/core': 4.2.4 - '@octokit/plugin-paginate-rest': 6.1.2(@octokit/core@4.2.4) - '@octokit/plugin-request-log': 1.0.4(@octokit/core@4.2.4) - '@octokit/plugin-rest-endpoint-methods': 7.2.3(@octokit/core@4.2.4) - transitivePeerDependencies: - - encoding - - '@octokit/tsconfig@1.0.2': {} - - '@octokit/types@10.0.0': - dependencies: - '@octokit/openapi-types': 18.1.1 + '@octokit/core': 5.2.0 + '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.2.0) + '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.0) + '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.2.0) - '@octokit/types@9.3.2': + '@octokit/types@13.5.0': dependencies: - '@octokit/openapi-types': 18.1.1 + '@octokit/openapi-types': 22.2.0 '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': dependencies: is-node-process: 1.2.0 - outvariant: 1.4.2 + outvariant: 1.4.3 '@open-draft/until@2.1.0': {} - '@opentelemetry/api-logs@0.50.0': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api@1.8.0': {} - '@opentelemetry/core@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/core@1.24.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/semantic-conventions': 1.24.0 - - '@opentelemetry/otlp-transformer@0.50.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api-logs': 0.50.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-logs': 0.50.0(@opentelemetry/api-logs@0.50.0)(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-metrics': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.23.0(@opentelemetry/api@1.8.0) - - '@opentelemetry/resources@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/resources@1.24.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.0 - - '@opentelemetry/sdk-logs@0.50.0(@opentelemetry/api-logs@0.50.0)(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api-logs': 0.50.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - - '@opentelemetry/sdk-metrics@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - lodash.merge: 4.6.2 - - '@opentelemetry/sdk-trace-base@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/sdk-trace-base@1.24.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.0 - - '@opentelemetry/semantic-conventions@1.23.0': {} - - '@opentelemetry/semantic-conventions@1.24.0': {} - '@parcel/watcher-android-arm64@2.4.1': optional: true @@ -14018,7 +13750,7 @@ snapshots: '@parcel/watcher-wasm@2.4.1': dependencies: is-glob: 4.0.3 - micromatch: 4.0.5 + micromatch: 4.0.8 '@parcel/watcher-win32-arm64@2.4.1': optional: true @@ -14033,8 +13765,8 @@ snapshots: dependencies: detect-libc: 1.0.3 is-glob: 4.0.3 - micromatch: 4.0.5 - node-addon-api: 7.1.0 + micromatch: 4.0.8 + node-addon-api: 7.1.1 optionalDependencies: '@parcel/watcher-android-arm64': 2.4.1 '@parcel/watcher-darwin-arm64': 2.4.1 @@ -14054,213 +13786,212 @@ snapshots: '@pkgr/core@0.1.1': {} - '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.18.1)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@4.25.0)(webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)))': dependencies: - ansi-html-community: 0.0.8 - core-js-pure: 3.37.0 + ansi-html: 0.0.9 + core-js-pure: 3.38.1 error-stack-parser: 2.1.4 html-entities: 2.5.2 loader-utils: 2.0.4 react-refresh: 0.14.2 - schema-utils: 3.3.0 + schema-utils: 4.2.0 source-map: 0.7.4 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) optionalDependencies: - type-fest: 4.18.1 - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + type-fest: 4.25.0 + webpack-dev-server: 5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) - '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.18.1)(webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - ansi-html-community: 0.0.8 - core-js-pure: 3.37.0 + ansi-html: 0.0.9 + core-js-pure: 3.38.1 error-stack-parser: 2.1.4 html-entities: 2.5.2 loader-utils: 2.0.4 react-refresh: 0.14.2 - schema-utils: 3.3.0 + schema-utils: 4.2.0 source-map: 0.7.4 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: - type-fest: 4.18.1 - webpack-dev-server: 5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) '@pnpm/config.env-replace@1.1.0': {} - '@pnpm/constants@7.1.1': {} + '@pnpm/constants@8.0.0': {} - '@pnpm/error@5.0.3': + '@pnpm/error@6.0.1': dependencies: - '@pnpm/constants': 7.1.1 + '@pnpm/constants': 8.0.0 '@pnpm/network.ca-file@1.0.2': dependencies: graceful-fs: 4.2.10 - '@pnpm/npm-conf@2.2.2': + '@pnpm/npm-conf@2.3.1': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@pnpm/workspace.read-manifest@1.0.3': + '@pnpm/workspace.read-manifest@2.2.0': dependencies: - '@pnpm/constants': 7.1.1 - '@pnpm/error': 5.0.3 + '@pnpm/constants': 8.0.0 + '@pnpm/error': 6.0.1 read-yaml-file: 2.1.0 - '@react-aria/i18n@3.11.0(react@18.3.1)': + '@react-aria/i18n@3.12.2(react@18.3.1)': dependencies: - '@internationalized/date': 3.5.3 - '@internationalized/message': 3.1.3 - '@internationalized/number': 3.5.2 - '@internationalized/string': 3.2.2 - '@react-aria/ssr': 3.9.3(react@18.3.1) - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@internationalized/date': 3.5.5 + '@internationalized/message': 3.1.4 + '@internationalized/number': 3.5.3 + '@internationalized/string': 3.2.3 + '@react-aria/ssr': 3.9.5(react@18.3.1) + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-aria/interactions@3.21.2(react@18.3.1)': + '@react-aria/interactions@3.22.2(react@18.3.1)': dependencies: - '@react-aria/ssr': 3.9.3(react@18.3.1) - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/ssr': 3.9.5(react@18.3.1) + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-aria/landmark@3.0.0-beta.10(react@18.3.1)': + '@react-aria/landmark@3.0.0-beta.12(react@18.3.1)': dependencies: - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - '@react-aria/landmark@3.0.0-beta.11(react@18.3.1)': + '@react-aria/landmark@3.0.0-beta.15(react@18.3.1)': dependencies: - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - '@react-aria/ssr@3.9.3(react@18.3.1)': + '@react-aria/ssr@3.9.5(react@18.3.1)': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-aria/toast@3.0.0-beta.10(react@18.3.1)': + '@react-aria/toast@3.0.0-beta.12(react@18.3.1)': dependencies: - '@react-aria/i18n': 3.11.0(react@18.3.1) - '@react-aria/interactions': 3.21.2(react@18.3.1) - '@react-aria/landmark': 3.0.0-beta.10(react@18.3.1) - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-stately/toast': 3.0.0-beta.2(react@18.3.1) - '@react-types/button': 3.9.3(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/i18n': 3.12.2(react@18.3.1) + '@react-aria/interactions': 3.22.2(react@18.3.1) + '@react-aria/landmark': 3.0.0-beta.12(react@18.3.1) + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-stately/toast': 3.0.0-beta.4(react@18.3.1) + '@react-types/button': 3.9.6(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-aria/toast@3.0.0-beta.11(react@18.3.1)': + '@react-aria/toast@3.0.0-beta.15(react@18.3.1)': dependencies: - '@react-aria/i18n': 3.11.0(react@18.3.1) - '@react-aria/interactions': 3.21.2(react@18.3.1) - '@react-aria/landmark': 3.0.0-beta.11(react@18.3.1) - '@react-aria/utils': 3.24.0(react@18.3.1) - '@react-stately/toast': 3.0.0-beta.3(react@18.3.1) - '@react-types/button': 3.9.3(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/i18n': 3.12.2(react@18.3.1) + '@react-aria/interactions': 3.22.2(react@18.3.1) + '@react-aria/landmark': 3.0.0-beta.15(react@18.3.1) + '@react-aria/utils': 3.25.2(react@18.3.1) + '@react-stately/toast': 3.0.0-beta.5(react@18.3.1) + '@react-types/button': 3.9.6(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-aria/utils@3.24.0(react@18.3.1)': + '@react-aria/utils@3.25.2(react@18.3.1)': dependencies: - '@react-aria/ssr': 3.9.3(react@18.3.1) - '@react-stately/utils': 3.10.0(react@18.3.1) - '@react-types/shared': 3.23.0(react@18.3.1) - '@swc/helpers': 0.5.11 + '@react-aria/ssr': 3.9.5(react@18.3.1) + '@react-stately/utils': 3.10.3(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) + '@swc/helpers': 0.5.12 clsx: 2.1.1 react: 18.3.1 - '@react-stately/toast@3.0.0-beta.2(react@18.3.1)': + '@react-stately/toast@3.0.0-beta.4(react@18.3.1)': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - '@react-stately/toast@3.0.0-beta.3(react@18.3.1)': + '@react-stately/toast@3.0.0-beta.5(react@18.3.1)': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - '@react-stately/utils@3.10.0(react@18.3.1)': + '@react-stately/utils@3.10.3(react@18.3.1)': dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.12 react: 18.3.1 - '@react-types/button@3.9.3(react@18.3.1)': + '@react-types/button@3.9.6(react@18.3.1)': dependencies: - '@react-types/shared': 3.23.0(react@18.3.1) + '@react-types/shared': 3.24.1(react@18.3.1) react: 18.3.1 - '@react-types/shared@3.23.0(react@18.3.1)': + '@react-types/shared@3.24.1(react@18.3.1)': dependencies: react: 18.3.1 - '@remix-run/router@1.16.0': {} + '@remix-run/router@1.18.0': {} '@rollup/pluginutils@4.2.1': dependencies: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.21.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.21.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.21.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.21.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.21.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.21.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.21.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.21.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.21.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.21.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.21.0': optional: true '@sinclair/typebox@0.27.8': {} @@ -14287,7 +14018,7 @@ snapshots: '@snyk/github-codeowners@1.1.0': dependencies: commander: 4.1.1 - ignore: 5.3.1 + ignore: 5.3.2 p-map: 4.0.0 '@squide/core@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -14296,17 +14027,17 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@squide/firefly-webpack-configs@3.0.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0))(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': - dependencies: - '@squide/webpack-configs': 3.0.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0))(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - '@swc/helpers': 0.5.11 - '@workleap/swc-configs': 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) - '@workleap/webpack-configs': 1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - browserslist: 4.23.0 - postcss: 8.4.38 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + '@squide/firefly-webpack-configs@3.0.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2))(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': + dependencies: + '@squide/webpack-configs': 3.0.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2))(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 + '@workleap/swc-configs': 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) + '@workleap/webpack-configs': 1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + browserslist: 4.23.2 + postcss: 8.4.39 + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) transitivePeerDependencies: - '@rspack/core' - '@types/webpack' @@ -14323,17 +14054,17 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@squide/firefly@8.0.0(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12))': + '@squide/firefly@8.0.0(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@squide/module-federation': 5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - '@squide/msw': 2.0.14(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@squide/react-router': 5.0.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) - msw: 2.2.14(typescript@5.4.5) + '@squide/module-federation': 5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@squide/msw': 2.0.14(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@squide/react-router': 5.0.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + msw: 2.3.1(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-error-boundary: 4.0.13(react@18.3.1) - react-router-dom: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router-dom: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - bufferutil - debug @@ -14343,17 +14074,12 @@ snapshots: - vue-tsc - webpack - '@squide/firefly@8.0.0(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react-error-boundary@4.0.13(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@squide/module-federation@5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: + '@module-federation/enhanced': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@squide/module-federation': 5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@squide/msw': 2.0.14(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@squide/react-router': 5.0.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) - msw: 2.2.14(typescript@5.4.5) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-error-boundary: 4.0.13(react@18.3.1) - react-router-dom: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - bufferutil - debug @@ -14363,65 +14089,35 @@ snapshots: - vue-tsc - webpack - '@squide/module-federation@5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12))': - dependencies: - '@module-federation/enhanced': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - typescript - - utf-8-validate - - vue-tsc - - webpack - - '@squide/module-federation@5.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': - dependencies: - '@module-federation/enhanced': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - typescript - - utf-8-validate - - vue-tsc - - webpack - - '@squide/msw@2.0.14(msw@2.2.14(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@squide/msw@2.0.14(msw@2.3.1(typescript@5.5.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - msw: 2.2.14(typescript@5.4.5) + msw: 2.3.1(typescript@5.5.3) - '@squide/react-router@5.0.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@squide/react-router@5.0.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: '@squide/core': 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router-dom: 6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router-dom: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@squide/webpack-configs@3.0.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0))(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@squide/webpack-configs@3.0.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2))(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - '@module-federation/enhanced': 0.1.11(typescript@5.4.5)(vue-tsc@1.8.27(typescript@5.4.5))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - '@swc/helpers': 0.5.11 - '@workleap/swc-configs': 2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0) - '@workleap/webpack-configs': 1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - browserslist: 4.23.0 + '@module-federation/enhanced': 0.1.11(typescript@5.5.3)(vue-tsc@1.8.27(typescript@5.5.3))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 + '@workleap/swc-configs': 2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2) + '@workleap/webpack-configs': 1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + browserslist: 4.23.2 deepmerge: 4.3.1 - html-webpack-plugin: 5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - postcss: 8.4.38 + html-webpack-plugin: 5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + postcss: 8.4.39 semver: 7.6.0 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) transitivePeerDependencies: - '@rspack/core' - '@types/webpack' @@ -14442,56 +14138,56 @@ snapshots: dependencies: lodash: 4.17.21 - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.24.5)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 - '@svgr/babel-preset@8.1.0(@babel/core@7.24.5)': + '@svgr/babel-preset@8.1.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.24.5) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.5) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.25.2) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.25.2) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.25.2) - '@svgr/core@8.1.0(typescript@5.4.5)': + '@svgr/core@8.1.0(typescript@5.5.3)': dependencies: - '@babel/core': 7.24.5 - '@svgr/babel-preset': 8.1.0(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@svgr/babel-preset': 8.1.0(@babel/core@7.25.2) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.4.5) + cosmiconfig: 8.3.6(typescript@5.5.3) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -14499,103 +14195,103 @@ snapshots: '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))': dependencies: - '@babel/core': 7.24.5 - '@svgr/babel-preset': 8.1.0(@babel/core@7.24.5) - '@svgr/core': 8.1.0(typescript@5.4.5) + '@babel/core': 7.25.2 + '@svgr/babel-preset': 8.1.0(@babel/core@7.25.2) + '@svgr/core': 8.1.0(typescript@5.5.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5)': + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3)': dependencies: - '@svgr/core': 8.1.0(typescript@5.4.5) - cosmiconfig: 8.3.6(typescript@5.4.5) + '@svgr/core': 8.1.0(typescript@5.5.3) + cosmiconfig: 8.3.6(typescript@5.5.3) deepmerge: 4.3.1 - svgo: 3.2.0 + svgo: 3.3.2 transitivePeerDependencies: - typescript - '@svgr/webpack@8.1.0(typescript@5.4.5)': + '@svgr/webpack@8.1.0(typescript@5.5.3)': dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-transform-react-constant-elements': 7.24.1(@babel/core@7.24.5) - '@babel/preset-env': 7.24.5(@babel/core@7.24.5) - '@babel/preset-react': 7.24.1(@babel/core@7.24.5) - '@babel/preset-typescript': 7.24.1(@babel/core@7.24.5) - '@svgr/core': 8.1.0(typescript@5.4.5) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5)) - '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5) + '@babel/core': 7.25.2 + '@babel/plugin-transform-react-constant-elements': 7.25.1(@babel/core@7.25.2) + '@babel/preset-env': 7.25.4(@babel/core@7.25.2) + '@babel/preset-react': 7.24.7(@babel/core@7.25.2) + '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) + '@svgr/core': 8.1.0(typescript@5.5.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3) transitivePeerDependencies: - supports-color - typescript - '@swc/core-darwin-arm64@1.4.17': + '@swc/core-darwin-arm64@1.7.0': optional: true - '@swc/core-darwin-x64@1.4.17': + '@swc/core-darwin-x64@1.7.0': optional: true - '@swc/core-linux-arm-gnueabihf@1.4.17': + '@swc/core-linux-arm-gnueabihf@1.7.0': optional: true - '@swc/core-linux-arm64-gnu@1.4.17': + '@swc/core-linux-arm64-gnu@1.7.0': optional: true - '@swc/core-linux-arm64-musl@1.4.17': + '@swc/core-linux-arm64-musl@1.7.0': optional: true - '@swc/core-linux-x64-gnu@1.4.17': + '@swc/core-linux-x64-gnu@1.7.0': optional: true - '@swc/core-linux-x64-musl@1.4.17': + '@swc/core-linux-x64-musl@1.7.0': optional: true - '@swc/core-win32-arm64-msvc@1.4.17': + '@swc/core-win32-arm64-msvc@1.7.0': optional: true - '@swc/core-win32-ia32-msvc@1.4.17': + '@swc/core-win32-ia32-msvc@1.7.0': optional: true - '@swc/core-win32-x64-msvc@1.4.17': + '@swc/core-win32-x64-msvc@1.7.0': optional: true - '@swc/core@1.4.17(@swc/helpers@0.5.11)': + '@swc/core@1.7.0(@swc/helpers@0.5.12)': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.6 + '@swc/types': 0.1.12 optionalDependencies: - '@swc/core-darwin-arm64': 1.4.17 - '@swc/core-darwin-x64': 1.4.17 - '@swc/core-linux-arm-gnueabihf': 1.4.17 - '@swc/core-linux-arm64-gnu': 1.4.17 - '@swc/core-linux-arm64-musl': 1.4.17 - '@swc/core-linux-x64-gnu': 1.4.17 - '@swc/core-linux-x64-musl': 1.4.17 - '@swc/core-win32-arm64-msvc': 1.4.17 - '@swc/core-win32-ia32-msvc': 1.4.17 - '@swc/core-win32-x64-msvc': 1.4.17 - '@swc/helpers': 0.5.11 + '@swc/core-darwin-arm64': 1.7.0 + '@swc/core-darwin-x64': 1.7.0 + '@swc/core-linux-arm-gnueabihf': 1.7.0 + '@swc/core-linux-arm64-gnu': 1.7.0 + '@swc/core-linux-arm64-musl': 1.7.0 + '@swc/core-linux-x64-gnu': 1.7.0 + '@swc/core-linux-x64-musl': 1.7.0 + '@swc/core-win32-arm64-msvc': 1.7.0 + '@swc/core-win32-ia32-msvc': 1.7.0 + '@swc/core-win32-x64-msvc': 1.7.0 + '@swc/helpers': 0.5.12 '@swc/counter@0.1.3': {} - '@swc/helpers@0.5.11': + '@swc/helpers@0.5.12': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 - '@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11))': + '@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12))': dependencies: '@jest/create-cache-key-function': 29.7.0 - '@swc/core': 1.4.17(@swc/helpers@0.5.11) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) '@swc/counter': 0.1.3 - jsonc-parser: 3.2.1 + jsonc-parser: 3.3.1 - '@swc/types@0.1.6': + '@swc/types@0.1.12': dependencies: '@swc/counter': 0.1.3 @@ -14603,25 +14299,25 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tanstack/query-core@5.32.0': {} + '@tanstack/query-core@5.51.9': {} - '@tanstack/query-devtools@5.28.10': {} + '@tanstack/query-devtools@5.51.9': {} - '@tanstack/react-query-devtools@5.32.0(@tanstack/react-query@5.32.0(react@18.3.1))(react@18.3.1)': + '@tanstack/react-query-devtools@5.51.9(@tanstack/react-query@5.51.9(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/query-devtools': 5.28.10 - '@tanstack/react-query': 5.32.0(react@18.3.1) + '@tanstack/query-devtools': 5.51.9 + '@tanstack/react-query': 5.51.9(react@18.3.1) react: 18.3.1 - '@tanstack/react-query@5.32.0(react@18.3.1)': + '@tanstack/react-query@5.51.9(react@18.3.1)': dependencies: - '@tanstack/query-core': 5.32.0 + '@tanstack/query-core': 5.51.9 react: 18.3.1 - '@testing-library/dom@10.1.0': + '@testing-library/dom@10.4.0': dependencies: - '@babel/code-frame': 7.24.2 - '@babel/runtime': 7.24.5 + '@babel/code-frame': 7.24.7 + '@babel/runtime': 7.25.4 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -14629,10 +14325,10 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))': + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))': dependencies: - '@adobe/css-tools': 4.3.3 - '@babel/runtime': 7.24.5 + '@adobe/css-tools': 4.4.0 + '@babel/runtime': 7.25.4 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 @@ -14642,15 +14338,17 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) - '@testing-library/react@15.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react@16.0.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@testing-library/dom': 10.1.0 - '@types/react-dom': 18.3.0 + '@babel/runtime': 7.25.4 + '@testing-library/dom': 10.4.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.3.0 '@tokenizer/token@0.3.0': {} @@ -14674,46 +14372,46 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 + '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 - '@types/babel__traverse@7.20.5': + '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.4 '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/bonjour@3.5.13': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/concat-stream@2.0.3': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/connect-history-api-fallback@1.5.4': dependencies: - '@types/express-serve-static-core': 4.19.0 - '@types/node': 20.12.7 + '@types/express-serve-static-core': 4.19.5 + '@types/node': 20.14.11 '@types/connect@3.4.38': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/cookie@0.6.0': {} @@ -14723,10 +14421,10 @@ snapshots: '@types/eslint-scope@3.7.7': dependencies: - '@types/eslint': 8.56.10 + '@types/eslint': 9.6.0 '@types/estree': 1.0.5 - '@types/eslint@8.56.10': + '@types/eslint@9.6.0': dependencies: '@types/estree': 1.0.5 '@types/json-schema': 7.0.15 @@ -14737,9 +14435,9 @@ snapshots: '@types/estree@1.0.5': {} - '@types/express-serve-static-core@4.19.0': + '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -14747,22 +14445,22 @@ snapshots: '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 + '@types/express-serve-static-core': 4.19.5 '@types/qs': 6.9.15 '@types/serve-static': 1.15.7 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/hast@3.0.4': dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 '@types/html-minifier-terser@6.1.0': {} @@ -14770,9 +14468,9 @@ snapshots: '@types/http-errors@2.0.4': {} - '@types/http-proxy@1.17.14': + '@types/http-proxy@1.17.15': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/is-empty@1.2.3': {} @@ -14793,7 +14491,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -14803,34 +14501,36 @@ snapshots: '@types/mdast@3.0.15': dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 - '@types/mdast@4.0.3': + '@types/mdast@4.0.4': dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 '@types/mime@1.3.5': {} '@types/minimatch@5.1.2': {} - '@types/minimist@1.2.5': {} - '@types/ms@0.7.34': {} '@types/mute-stream@0.0.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/node@12.20.55': {} - '@types/node@20.12.7': + '@types/node@20.14.11': dependencies: undici-types: 5.26.5 + '@types/node@22.5.0': + dependencies: + undici-types: 6.19.8 + '@types/normalize-package-data@2.4.4': {} '@types/prop-types@15.7.12': {} @@ -14841,13 +14541,13 @@ snapshots: '@types/react-dom@18.3.0': dependencies: - '@types/react': 18.3.1 + '@types/react': 18.3.3 '@types/react-test-renderer@18.3.0': dependencies: - '@types/react': 18.3.1 + '@types/react': 18.3.3 - '@types/react@18.3.1': + '@types/react@18.3.3': dependencies: '@types/prop-types': 15.7.12 csstype: 3.1.3 @@ -14861,7 +14561,7 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/serve-index@1.9.4': dependencies: @@ -14870,12 +14570,12 @@ snapshots: '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/send': 0.17.4 '@types/sockjs@0.3.36': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/stack-utils@2.0.3': {} @@ -14887,15 +14587,15 @@ snapshots: '@types/triple-beam@1.3.5': {} - '@types/unist@2.0.10': {} + '@types/unist@2.0.11': {} - '@types/unist@3.0.2': {} + '@types/unist@3.0.3': {} '@types/wrap-ansi@3.0.0': {} - '@types/ws@8.5.10': + '@types/ws@8.5.12': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/yargs-parser@21.0.3': {} @@ -14903,45 +14603,43 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@types/yargs@17.0.32': + '@types/yargs@17.0.33': dependencies: '@types/yargs-parser': 21.0.3 '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 optional: true - '@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@5.5.0) + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.16.1(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.18.0 eslint: 8.57.0 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 5.3.2 natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@5.5.0) + '@typescript-eslint/scope-manager': 7.16.1 + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.16.1 + debug: 4.3.6(supports-color@5.5.0) eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -14950,95 +14648,114 @@ snapshots: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - '@typescript-eslint/scope-manager@7.8.0': + '@typescript-eslint/scope-manager@7.16.1': + dependencies: + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/visitor-keys': 7.16.1 + + '@typescript-eslint/scope-manager@7.18.0': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@5.5.0) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.3) + debug: 4.3.6(supports-color@5.5.0) eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color '@typescript-eslint/types@5.62.0': {} - '@typescript-eslint/types@7.8.0': {} + '@typescript-eslint/types@7.16.1': {} + + '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/typescript-estree@5.62.0(supports-color@9.4.0)(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@5.62.0(supports-color@9.4.0)(typescript@5.5.3)': dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.6(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.4.5) + semver: 7.6.3 + tsutils: 3.21.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.3)': dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.4.5) + semver: 7.6.3 + tsutils: 3.21.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.16.1(typescript@5.5.3)': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4(supports-color@5.5.0) + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/visitor-keys': 7.16.1 + debug: 4.3.6(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.3)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6(supports-color@5.5.0) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.3) eslint: 8.57.0 eslint-scope: 5.1.1 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.3) eslint: 8.57.0 - semver: 7.6.0 transitivePeerDependencies: - supports-color - typescript @@ -15048,77 +14765,48 @@ snapshots: '@typescript-eslint/types': 5.62.0 eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@7.8.0': + '@typescript-eslint/visitor-keys@7.16.1': dependencies: - '@typescript-eslint/types': 7.8.0 + '@typescript-eslint/types': 7.16.1 eslint-visitor-keys: 3.4.3 - '@ungap/structured-clone@1.2.0': {} - - '@vercel/nft@0.23.1': + '@typescript-eslint/visitor-keys@7.18.0': dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - '@rollup/pluginutils': 4.2.1 - acorn: 8.11.3 - async-sema: 3.1.1 - bindings: 1.5.0 - estree-walker: 2.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - node-gyp-build: 4.8.1 - resolve-from: 5.0.0 - transitivePeerDependencies: - - encoding - - supports-color + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 - '@vercel/nft@0.23.1(supports-color@9.4.0)': - dependencies: - '@mapbox/node-pre-gyp': 1.0.11(supports-color@9.4.0) - '@rollup/pluginutils': 4.2.1 - acorn: 8.11.3 - async-sema: 3.1.1 - bindings: 1.5.0 - estree-walker: 2.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - node-gyp-build: 4.8.1 - resolve-from: 5.0.0 - transitivePeerDependencies: - - encoding - - supports-color + '@ungap/structured-clone@1.2.0': {} - '@vercel/nft@0.26.4': + '@vercel/nft@0.27.3': dependencies: '@mapbox/node-pre-gyp': 1.0.11 '@rollup/pluginutils': 4.2.1 - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) async-sema: 3.1.1 bindings: 1.5.0 estree-walker: 2.0.2 glob: 7.2.3 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.8 node-gyp-build: 4.8.1 resolve-from: 5.0.0 transitivePeerDependencies: - encoding - supports-color - '@vercel/nft@0.26.4(supports-color@9.4.0)': + '@vercel/nft@0.27.3(supports-color@9.4.0)': dependencies: '@mapbox/node-pre-gyp': 1.0.11(supports-color@9.4.0) '@rollup/pluginutils': 4.2.1 - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) async-sema: 3.1.1 bindings: 1.5.0 estree-walker: 2.0.2 glob: 7.2.3 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.8 node-gyp-build: 4.8.1 resolve-from: 5.0.0 transitivePeerDependencies: @@ -15140,42 +14828,42 @@ snapshots: '@voxpelli/semver-set@5.0.2': dependencies: - semver: 7.6.0 + semver: 7.6.3 '@voxpelli/type-helpers@3.4.0': {} - '@voxpelli/typed-utils@1.10.1': + '@voxpelli/typed-utils@1.10.2': dependencies: '@voxpelli/type-helpers': 3.4.0 - '@vue/compiler-core@3.4.26': + '@vue/compiler-core@3.4.38': dependencies: - '@babel/parser': 7.24.5 - '@vue/shared': 3.4.26 + '@babel/parser': 7.25.4 + '@vue/shared': 3.4.38 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-dom@3.4.26': + '@vue/compiler-dom@3.4.38': dependencies: - '@vue/compiler-core': 3.4.26 - '@vue/shared': 3.4.26 + '@vue/compiler-core': 3.4.38 + '@vue/shared': 3.4.38 - '@vue/language-core@1.8.27(typescript@5.4.5)': + '@vue/language-core@1.8.27(typescript@5.5.3)': dependencies: '@volar/language-core': 1.11.1 '@volar/source-map': 1.11.1 - '@vue/compiler-dom': 3.4.26 - '@vue/shared': 3.4.26 + '@vue/compiler-dom': 3.4.38 + '@vue/shared': 3.4.38 computeds: 0.0.1 - minimatch: 9.0.4 + minimatch: 9.0.5 muggle-string: 0.3.1 path-browserify: 1.0.1 vue-template-compiler: 2.7.16 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 - '@vue/shared@3.4.26': {} + '@vue/shared@3.4.38': {} '@webassemblyjs/ast@1.12.1': dependencies: @@ -15253,86 +14941,121 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) optionalDependencies: - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) '@workleap/browserslist-config@2.0.1': {} - '@workleap/eslint-plugin@3.2.2(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5)': + '@workleap/eslint-plugin@3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3)': + dependencies: + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) + eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) + eslint-plugin-mdx: 3.1.5(eslint@8.57.0) + eslint-plugin-package-json: 0.10.4(eslint@8.57.0)(jsonc-eslint-parser@2.4.0) + eslint-plugin-react: 7.35.0(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + eslint-plugin-storybook: 0.8.0(eslint@8.57.0)(typescript@5.5.3) + eslint-plugin-testing-library: 6.3.0(eslint@8.57.0)(typescript@5.5.3) + eslint-plugin-yml: 1.14.0(eslint@8.57.0) + jsonc-eslint-parser: 2.4.0 + yaml-eslint-parser: 1.2.3 + optionalDependencies: + '@typescript-eslint/parser': 7.16.1(eslint@8.57.0)(typescript@5.5.3) + eslint: 8.57.0 + typescript: 5.5.3 + transitivePeerDependencies: + - bluebird + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - jest + - supports-color + + '@workleap/eslint-plugin@3.2.2(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3)': dependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3) + eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-mdx: 3.1.5(eslint@8.57.0) eslint-plugin-package-json: 0.10.4(eslint@8.57.0)(jsonc-eslint-parser@2.4.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) + eslint-plugin-react: 7.35.0(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) - eslint-plugin-storybook: 0.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@5.4.5) + eslint-plugin-storybook: 0.8.0(eslint@8.57.0)(typescript@5.5.3) + eslint-plugin-testing-library: 6.3.0(eslint@8.57.0)(typescript@5.5.3) eslint-plugin-yml: 1.14.0(eslint@8.57.0) jsonc-eslint-parser: 2.4.0 - yaml-eslint-parser: 1.2.2 + yaml-eslint-parser: 1.2.3 optionalDependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.16.1(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: + - bluebird - eslint-import-resolver-typescript - eslint-import-resolver-webpack - jest - supports-color - '@workleap/swc-configs@2.2.3(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@swc/jest@0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)))(browserslist@4.23.0)': + '@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.2)': dependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - '@swc/helpers': 0.5.11 + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 optionalDependencies: - '@swc/jest': 0.2.36(@swc/core@1.4.17(@swc/helpers@0.5.11)) - browserslist: 4.23.0 + '@swc/jest': 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) + browserslist: 4.23.2 - '@workleap/tsup-configs@3.0.6(tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5))(typescript@5.4.5)': + '@workleap/swc-configs@2.2.3(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@swc/jest@0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)))(browserslist@4.23.3)': dependencies: - tsup: 8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5) - typescript: 5.4.5 + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 + optionalDependencies: + '@swc/jest': 0.2.36(@swc/core@1.7.0(@swc/helpers@0.5.12)) + browserslist: 4.23.3 - '@workleap/typescript-configs@3.0.2(typescript@5.4.5)': + '@workleap/tsup-configs@3.0.6(tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0))(typescript@5.5.3)': dependencies: - typescript: 5.4.5 + tsup: 8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0) + typescript: 5.5.3 - '@workleap/webpack-configs@1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(esbuild@0.19.12)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12))': + '@workleap/typescript-configs@3.0.2(typescript@5.5.3)': dependencies: - '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.18.1)(webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - '@svgr/webpack': 8.1.0(typescript@5.4.5) - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - '@swc/helpers': 0.5.11 - browserslist: 4.23.0 - css-loader: 6.11.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - html-webpack-plugin: 5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - mini-css-extract-plugin: 2.9.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - postcss: 8.4.38 - postcss-loader: 8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + typescript: 5.5.3 + + '@workleap/webpack-configs@1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(type-fest@4.25.0)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)))': + dependencies: + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@4.25.0)(webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + '@svgr/webpack': 8.1.0(typescript@5.5.3) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 + browserslist: 4.23.2 + css-loader: 6.11.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + html-webpack-plugin: 5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + mini-css-extract-plugin: 2.9.1(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + postcss: 8.4.39 + postcss-loader: 8.1.1(postcss@8.4.39)(typescript@5.5.3)(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) react-refresh: 0.14.2 - style-loader: 3.3.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - swc-loader: 0.2.6(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - terser-webpack-plugin: 5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + style-loader: 3.3.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + swc-loader: 0.2.6(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) optionalDependencies: - webpack-dev-server: 5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) + webpack-dev-server: 5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) transitivePeerDependencies: - '@rspack/core' - '@types/webpack' @@ -15345,25 +15068,25 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@workleap/webpack-configs@1.5.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(browserslist@4.23.0)(postcss@8.4.38)(type-fest@4.18.1)(typescript@5.4.5)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4))': - dependencies: - '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.18.1)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@svgr/webpack': 8.1.0(typescript@5.4.5) - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - '@swc/helpers': 0.5.11 - browserslist: 4.23.0 - css-loader: 6.11.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - html-webpack-plugin: 5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - mini-css-extract-plugin: 2.9.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - postcss: 8.4.38 - postcss-loader: 8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + '@workleap/webpack-configs@1.5.1(@swc/core@1.7.0(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(browserslist@4.23.2)(postcss@8.4.39)(typescript@5.5.3)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': + dependencies: + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@svgr/webpack': 8.1.0(typescript@5.5.3) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + '@swc/helpers': 0.5.12 + browserslist: 4.23.2 + css-loader: 6.11.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + html-webpack-plugin: 5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + mini-css-extract-plugin: 2.9.1(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + postcss: 8.4.39 + postcss-loader: 8.1.1(postcss@8.4.39)(typescript@5.5.3)(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) react-refresh: 0.14.2 - style-loader: 3.3.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - swc-loader: 0.2.6(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - terser-webpack-plugin: 5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + style-loader: 3.3.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + swc-loader: 0.2.6(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) transitivePeerDependencies: - '@rspack/core' - '@types/webpack' @@ -15452,42 +15175,40 @@ snapshots: acorn-globals@7.0.1: dependencies: - acorn: 8.11.3 - acorn-walk: 8.3.2 + acorn: 8.12.1 + acorn-walk: 8.3.3 - acorn-import-assertions@1.9.0(acorn@8.11.3): + acorn-import-attributes@1.9.5(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn-import-attributes@1.9.5(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-walk@8.3.3: dependencies: - acorn: 8.11.3 - - acorn-walk@8.3.2: {} + acorn: 8.12.1 - acorn@8.11.3: {} + acorn@8.12.1: {} - adm-zip@0.5.12: {} + adm-zip@0.5.15: {} agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color agent-base@6.0.2(supports-color@9.4.0): dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.6(supports-color@9.4.0) transitivePeerDependencies: - supports-color agent-base@7.1.1: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -15501,25 +15222,25 @@ snapshots: clean-stack: 4.2.0 indent-string: 5.0.0 - ajv-errors@3.0.0(ajv@8.13.0): + ajv-errors@3.0.0(ajv@8.17.1): dependencies: - ajv: 8.13.0 + ajv: 8.17.1 - ajv-formats@2.1.1(ajv@8.13.0): + ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: - ajv: 8.13.0 + ajv: 8.17.1 - ajv-formats@3.0.1(ajv@8.13.0): + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: - ajv: 8.13.0 + ajv: 8.17.1 ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 - ajv-keywords@5.1.0(ajv@8.13.0): + ajv-keywords@5.1.0(ajv@8.17.1): dependencies: - ajv: 8.13.0 + ajv: 8.17.1 fast-deep-equal: 3.1.3 ajv@6.12.6: @@ -15529,12 +15250,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.13.0: + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.0.1 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 all-node-versions@11.3.0: dependencies: @@ -15544,7 +15265,7 @@ snapshots: global-cache-dir: 4.4.0 is-plain-obj: 4.1.0 path-exists: 5.0.0 - semver: 7.6.0 + semver: 7.6.3 write-file-atomic: 4.0.2 ansi-align@3.0.1: @@ -15565,8 +15286,14 @@ snapshots: ansi-escapes@6.2.1: {} + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + ansi-html-community@0.0.8: {} + ansi-html@0.0.9: {} + ansi-regex@3.0.1: {} ansi-regex@4.1.1: {} @@ -15600,26 +15327,25 @@ snapshots: aproba@2.0.0: {} - archiver-utils@4.0.1: + archiver-utils@5.0.2: dependencies: - glob: 8.1.0 + glob: 10.4.5 graceful-fs: 4.2.11 + is-stream: 2.0.1 lazystream: 1.0.1 lodash: 4.17.21 normalize-path: 3.0.0 - readable-stream: 3.6.2 + readable-stream: 4.5.2 - archiver@6.0.2: + archiver@7.0.1: dependencies: - archiver-utils: 4.0.1 - async: 3.2.5 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 + archiver-utils: 5.0.2 + async: 3.2.6 + buffer-crc32: 1.0.0 + readable-stream: 4.5.2 readdir-glob: 1.1.3 tar-stream: 3.1.7 - zip-stream: 5.0.2 - - archy@1.0.0: {} + zip-stream: 6.0.1 are-we-there-yet@2.0.0: dependencies: @@ -15634,18 +15360,14 @@ snapshots: argparse@2.0.1: {} + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + aria-query@5.3.0: dependencies: dequal: 2.0.3 - arity-n@1.0.4: {} - - arr-diff@4.0.0: {} - - arr-flatten@1.1.0: {} - - arr-union@3.1.0: {} - array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 @@ -15662,16 +15384,10 @@ snapshots: get-intrinsic: 1.2.4 is-string: 1.0.7 - array-last@1.3.0: - dependencies: - is-number: 4.0.0 - array-timsort@1.0.3: {} array-union@2.1.0: {} - array-unique@0.3.2: {} - array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.7 @@ -15704,14 +15420,7 @@ snapshots: es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 - array.prototype.toreversed@1.1.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - array.prototype.tosorted@1.1.3: + array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -15730,14 +15439,10 @@ snapshots: is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 - arrify@1.0.1: {} - arrify@3.0.0: {} ascii-table@0.0.9: {} - assign-symbols@1.0.0: {} - ast-module-types@5.0.0: {} ast-types-flow@0.0.8: {} @@ -15750,52 +15455,46 @@ snapshots: dependencies: lodash: 4.17.21 - async@3.2.5: {} + async@3.2.6: {} asynckit@0.4.0: {} at-least-node@1.0.0: {} - atob@2.1.2: {} - atomic-sleep@1.0.0: {} available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - avvio@8.3.0: + avvio@8.4.0: dependencies: '@fastify/error': 3.4.1 - archy: 1.0.0 - debug: 4.3.4(supports-color@5.5.0) fastq: 1.17.1 - transitivePeerDependencies: - - supports-color - axe-core@4.7.0: {} + axe-core@4.10.0: {} - axios@1.6.8: + axios@1.7.5: dependencies: - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.5) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - axobject-query@3.2.1: + axobject-query@3.1.1: dependencies: - dequal: 2.0.3 + deep-equal: 2.2.3 b4a@1.6.6: {} - babel-jest@29.7.0(@babel/core@7.24.5): + babel-jest@29.7.0(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.5) + babel-preset-jest: 29.6.3(@babel/core@7.25.2) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -15804,7 +15503,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-plugin-utils': 7.24.8 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -15814,58 +15513,59 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 + '@babel/template': 7.25.0 + '@babel/types': 7.25.4 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.5 + '@types/babel__traverse': 7.20.6 - babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.5): + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.25.2): dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) + '@babel/compat-data': 7.25.4 + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.5): + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) - core-js-compat: 3.37.0 + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) + core-js-compat: 3.38.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.24.5): + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.5 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.5) + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5): - dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) - - babel-preset-jest@29.6.3(@babel/core@7.24.5): - dependencies: - '@babel/core': 7.24.5 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) + + babel-preset-jest@29.6.3(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) - - babylon@6.18.0: {} + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) backoff@2.5.0: dependencies: @@ -15875,41 +15575,31 @@ snapshots: balanced-match@1.0.2: {} - bare-events@2.2.2: + bare-events@2.4.2: optional: true - bare-fs@2.3.0: + bare-fs@2.3.1: dependencies: - bare-events: 2.2.2 - bare-path: 2.1.2 - bare-stream: 1.0.0 + bare-events: 2.4.2 + bare-path: 2.1.3 + bare-stream: 2.1.3 optional: true - bare-os@2.3.0: + bare-os@2.4.0: optional: true - bare-path@2.1.2: + bare-path@2.1.3: dependencies: - bare-os: 2.3.0 + bare-os: 2.4.0 optional: true - bare-stream@1.0.0: + bare-stream@2.1.3: dependencies: - streamx: 2.16.1 + streamx: 2.19.0 optional: true base64-js@1.5.1: {} - base@0.11.2: - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.1 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 - basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 @@ -15918,11 +15608,11 @@ snapshots: before-after-hook@2.2.3: {} - better-ajv-errors@1.2.0(ajv@8.13.0): + better-ajv-errors@1.2.0(ajv@8.17.1): dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 '@humanwhocodes/momoa': 2.0.4 - ajv: 8.13.0 + ajv: 8.17.1 chalk: 4.1.2 jsonpointer: 5.0.1 leven: 3.1.0 @@ -15949,12 +15639,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - bl@5.1.0: - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - blueimp-md5@2.19.0: {} body-parser@1.20.2: @@ -16001,35 +15685,23 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@2.3.2: - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 - breakword@1.0.6: + browserslist@4.23.2: dependencies: - wcwidth: 1.0.1 + caniuse-lite: 1.0.30001651 + electron-to-chromium: 1.5.13 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.2) - browserslist@4.23.0: + browserslist@4.23.3: dependencies: - caniuse-lite: 1.0.30001615 - electron-to-chromium: 1.4.756 - node-releases: 2.0.14 - update-browserslist-db: 1.0.14(browserslist@4.23.0) + caniuse-lite: 1.0.30001651 + electron-to-chromium: 1.5.13 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.3) bs-logger@0.2.6: dependencies: @@ -16039,8 +15711,12 @@ snapshots: dependencies: node-int64: 0.4.0 + btoa@1.2.1: {} + buffer-crc32@0.2.13: {} + buffer-crc32@1.0.0: {} + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} @@ -16055,21 +15731,21 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - buffered-async-iterable@0.3.0: {} + buffered-async-iterable@1.0.1: {} builtin-modules@3.3.0: {} builtins@5.1.0: dependencies: - semver: 7.6.0 + semver: 7.6.3 bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 - bundle-require@4.1.0(esbuild@0.19.12): + bundle-require@5.0.0(esbuild@0.23.1): dependencies: - esbuild: 0.19.12 + esbuild: 0.23.1 load-tsconfig: 0.2.5 byline@5.0.0: {} @@ -16080,18 +15756,6 @@ snapshots: cac@6.7.14: {} - cache-base@1.0.1: - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.1 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - cache-content-type@1.0.1: dependencies: mime-types: 2.1.35 @@ -16126,13 +15790,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.6.2 - - camelcase-keys@6.2.2: - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 + tslib: 2.6.3 camelcase@5.3.1: {} @@ -16140,7 +15798,7 @@ snapshots: camelcase@7.0.1: {} - caniuse-lite@1.0.30001615: {} + caniuse-lite@1.0.30001651: {} ccount@2.0.1: {} @@ -16160,8 +15818,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.2.0: {} - chalk@5.3.0: {} char-regex@1.0.2: {} @@ -16182,22 +15838,10 @@ snapshots: chardet@0.7.0: {} - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -16210,9 +15854,7 @@ snapshots: chownr@2.0.0: {} - chrome-trace-event@1.0.3: {} - - ci-info@3.8.0: {} + chrome-trace-event@1.0.4: {} ci-info@3.9.0: {} @@ -16224,13 +15866,6 @@ snapshots: cjs-module-lexer@1.3.1: {} - class-utils@0.3.6: - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 - clean-css@5.3.3: dependencies: source-map: 0.6.1 @@ -16263,10 +15898,10 @@ snapshots: cli-spinners@2.9.2: {} - cli-truncate@3.1.0: + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 - string-width: 5.1.2 + string-width: 7.2.0 cli-width@2.2.1: {} @@ -16278,12 +15913,6 @@ snapshots: is-wsl: 3.1.0 is64bit: 2.0.0 - cliui@6.0.0: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - cliui@7.0.4: dependencies: string-width: 4.2.3 @@ -16302,7 +15931,8 @@ snapshots: kind-of: 6.0.3 shallow-clone: 3.0.1 - clone@1.0.4: {} + clone@1.0.4: + optional: true clsx@2.1.1: {} @@ -16310,11 +15940,6 @@ snapshots: collect-v8-coverage@1.0.2: {} - collection-visit@1.0.0: - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -16391,22 +16016,17 @@ snapshots: common-path-prefix@3.0.0: {} - component-emitter@1.3.1: {} - - compose-function@3.0.3: - dependencies: - arity-n: 1.0.4 - - compress-commons@5.0.3: + compress-commons@6.0.2: dependencies: crc-32: 1.2.2 - crc32-stream: 5.0.1 + crc32-stream: 6.0.0 + is-stream: 2.0.1 normalize-path: 3.0.0 - readable-stream: 3.6.2 + readable-stream: 4.5.2 compressible@2.0.18: dependencies: - mime-db: 1.52.0 + mime-db: 1.53.0 compression@1.7.4: dependencies: @@ -16439,7 +16059,7 @@ snapshots: js-string-escape: 1.0.1 lodash: 4.17.21 md5-hex: 3.0.1 - semver: 7.6.0 + semver: 7.6.3 well-known-symbols: 2.0.0 confbox@0.1.7: {} @@ -16471,7 +16091,7 @@ snapshots: convert-source-map@2.0.0: {} - cookie-es@1.1.0: {} + cookie-es@1.2.2: {} cookie-signature@1.0.6: {} @@ -16484,22 +16104,6 @@ snapshots: depd: 2.0.0 keygrip: 1.1.0 - copy-descriptor@0.1.1: {} - - copy-template-dir@1.4.0: - dependencies: - end-of-stream: 1.4.4 - graceful-fs: 4.2.11 - maxstache: 1.0.7 - maxstache-stream: 1.0.4 - mkdirp: 0.5.6 - noop2: 2.0.0 - pump: 1.0.3 - readdirp: 2.2.1 - run-parallel: 1.2.0 - transitivePeerDependencies: - - supports-color - copyfiles@2.4.1: dependencies: glob: 7.2.3 @@ -16510,33 +16114,33 @@ snapshots: untildify: 4.0.0 yargs: 16.2.0 - core-js-compat@3.37.0: + core-js-compat@3.38.1: dependencies: - browserslist: 4.23.0 + browserslist: 4.23.3 - core-js-pure@3.37.0: {} + core-js-pure@3.38.1: {} core-util-is@1.0.3: {} corser@2.0.1: {} - cosmiconfig@8.3.6(typescript@5.4.5): + cosmiconfig@8.3.6(typescript@5.5.3): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 - cosmiconfig@9.0.0(typescript@5.4.5): + cosmiconfig@9.0.0(typescript@5.5.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 cp-file@10.0.0: dependencies: @@ -16557,25 +16161,25 @@ snapshots: cp-file: 9.1.0 globby: 13.2.2 junk: 4.0.1 - micromatch: 4.0.5 + micromatch: 4.0.8 nested-error-stacks: 2.1.1 p-filter: 3.0.0 p-map: 5.5.0 crc-32@1.2.2: {} - crc32-stream@5.0.1: + crc32-stream@6.0.0: dependencies: crc-32: 1.2.2 - readable-stream: 3.6.2 + readable-stream: 4.5.2 - create-jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -16584,15 +16188,27 @@ snapshots: - supports-color - ts-node - create-require@1.1.1: {} - - cron-parser@4.8.1: + create-jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): dependencies: - luxon: 3.4.4 + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + + create-require@1.1.1: {} cron-parser@4.9.0: dependencies: - luxon: 3.4.4 + luxon: 3.5.0 cross-env@7.0.3: dependencies: @@ -16616,31 +16232,31 @@ snapshots: dependencies: type-fest: 1.4.0 - css-loader@6.11.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + css-loader@6.11.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.39) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.39) + postcss-modules-scope: 3.2.0(postcss@8.4.39) + postcss-modules-values: 4.0.0(postcss@8.4.39) postcss-value-parser: 4.2.0 - semver: 7.6.0 + semver: 7.6.3 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - css-loader@6.11.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + css-loader@6.11.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.39) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.39) + postcss-modules-scope: 3.2.0(postcss@8.4.39) + postcss-modules-values: 4.0.0(postcss@8.4.39) postcss-value-parser: 4.2.0 - semver: 7.6.0 + semver: 7.6.3 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) css-select@4.3.0: dependencies: @@ -16690,19 +16306,6 @@ snapshots: csstype@3.1.3: {} - csv-generate@3.4.3: {} - - csv-parse@4.16.3: {} - - csv-stringify@5.6.5: {} - - csv@5.5.3: - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - cyclist@1.0.2: {} damerau-levenshtein@1.0.8: {} @@ -16755,13 +16358,17 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.4(supports-color@5.5.0): + debug@4.3.5: + dependencies: + ms: 2.1.2 + + debug@4.3.6(supports-color@5.5.0): dependencies: ms: 2.1.2 optionalDependencies: supports-color: 5.5.0 - debug@4.3.4(supports-color@9.4.0): + debug@4.3.6(supports-color@9.4.0): dependencies: ms: 2.1.2 optionalDependencies: @@ -16771,21 +16378,12 @@ snapshots: dependencies: callsite: 1.0.0 - decamelize-keys@1.1.1: - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - - decamelize@1.2.0: {} - decimal.js@10.4.3: {} decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 - decode-uri-component@0.2.2: {} - decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -16794,10 +16392,29 @@ snapshots: deep-equal@1.0.1: {} + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.4 + is-arguments: 1.1.1 + is-array-buffer: 3.0.4 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + side-channel: 1.0.6 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + deep-extend@0.6.0: {} - deep-freeze@0.0.1: {} - deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -16816,6 +16433,7 @@ snapshots: defaults@1.0.4: dependencies: clone: 1.0.4 + optional: true defer-to-connect@2.0.1: {} @@ -16835,19 +16453,6 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - define-property@0.2.5: - dependencies: - is-descriptor: 0.1.7 - - define-property@1.0.0: - dependencies: - is-descriptor: 1.0.3 - - define-property@2.0.2: - dependencies: - is-descriptor: 1.0.3 - isobject: 3.0.1 - defu@6.1.4: {} delayed-stream@1.0.0: {} @@ -16895,8 +16500,8 @@ snapshots: detective-postcss@6.1.3: dependencies: is-url: 1.2.4 - postcss: 8.4.38 - postcss-values-parser: 6.0.2(postcss@8.4.38) + postcss: 8.4.39 + postcss-values-parser: 6.0.2(postcss@8.4.39) detective-sass@5.0.3: dependencies: @@ -16912,19 +16517,19 @@ snapshots: detective-typescript@11.2.0: dependencies: - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.3) ast-module-types: 5.0.0 node-source-walk: 6.0.2 - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color detective-typescript@11.2.0(supports-color@9.4.0): dependencies: - '@typescript-eslint/typescript-estree': 5.62.0(supports-color@9.4.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 5.62.0(supports-color@9.4.0)(typescript@5.5.3) ast-module-types: 5.0.0 node-source-walk: 6.0.2 - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -17003,7 +16608,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.6.3 dot-prop@6.0.1: dependencies: @@ -17013,7 +16618,9 @@ snapshots: dependencies: type-fest: 2.19.0 - dotenv@16.0.3: {} + dot-prop@9.0.0: + dependencies: + type-fest: 4.25.0 dotenv@16.4.5: {} @@ -17033,7 +16640,11 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.4.756: {} + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.13: {} emittery@0.13.1: {} @@ -17053,7 +16664,7 @@ snapshots: dependencies: once: 1.4.0 - enhanced-resolve@5.16.0: + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 @@ -17073,7 +16684,9 @@ snapshots: envinfo@7.13.0: {} - envinfo@7.8.1: {} + environment@1.1.0: {} + + err-code@2.0.3: {} error-ex@1.3.2: dependencies: @@ -17118,7 +16731,7 @@ snapshots: is-string: 1.0.7 is-typed-array: 1.1.13 is-weakref: 1.0.2 - object-inspect: 1.13.1 + object-inspect: 1.13.2 object-keys: 1.1.1 object.assign: 4.1.5 regexp.prototype.flags: 1.5.2 @@ -17140,6 +16753,18 @@ snapshots: es-errors@1.3.0: {} + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + es-iterator-helpers@1.0.19: dependencies: call-bind: 1.0.7 @@ -17157,7 +16782,7 @@ snapshots: iterator.prototype: 1.1.2 safe-array-concat: 1.1.2 - es-module-lexer@1.5.2: {} + es-module-lexer@1.5.4: {} es-object-atoms@1.0.0: dependencies: @@ -17207,57 +16832,58 @@ snapshots: '@esbuild/win32-ia32': 0.19.11 '@esbuild/win32-x64': 0.19.11 - esbuild@0.19.12: + esbuild@0.21.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - - esbuild@0.20.2: + '@esbuild/aix-ppc64': 0.21.2 + '@esbuild/android-arm': 0.21.2 + '@esbuild/android-arm64': 0.21.2 + '@esbuild/android-x64': 0.21.2 + '@esbuild/darwin-arm64': 0.21.2 + '@esbuild/darwin-x64': 0.21.2 + '@esbuild/freebsd-arm64': 0.21.2 + '@esbuild/freebsd-x64': 0.21.2 + '@esbuild/linux-arm': 0.21.2 + '@esbuild/linux-arm64': 0.21.2 + '@esbuild/linux-ia32': 0.21.2 + '@esbuild/linux-loong64': 0.21.2 + '@esbuild/linux-mips64el': 0.21.2 + '@esbuild/linux-ppc64': 0.21.2 + '@esbuild/linux-riscv64': 0.21.2 + '@esbuild/linux-s390x': 0.21.2 + '@esbuild/linux-x64': 0.21.2 + '@esbuild/netbsd-x64': 0.21.2 + '@esbuild/openbsd-x64': 0.21.2 + '@esbuild/sunos-x64': 0.21.2 + '@esbuild/win32-arm64': 0.21.2 + '@esbuild/win32-ia32': 0.21.2 + '@esbuild/win32-x64': 0.21.2 + + esbuild@0.23.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 escalade@3.1.2: {} @@ -17281,50 +16907,51 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-compat-utils@0.5.0(eslint@8.57.0): + eslint-compat-utils@0.5.1(eslint@8.57.0): dependencies: eslint: 8.57.0 - semver: 7.6.0 + semver: 7.6.3 eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 - is-core-module: 2.13.1 + is-core-module: 2.15.1 resolve: 1.22.8 transitivePeerDependencies: - supports-color eslint-mdx@3.1.5(eslint@8.57.0): dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint: 8.57.0 espree: 9.6.1 estree-util-visit: 2.0.0 remark-mdx: 3.0.1 remark-parse: 11.0.0 remark-stringify: 11.0.0 - synckit: 0.9.0 - tslib: 2.6.2 - unified: 11.0.4 + synckit: 0.9.1 + tslib: 2.6.3 + unified: 11.0.5 unified-engine: 11.2.1 unist-util-visit: 5.0.0 uvu: 0.5.6 - vfile: 6.0.1 + vfile: 6.0.2 transitivePeerDependencies: + - bluebird - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.16.1(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -17334,9 +16961,9 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) hasown: 2.0.2 - is-core-module: 2.13.1 + is-core-module: 2.15.1 is-glob: 4.0.3 minimatch: 3.1.2 object.fromentries: 2.0.8 @@ -17345,32 +16972,42 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.16.1(eslint@8.57.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3): dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + jest: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3): dependencies: - '@babel/runtime': 7.24.5 - aria-query: 5.3.0 + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3) + eslint: 8.57.0 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + jest: 29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-jsx-a11y@6.9.0(eslint@8.57.0): + dependencies: + aria-query: 5.1.3 array-includes: 3.1.8 array.prototype.flatmap: 1.3.2 ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 + axe-core: 4.10.0 + axobject-query: 3.1.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 es-iterator-helpers: 1.0.19 @@ -17379,8 +17016,9 @@ snapshots: jsx-ast-utils: 3.3.5 language-tags: 1.0.9 minimatch: 3.1.2 - object.entries: 1.1.8 object.fromentries: 2.0.8 + safe-regex-test: 1.0.3 + string.prototype.includes: 2.0.0 eslint-plugin-markdown@3.0.1(eslint@8.57.0): dependencies: @@ -17397,51 +17035,52 @@ snapshots: remark-mdx: 3.0.1 remark-parse: 11.0.0 remark-stringify: 11.0.0 - tslib: 2.6.2 - unified: 11.0.4 - vfile: 6.0.1 + tslib: 2.6.3 + unified: 11.0.5 + vfile: 6.0.2 transitivePeerDependencies: + - bluebird - supports-color eslint-plugin-package-json@0.10.4(eslint@8.57.0)(jsonc-eslint-parser@2.4.0): dependencies: eslint: 8.57.0 jsonc-eslint-parser: 2.4.0 - package-json-validator: 0.6.4 - semver: 7.6.0 + package-json-validator: 0.6.5 + semver: 7.6.3 sort-package-json: 1.57.0 - validate-npm-package-name: 5.0.0 + validate-npm-package-name: 5.0.1 eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): dependencies: eslint: 8.57.0 - eslint-plugin-react@7.34.1(eslint@8.57.0): + eslint-plugin-react@7.35.0(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.2 - array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.3 + array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.0.19 eslint: 8.57.0 estraverse: 5.3.0 + hasown: 2.0.2 jsx-ast-utils: 3.3.5 minimatch: 3.1.2 object.entries: 1.1.8 object.fromentries: 2.0.8 - object.hasown: 1.1.4 object.values: 1.2.0 prop-types: 15.8.1 resolve: 2.0.0-next.5 semver: 6.3.1 string.prototype.matchall: 4.0.11 + string.prototype.repeat: 1.0.0 - eslint-plugin-storybook@0.8.0(eslint@8.57.0)(typescript@5.4.5): + eslint-plugin-storybook@0.8.0(eslint@8.57.0)(typescript@5.5.3): dependencies: '@storybook/csf': 0.0.1 - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 requireindex: 1.2.0 ts-dedent: 2.2.0 @@ -17449,9 +17088,9 @@ snapshots: - supports-color - typescript - eslint-plugin-testing-library@6.2.2(eslint@8.57.0)(typescript@5.4.5): + eslint-plugin-testing-library@6.3.0(eslint@8.57.0)(typescript@5.5.3): dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 transitivePeerDependencies: - supports-color @@ -17459,12 +17098,12 @@ snapshots: eslint-plugin-yml@1.14.0(eslint@8.57.0): dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) eslint: 8.57.0 - eslint-compat-utils: 0.5.0(eslint@8.57.0) + eslint-compat-utils: 0.5.1(eslint@8.57.0) lodash: 4.17.21 natural-compare: 1.4.0 - yaml-eslint-parser: 1.2.2 + yaml-eslint-parser: 1.2.3 transitivePeerDependencies: - supports-color @@ -17483,7 +17122,7 @@ snapshots: eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 + '@eslint-community/regexpp': 4.11.0 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.0 '@humanwhocodes/config-array': 0.11.14 @@ -17493,13 +17132,13 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - esquery: 1.5.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 @@ -17507,7 +17146,7 @@ snapshots: glob-parent: 6.0.2 globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -17525,13 +17164,13 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -17548,7 +17187,7 @@ snapshots: estree-util-visit@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 estree-walker@2.0.2: {} @@ -17602,18 +17241,6 @@ snapshots: exit@0.1.2: {} - expand-brackets@2.1.4: - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - expand-template@2.0.3: {} expand-tilde@2.0.2: @@ -17670,22 +17297,13 @@ snapshots: ext-list@2.2.2: dependencies: - mime-db: 1.52.0 + mime-db: 1.53.0 ext-name@5.0.0: dependencies: ext-list: 2.2.2 sort-keys-length: 1.0.1 - extend-shallow@2.0.1: - dependencies: - is-extendable: 0.1.1 - - extend-shallow@3.0.2: - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - extend@3.0.2: {} extendable-error@0.1.7: {} @@ -17696,22 +17314,9 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 - extglob@2.0.4: - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - extract-zip@2.0.1: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -17737,19 +17342,19 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} - fast-json-stringify@5.15.0: + fast-json-stringify@5.16.1: dependencies: '@fastify/merge-json-schemas': 0.1.1 - ajv: 8.13.0 - ajv-formats: 3.0.1(ajv@8.13.0) + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) fast-deep-equal: 3.1.3 - fast-uri: 2.3.0 + fast-uri: 2.4.0 json-schema-ref-resolver: 1.0.1 - rfdc: 1.3.1 + rfdc: 1.4.1 fast-levenshtein@2.0.6: {} @@ -17761,32 +17366,32 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@2.3.0: {} + fast-uri@2.4.0: {} + + fast-uri@3.0.1: {} fastest-levenshtein@1.0.16: {} fastify-plugin@4.5.1: {} - fastify@4.17.0: + fastify@4.28.1: dependencies: - '@fastify/ajv-compiler': 3.5.0 + '@fastify/ajv-compiler': 3.6.0 '@fastify/error': 3.4.1 '@fastify/fast-json-stringify-compiler': 4.3.0 abstract-logging: 2.0.1 - avvio: 8.3.0 + avvio: 8.4.0 fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.15.0 - find-my-way: 7.7.0 + fast-json-stringify: 5.16.1 + find-my-way: 8.2.0 light-my-request: 5.13.0 - pino: 8.21.0 - process-warning: 2.3.2 + pino: 9.3.2 + process-warning: 3.0.0 proxy-addr: 2.0.7 - rfdc: 1.3.1 + rfdc: 1.4.1 secure-json-parse: 2.7.0 - semver: 7.6.0 - tiny-lru: 11.2.6 - transitivePeerDependencies: - - supports-color + semver: 7.6.3 + toad-cache: 3.7.0 fastq@1.17.1: dependencies: @@ -17804,7 +17409,7 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.1.1(picomatch@4.0.2): + fdir@6.2.0(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -17845,18 +17450,18 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - file-type@18.7.0: dependencies: readable-web-to-node-stream: 3.0.2 - strtok3: 7.0.0 + strtok3: 7.1.1 token-types: 5.0.1 file-uri-to-path@1.0.0: {} + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + filename-reserved-regex@3.0.0: {} filenamify@5.1.1: @@ -17865,21 +17470,10 @@ snapshots: strip-outer: 2.0.0 trim-repeated: 2.0.0 - fill-range@4.0.0: - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - filter-iterator@0.0.1: {} - - filter-obj@1.1.0: {} - filter-obj@3.0.0: {} filter-obj@5.1.0: {} @@ -17900,11 +17494,11 @@ snapshots: dependencies: resolve-dir: 1.0.1 - find-my-way@7.7.0: + find-my-way@8.2.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 - safe-regex2: 2.0.0 + safe-regex2: 3.1.0 find-pkg@2.0.0: dependencies: @@ -17927,9 +17521,15 @@ snapshots: locate-path: 7.2.0 path-exists: 5.0.0 + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + find-yarn-workspace-root2@1.2.16: dependencies: - micromatch: 4.0.5 + micromatch: 4.0.8 pkg-dir: 4.2.0 flat-cache@3.2.0: @@ -17938,11 +17538,6 @@ snapshots: keyv: 4.5.4 rimraf: 3.0.2 - flat-cache@4.0.1: - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - flat@5.0.2: {} flatted@3.3.1: {} @@ -17958,17 +17553,15 @@ snapshots: dependencies: from2: 2.3.0 - follow-redirects@1.15.6(debug@4.3.4): + follow-redirects@1.15.6(debug@4.3.5): optionalDependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 for-each@0.3.3: dependencies: is-callable: 1.2.7 - for-in@1.0.2: {} - - foreground-child@3.1.1: + foreground-child@3.3.0: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 @@ -17987,10 +17580,6 @@ snapshots: forwarded@0.2.0: {} - fragment-cache@0.2.1: - dependencies: - map-cache: 0.2.2 - fresh@0.5.2: {} from2-array@0.0.4: @@ -18066,6 +17655,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.2.0: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -18098,13 +17689,11 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-value@2.0.6: {} - gh-release-fetch@4.0.3: dependencies: '@xhmikosr/downloader': 13.0.1 node-fetch: 3.3.2 - semver: 7.6.0 + semver: 7.6.3 git-hooks-list@1.0.3: {} @@ -18126,13 +17715,14 @@ snapshots: glob-to-regexp@0.4.1: {} - glob@10.3.12: + glob@10.4.5: dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 glob@7.2.3: dependencies: @@ -18192,7 +17782,7 @@ snapshots: dir-glob: 3.0.1 fast-glob: 3.3.2 glob: 7.2.3 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -18201,7 +17791,7 @@ snapshots: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -18209,7 +17799,7 @@ snapshots: dependencies: dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 4.0.0 @@ -18239,31 +17829,27 @@ snapshots: graceful-fs@4.2.11: {} - grapheme-splitter@1.0.4: {} - graphemer@1.4.0: {} - graphql@16.8.1: {} + graphql@16.9.0: {} - h3@1.11.1: + h3@1.12.0: dependencies: - cookie-es: 1.1.0 + cookie-es: 1.2.2 crossws: 0.2.4 defu: 6.1.4 destr: 2.0.3 - iron-webcrypto: 1.1.1 + iron-webcrypto: 1.2.1 ohash: 1.1.3 radix3: 1.1.2 - ufo: 1.5.3 + ufo: 1.5.4 uncrypto: 0.1.3 - unenv: 1.9.0 + unenv: 1.10.0 transitivePeerDependencies: - uWebSockets.js handle-thing@2.0.1: {} - hard-rejection@2.1.0: {} - has-bigints@1.0.2: {} has-flag@3.0.0: {} @@ -18272,8 +17858,6 @@ snapshots: has-own-prop@2.0.0: {} - has-own-property@0.1.0: {} - has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 @@ -18288,27 +17872,6 @@ snapshots: has-unicode@2.0.1: {} - has-value@0.3.1: - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - - has-value@1.0.0: - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - - has-values@0.1.4: {} - - has-values@1.0.0: - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - - has-yarn@3.0.0: {} - hasbin@1.2.3: dependencies: async: 1.5.2 @@ -18330,15 +17893,13 @@ snapshots: dependencies: parse-passwd: 1.0.0 - hosted-git-info@2.8.9: {} - hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 - hosted-git-info@7.0.1: + hosted-git-info@7.0.2: dependencies: - lru-cache: 10.2.2 + lru-cache: 10.4.3 hot-shots@10.0.0: optionalDependencies: @@ -18367,13 +17928,13 @@ snapshots: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.31.0 + terser: 5.31.6 html-parse-stringify@3.0.1: dependencies: void-elements: 3.1.0 - html-webpack-plugin@5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + html-webpack-plugin@5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -18381,9 +17942,9 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - html-webpack-plugin@5.6.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + html-webpack-plugin@5.6.0(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -18391,7 +17952,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) htmlparser2@6.1.0: dependencies: @@ -18438,26 +17999,26 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color - http-proxy-middleware@2.0.6(@types/express@4.17.21)(debug@4.3.4): + http-proxy-middleware@2.0.6(@types/express@4.17.21)(debug@4.3.5): dependencies: - '@types/http-proxy': 1.17.14 - http-proxy: 1.18.1(debug@4.3.4) + '@types/http-proxy': 1.17.15 + http-proxy: 1.18.1(debug@4.3.5) is-glob: 4.0.3 is-plain-obj: 3.0.0 - micromatch: 4.0.5 + micromatch: 4.0.8 optionalDependencies: '@types/express': 4.17.21 transitivePeerDependencies: - debug - http-proxy@1.18.1(debug@4.3.4): + http-proxy@1.18.1(debug@4.3.5): dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.5) requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -18469,7 +18030,7 @@ snapshots: corser: 2.0.1 he: 1.2.0 html-encoding-sniffer: 3.0.0 - http-proxy: 1.18.1(debug@4.3.4) + http-proxy: 1.18.1(debug@4.3.5) mime: 1.6.0 minimist: 1.2.8 opener: 1.5.2 @@ -18491,21 +18052,21 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color https-proxy-agent@5.0.1(supports-color@9.4.0): dependencies: agent-base: 6.0.2(supports-color@9.4.0) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.6(supports-color@9.4.0) transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.4: + https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -18519,13 +18080,13 @@ snapshots: hyperdyperid@1.2.0: {} - i18next-browser-languagedetector@7.2.1: + i18next-browser-languagedetector@8.0.0: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 - i18next@23.11.3: + i18next@23.12.1: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 iconv-lite@0.4.24: dependencies: @@ -18535,19 +18096,17 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.38): + icss-utils@5.1.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 - - identity-function@1.0.0: {} + postcss: 8.4.39 ieee754@1.2.1: {} ignore-by-default@1.0.1: {} - ignore@5.3.1: {} + ignore@5.3.2: {} - image-meta@0.2.0: {} + image-meta@0.2.1: {} import-fresh@3.3.0: dependencies: @@ -18556,7 +18115,7 @@ snapshots: import-lazy@4.0.0: {} - import-local@3.1.0: + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 @@ -18584,7 +18143,7 @@ snapshots: ini@2.0.0: {} - ini@4.1.2: {} + ini@4.1.3: {} inquirer-autocomplete-prompt@1.4.0(inquirer@6.5.2): dependencies: @@ -18618,11 +18177,11 @@ snapshots: installed-check-core@8.3.0: dependencies: '@voxpelli/semver-set': 5.0.2 - '@voxpelli/typed-utils': 1.10.1 + '@voxpelli/typed-utils': 1.10.2 is-glob: 4.0.3 - list-installed: 5.3.0 + list-installed: 5.3.1 picomatch: 4.0.2 - semver: 7.6.0 + semver: 7.6.3 installed-check@9.3.0: dependencies: @@ -18640,18 +18199,18 @@ snapshots: interpret@3.1.1: {} - intl-messageformat@10.5.11: + intl-messageformat@10.5.14: dependencies: - '@formatjs/ecma402-abstract': 1.18.2 + '@formatjs/ecma402-abstract': 2.0.0 '@formatjs/fast-memoize': 2.2.0 - '@formatjs/icu-messageformat-parser': 2.7.6 - tslib: 2.6.2 + '@formatjs/icu-messageformat-parser': 2.7.8 + tslib: 2.6.3 ipaddr.js@1.9.1: {} ipaddr.js@2.2.0: {} - ipx@2.1.0(@netlify/blobs@7.3.0): + ipx@2.1.0(@netlify/blobs@7.4.0): dependencies: '@fastify/accept-negotiator': 1.1.0 citty: 0.1.6 @@ -18659,15 +18218,15 @@ snapshots: defu: 6.1.4 destr: 2.0.3 etag: 1.8.1 - h3: 1.11.1 - image-meta: 0.2.0 + h3: 1.12.0 + image-meta: 0.2.1 listhen: 1.7.2 ofetch: 1.3.4 pathe: 1.1.2 sharp: 0.32.6 - svgo: 3.2.0 - ufo: 1.5.3 - unstorage: 1.10.2(@netlify/blobs@7.3.0) + svgo: 3.3.2 + ufo: 1.5.4 + unstorage: 1.10.2(@netlify/blobs@7.4.0) xss: 1.0.15 transitivePeerDependencies: - '@azure/app-configuration' @@ -18685,11 +18244,7 @@ snapshots: - ioredis - uWebSockets.js - iron-webcrypto@1.1.1: {} - - is-accessor-descriptor@1.0.1: - dependencies: - hasown: 2.0.2 + iron-webcrypto@1.2.1: {} is-alphabetical@1.0.4: {} @@ -18705,6 +18260,11 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 @@ -18731,23 +18291,13 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 - is-buffer@1.1.6: {} - is-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 is-callable@1.2.7: {} - is-ci@3.0.1: - dependencies: - ci-info: 3.9.0 - - is-core-module@2.13.1: - dependencies: - hasown: 2.0.2 - - is-data-descriptor@1.0.1: + is-core-module@2.15.1: dependencies: hasown: 2.0.2 @@ -18763,28 +18313,12 @@ snapshots: is-decimal@2.0.1: {} - is-descriptor@0.1.7: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - - is-descriptor@1.0.3: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - is-docker@2.2.1: {} is-docker@3.0.0: {} is-empty@1.2.0: {} - is-extendable@0.1.1: {} - - is-extendable@1.0.1: - dependencies: - is-plain-object: 2.0.4 - is-extglob@2.1.1: {} is-finalizationregistry@1.0.2: @@ -18797,6 +18331,10 @@ snapshots: is-fullwidth-code-point@4.0.0: {} + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + is-generator-fn@2.1.0: {} is-generator-function@1.0.10: @@ -18811,6 +18349,8 @@ snapshots: is-hexadecimal@2.0.1: {} + is-in-ci@0.1.0: {} + is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 @@ -18822,8 +18362,6 @@ snapshots: is-interactive@2.0.0: {} - is-iterable@1.1.1: {} - is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -18838,12 +18376,6 @@ snapshots: dependencies: has-tostringtag: 1.0.2 - is-number@3.0.0: - dependencies: - kind-of: 3.2.2 - - is-number@4.0.0: {} - is-number@7.0.0: {} is-obj@2.0.0: {} @@ -18864,8 +18396,6 @@ snapshots: dependencies: isobject: 3.0.1 - is-plain-object@5.0.0: {} - is-potential-custom-element-name@1.0.1: {} is-regex@1.1.4: @@ -18883,6 +18413,8 @@ snapshots: is-stream@3.0.0: {} + is-stream@4.0.1: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 @@ -18903,6 +18435,8 @@ snapshots: is-unicode-supported@1.3.0: {} + is-unicode-supported@2.0.0: {} + is-url-superb@4.0.0: {} is-url@1.2.4: {} @@ -18928,8 +18462,6 @@ snapshots: dependencies: is-inside-container: 1.0.0 - is-yarn-global@0.4.1: {} - is64bit@2.0.0: dependencies: system-architecture: 0.1.0 @@ -18944,12 +18476,14 @@ snapshots: isexe@2.0.0: {} - isobject@2.1.0: - dependencies: - isarray: 1.0.0 + isexe@3.1.1: {} isobject@3.0.1: {} + isomorphic-ws@5.0.0(ws@8.17.1): + dependencies: + ws: 8.17.1 + isomorphic-ws@5.0.0(ws@8.5.0): dependencies: ws: 8.5.0 @@ -18958,21 +18492,21 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 + '@babel/core': 7.25.2 + '@babel/parser': 7.25.4 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 transitivePeerDependencies: - supports-color - istanbul-lib-instrument@6.0.2: + istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 + '@babel/core': 7.25.2 + '@babel/parser': 7.25.4 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color @@ -18984,7 +18518,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -18995,8 +18529,6 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - iterable-lookahead@1.0.0: {} - iterator.prototype@1.1.2: dependencies: define-properties: 1.2.1 @@ -19005,12 +18537,19 @@ snapshots: reflect.getprototypeof: 1.0.6 set-function-name: 2.0.2 - jackspeak@2.3.6: + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + jest-changed-files@29.7.0: dependencies: execa: 5.1.1 @@ -19023,7 +18562,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -19043,16 +18582,35 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-cli@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -19061,13 +18619,45 @@ snapshots: - babel-plugin-macros - supports-color - ts-node + optional: true + + jest-config@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): + dependencies: + '@babel/core': 7.25.2 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.14.11 + ts-node: 10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color - jest-config@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.5) + babel-jest: 29.7.0(@babel/core@7.25.2) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -19081,17 +18671,18 @@ snapshots: jest-runner: 29.7.0 jest-util: 29.7.0 jest-validate: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 parse-json: 5.2.0 pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.12.7 - ts-node: 10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + '@types/node': 22.5.0 + ts-node: 10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3) transitivePeerDependencies: - babel-plugin-macros - supports-color + optional: true jest-diff@29.7.0: dependencies: @@ -19118,7 +18709,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -19132,7 +18723,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -19144,14 +18735,14 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.12.7 + '@types/node': 20.14.11 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 jest-regex-util: 29.6.3 jest-util: 29.7.0 jest-worker: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -19170,12 +18761,12 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.8 pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -19183,7 +18774,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -19218,7 +18809,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -19246,7 +18837,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -19266,15 +18857,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.24.5 - '@babel/generator': 7.24.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - '@babel/types': 7.24.5 + '@babel/core': 7.25.2 + '@babel/generator': 7.25.5 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) + '@babel/types': 7.25.4 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -19285,14 +18876,14 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -19320,7 +18911,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -19329,30 +18920,43 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest@29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.5.0)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node + optional: true - jiti@1.21.0: {} + jiti@1.21.6: {} joycon@3.1.1: {} @@ -19372,7 +18976,7 @@ snapshots: jsdom@20.0.3: dependencies: abab: 2.0.6 - acorn: 8.11.3 + acorn: 8.12.1 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 @@ -19385,7 +18989,7 @@ snapshots: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.9 + nwsapi: 2.2.12 parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -19395,7 +18999,7 @@ snapshots: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.17.0 + ws: 8.18.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -19410,7 +19014,7 @@ snapshots: json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@3.0.1: {} + json-parse-even-better-errors@3.0.2: {} json-schema-ref-resolver@1.0.1: dependencies: @@ -19430,12 +19034,12 @@ snapshots: jsonc-eslint-parser@2.4.0: dependencies: - acorn: 8.11.3 + acorn: 8.12.1 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - semver: 7.6.0 + semver: 7.6.3 - jsonc-parser@3.2.1: {} + jsonc-parser@3.3.1: {} jsonfile@4.0.0: optionalDependencies: @@ -19460,7 +19064,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.6.0 + semver: 7.6.3 jsx-ast-utils@3.3.5: dependencies: @@ -19482,7 +19086,7 @@ snapshots: jwa: 1.4.1 safe-buffer: 5.2.1 - jwt-decode@3.1.2: {} + jwt-decode@4.0.0: {} keep-func-props@4.0.1: dependencies: @@ -19496,42 +19100,32 @@ snapshots: dependencies: json-buffer: 3.0.1 - kind-of@3.2.2: - dependencies: - is-buffer: 1.1.6 - - kind-of@4.0.0: - dependencies: - is-buffer: 1.1.6 - kind-of@6.0.3: {} kleur@3.0.3: {} kleur@4.1.5: {} - knip@5.12.3(@types/node@20.12.7)(typescript@5.4.5): + knip@5.26.0(@types/node@20.14.11)(typescript@5.5.3): dependencies: - '@ericcornelissen/bash-parser': 0.5.2 - '@nodelib/fs.walk': 2.0.0 + '@nodelib/fs.walk': 1.2.8 '@snyk/github-codeowners': 1.1.0 - '@types/node': 20.12.7 + '@types/node': 20.14.11 easy-table: 1.2.0 fast-glob: 3.3.2 - file-entry-cache: 8.0.0 - jiti: 1.21.0 + jiti: 1.21.6 js-yaml: 4.1.0 minimist: 1.2.8 - picocolors: 1.0.0 + picocolors: 1.0.1 picomatch: 4.0.2 - pretty-ms: 9.0.0 + pretty-ms: 9.1.0 resolve: 1.22.8 - smol-toml: 1.1.4 + smol-toml: 1.3.0 strip-json-comments: 5.0.1 summary: 2.1.0 - typescript: 5.4.5 - zod: 3.23.6 - zod-validation-error: 3.2.0(zod@3.23.6) + typescript: 5.5.3 + zod: 3.23.8 + zod-validation-error: 3.3.1(zod@3.23.8) koa-compose@3.2.1: dependencies: @@ -19575,25 +19169,25 @@ snapshots: kuler@2.0.0: {} - lambda-local@2.1.2: + lambda-local@2.2.0: dependencies: commander: 10.0.1 dotenv: 16.4.5 - winston: 3.13.0 + winston: 3.14.2 - language-subtag-registry@0.3.22: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: dependencies: - language-subtag-registry: 0.3.22 + language-subtag-registry: 0.3.23 latest-version@7.0.0: dependencies: package-json: 8.1.1 - launch-editor@2.6.1: + launch-editor@2.8.1: dependencies: - picocolors: 1.0.0 + picocolors: 1.0.1 shell-quote: 1.8.1 lazystream@1.0.1: @@ -19611,20 +19205,20 @@ snapshots: dependencies: cookie: 0.6.0 process-warning: 3.0.0 - set-cookie-parser: 2.6.0 + set-cookie-parser: 2.7.0 - lilconfig@3.1.1: {} + lilconfig@3.1.2: {} lines-and-columns@1.2.4: {} lines-and-columns@2.0.4: {} - list-installed@5.3.0: + list-installed@5.3.1: dependencies: - buffered-async-iterable: 0.3.0 + buffered-async-iterable: 1.0.1 pony-cause: 2.1.11 read-pkg: 9.0.1 - read-workspaces: 1.2.0 + read-workspaces: 1.2.2 listhen@1.7.2: dependencies: @@ -19636,32 +19230,34 @@ snapshots: crossws: 0.2.4 defu: 6.1.4 get-port-please: 3.1.2 - h3: 1.11.1 + h3: 1.12.0 http-shutdown: 1.2.2 - jiti: 1.21.0 - mlly: 1.7.0 + jiti: 1.21.6 + mlly: 1.7.1 node-forge: 1.3.1 pathe: 1.1.2 std-env: 3.7.0 - ufo: 1.5.3 + ufo: 1.5.4 untun: 0.1.3 uqr: 0.1.2 transitivePeerDependencies: - uWebSockets.js - listr2@7.0.2: + listr2@8.2.3: dependencies: - cli-truncate: 3.1.0 + cli-truncate: 4.0.0 colorette: 2.0.20 eventemitter3: 5.0.1 - log-update: 5.0.1 - rfdc: 1.3.1 - wrap-ansi: 8.1.0 + log-update: 6.0.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 load-plugin@6.0.3: dependencies: - '@npmcli/config': 8.3.1 + '@npmcli/config': 8.3.4 import-meta-resolve: 4.1.0 + transitivePeerDependencies: + - bluebird load-tsconfig@0.2.5: {} @@ -19696,8 +19292,6 @@ snapshots: lodash.clonedeepwith@4.5.0: {} - lodash.curry@4.1.1: {} - lodash.debounce@4.0.8: {} lodash.includes@4.3.0: {} @@ -19736,32 +19330,32 @@ snapshots: jest-validate: 27.5.1 map-obj: 5.0.2 moize: 6.1.6 - semver: 7.6.0 + semver: 7.6.3 - log-symbols@5.1.0: + log-symbols@6.0.0: dependencies: chalk: 5.3.0 is-unicode-supported: 1.3.0 - log-update@5.0.1: + log-update@6.0.0: dependencies: - ansi-escapes: 5.0.0 + ansi-escapes: 6.2.1 cli-cursor: 4.0.0 - slice-ansi: 5.0.0 + slice-ansi: 7.1.0 strip-ansi: 7.1.0 - wrap-ansi: 8.1.0 + wrap-ansi: 9.0.0 log4js@6.9.1: dependencies: date-format: 4.0.14 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) flatted: 3.3.1 - rfdc: 1.3.1 + rfdc: 1.4.1 streamroller: 3.1.5 transitivePeerDependencies: - supports-color - logform@2.6.0: + logform@2.6.1: dependencies: '@colors/colors': 1.6.0 '@types/triple-beam': 1.3.5 @@ -19780,11 +19374,11 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.6.2 + tslib: 2.6.3 lowercase-keys@3.0.0: {} - lru-cache@10.2.2: {} + lru-cache@10.4.3: {} lru-cache@4.1.5: dependencies: @@ -19799,15 +19393,11 @@ snapshots: dependencies: yallist: 4.0.0 - luxon@3.4.4: {} + luxon@3.5.0: {} lz-string@1.5.0: {} - macos-release@3.2.0: {} - - magic-string@0.16.0: - dependencies: - vlq: 0.2.3 + macos-release@3.3.0: {} make-dir@3.1.0: dependencies: @@ -19815,7 +19405,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.0 + semver: 7.6.3 make-error@1.3.6: {} @@ -19823,20 +19413,8 @@ snapshots: dependencies: tmpl: 1.0.5 - map-cache@0.2.2: {} - - map-obj@1.0.1: {} - - map-obj@2.0.0: {} - - map-obj@4.3.0: {} - map-obj@5.0.2: {} - map-visit@1.0.0: - dependencies: - object-visit: 1.0.1 - maxstache-stream@1.0.4: dependencies: maxstache: 1.0.7 @@ -19860,10 +19438,10 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-from-markdown@2.0.0: + mdast-util-from-markdown@2.0.1: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 decode-named-character-reference: 1.0.2 devlop: 1.1.0 mdast-util-to-string: 4.0.0 @@ -19881,9 +19459,9 @@ snapshots: dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.1 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color @@ -19892,11 +19470,11 @@ snapshots: dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.1 mdast-util-to-markdown: 2.1.0 parse-entities: 4.0.1 stringify-entities: 4.0.4 @@ -19908,7 +19486,7 @@ snapshots: mdast-util-mdx@3.0.0: dependencies: - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.1 mdast-util-mdx-expression: 2.0.0 mdast-util-mdx-jsx: 3.1.2 mdast-util-mdxjs-esm: 2.0.1 @@ -19920,22 +19498,22 @@ snapshots: dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.1 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color mdast-util-phrasing@4.1.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 unist-util-is: 6.0.0 mdast-util-to-markdown@2.1.0: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 longest-streak: 3.1.0 mdast-util-phrasing: 4.1.0 mdast-util-to-string: 4.0.0 @@ -19947,7 +19525,7 @@ snapshots: mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdn-data@2.0.28: {} @@ -19955,30 +19533,20 @@ snapshots: media-typer@0.3.0: {} - memfs@4.9.2: + memfs@4.11.1: dependencies: - '@jsonjoy.com/json-pack': 1.0.3(tslib@2.6.2) - '@jsonjoy.com/util': 1.1.2(tslib@2.6.2) - sonic-forest: 1.0.2(tslib@2.6.2) - tslib: 2.6.2 + '@jsonjoy.com/json-pack': 1.1.0(tslib@2.6.3) + '@jsonjoy.com/util': 1.3.0(tslib@2.6.3) + tree-dump: 1.0.2(tslib@2.6.3) + tslib: 2.6.3 memoize-one@6.0.0: {} - meow@12.1.1: {} - - meow@6.1.1: + memoize@10.0.0: dependencies: - '@types/minimist': 1.2.5 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 + mimic-function: 5.0.1 + + meow@12.1.1: {} merge-descriptors@1.0.1: {} @@ -20057,8 +19625,8 @@ snapshots: micromark-extension-mdxjs@3.0.0: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) micromark-extension-mdx-expression: 3.0.0 micromark-extension-mdx-jsx: 3.0.0 micromark-extension-mdx-md: 2.0.0 @@ -20146,7 +19714,7 @@ snapshots: dependencies: '@types/acorn': 4.0.6 '@types/estree': 1.0.5 - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 devlop: 1.1.0 estree-util-visit: 2.0.0 micromark-util-symbol: 2.0.0 @@ -20182,7 +19750,7 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -20190,7 +19758,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -20209,31 +19777,15 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@3.1.10: - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - - micromatch@4.0.5: + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} + mime-db@1.53.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 @@ -20248,23 +19800,25 @@ snapshots: mimic-fn@4.0.0: {} + mimic-function@5.0.1: {} + mimic-response@3.1.0: {} mimic-response@4.0.0: {} min-indent@1.0.1: {} - mini-css-extract-plugin@2.9.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + mini-css-extract-plugin@2.9.1(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - mini-css-extract-plugin@2.9.0(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + mini-css-extract-plugin@2.9.1(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) minimalistic-assert@1.0.1: {} @@ -20276,16 +19830,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimatch@9.0.4: + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 - minimist-options@4.1.0: - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - minimist@0.0.10: {} minimist@1.2.8: {} @@ -20296,20 +19844,13 @@ snapshots: minipass@5.0.0: {} - minipass@7.0.4: {} + minipass@7.1.2: {} minizlib@2.1.2: dependencies: minipass: 3.3.6 yallist: 4.0.0 - mixin-deep@1.3.2: - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - - mixme@0.5.10: {} - mkdirp-classic@0.5.3: {} mkdirp@0.5.6: @@ -20318,12 +19859,12 @@ snapshots: mkdirp@1.0.4: {} - mlly@1.7.0: + mlly@1.7.1: dependencies: - acorn: 8.11.3 + acorn: 8.12.1 pathe: 1.1.2 - pkg-types: 1.1.0 - ufo: 1.5.3 + pkg-types: 1.2.0 + ufo: 1.5.4 module-definition@5.0.1: dependencies: @@ -20347,27 +19888,27 @@ snapshots: ms@2.1.3: {} - msw@2.2.14(typescript@5.4.5): + msw@2.3.1(typescript@5.5.3): dependencies: '@bundled-es-modules/cookie': 2.0.0 '@bundled-es-modules/statuses': 1.0.1 - '@inquirer/confirm': 3.1.6 - '@mswjs/cookies': 1.1.0 - '@mswjs/interceptors': 0.26.15 + '@inquirer/confirm': 3.1.22 + '@mswjs/cookies': 1.1.1 + '@mswjs/interceptors': 0.29.1 '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 '@types/statuses': 2.0.5 chalk: 4.1.2 - graphql: 16.8.1 + graphql: 16.9.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 - outvariant: 1.4.2 + outvariant: 1.4.3 path-to-regexp: 6.2.2 strict-event-emitter: 0.5.1 - type-fest: 4.18.1 + type-fest: 4.25.0 yargs: 17.7.2 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 muggle-string@0.3.1: {} @@ -20392,27 +19933,11 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.19.0: + nan@2.20.0: optional: true nanoid@3.3.7: {} - nanomatch@1.2.13: - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - fragment-cache: 0.2.1 - is-windows: 1.0.2 - kind-of: 6.0.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - napi-build-utils@1.0.2: {} natural-compare@1.4.0: {} @@ -20423,53 +19948,52 @@ snapshots: nested-error-stacks@2.1.1: {} - netlify-cli@17.23.1(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/express@4.17.21)(@types/node@20.12.7)(picomatch@4.0.2): + netlify-cli@17.33.4(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/express@4.17.21)(@types/node@22.5.0)(picomatch@4.0.2): dependencies: - '@bugsnag/js': 7.22.7 - '@fastify/static': 6.12.0 - '@netlify/blobs': 7.3.0 - '@netlify/build': 29.41.2(@opentelemetry/api@1.8.0)(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(picomatch@4.0.2) - '@netlify/build-info': 7.13.2 - '@netlify/config': 20.12.3 - '@netlify/edge-bundler': 12.0.0 - '@netlify/edge-functions': 2.5.1 + '@bugsnag/js': 7.25.0 + '@fastify/static': 7.0.4 + '@netlify/blobs': 7.4.0 + '@netlify/build': 29.51.3(@opentelemetry/api@1.8.0)(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/node@22.5.0)(picomatch@4.0.2) + '@netlify/build-info': 7.14.1 + '@netlify/config': 20.17.1 + '@netlify/edge-bundler': 12.2.2 + '@netlify/edge-functions': 2.9.0 '@netlify/local-functions-proxy': 1.1.1 - '@netlify/zip-it-and-ship-it': 9.32.1(@opentelemetry/api@1.8.0) - '@octokit/rest': 19.0.13 + '@netlify/zip-it-and-ship-it': 9.37.7 + '@octokit/rest': 20.1.1 '@opentelemetry/api': 1.8.0 - ansi-escapes: 6.2.1 + ansi-escapes: 7.0.0 ansi-styles: 6.2.1 ansi-to-html: 0.7.2 ascii-table: 0.0.9 backoff: 2.5.0 better-opn: 3.0.2 boxen: 7.1.1 - chalk: 5.2.0 - chokidar: 3.5.3 - ci-info: 3.8.0 + chalk: 5.3.0 + chokidar: 3.6.0 + ci-info: 4.0.0 clean-deep: 3.4.0 commander: 10.0.1 comment-json: 4.2.3 concordance: 5.0.4 configstore: 6.0.0 content-type: 1.0.5 - cookie: 0.5.0 - copy-template-dir: 1.4.0 - cron-parser: 4.8.1 - debug: 4.3.4(supports-color@5.5.0) + cookie: 0.6.0 + cron-parser: 4.9.0 + debug: 4.3.5 decache: 4.6.2 - dot-prop: 7.2.0 - dotenv: 16.0.3 + dot-prop: 9.0.0 + dotenv: 16.4.5 env-paths: 3.0.0 - envinfo: 7.8.1 + envinfo: 7.13.0 etag: 1.8.1 execa: 5.1.1 express: 4.19.2 express-logging: 1.1.1 extract-zip: 2.0.1 fastest-levenshtein: 1.0.16 - fastify: 4.17.0 - find-up: 6.3.0 + fastify: 4.28.1 + find-up: 7.0.0 flush-write-stream: 2.0.0 folder-walker: 3.2.0 from2-array: 0.0.4 @@ -20480,63 +20004,65 @@ snapshots: gitconfiglocal: 2.1.0 hasbin: 1.2.3 hasha: 5.2.2 - http-proxy: 1.18.1(debug@4.3.4) - http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.4) - https-proxy-agent: 7.0.4 + http-proxy: 1.18.1(debug@4.3.5) + http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.5) + https-proxy-agent: 7.0.5 inquirer: 6.5.2 inquirer-autocomplete-prompt: 1.4.0(inquirer@6.5.2) - ipx: 2.1.0(@netlify/blobs@7.3.0) + ipx: 2.1.0(@netlify/blobs@7.4.0) is-docker: 3.0.0 - is-stream: 3.0.0 - is-wsl: 2.2.0 - isexe: 2.0.0 + is-stream: 4.0.1 + is-wsl: 3.1.0 + isexe: 3.1.1 js-yaml: 4.1.0 jsonwebtoken: 9.0.2 - jwt-decode: 3.1.2 - lambda-local: 2.1.2 - listr2: 7.0.2 + jwt-decode: 4.0.0 + lambda-local: 2.2.0 + listr2: 8.2.3 locate-path: 7.2.0 lodash: 4.17.21 - log-symbols: 5.1.0 - log-update: 5.0.1 + log-symbols: 6.0.0 + log-update: 6.0.0 + maxstache: 1.0.7 + maxstache-stream: 1.0.4 multiparty: 4.2.3 - netlify: 13.1.15 + netlify: 13.1.20 netlify-headers-parser: 7.1.4 - netlify-redirect-parser: 14.2.2 + netlify-redirect-parser: 14.3.0 netlify-redirector: 0.5.0 - node-fetch: 2.6.12 + node-fetch: 3.3.2 node-version-alias: 3.4.1 - ora: 6.3.1 - p-filter: 3.0.0 - p-map: 5.5.0 + ora: 8.0.1 + p-filter: 4.1.0 + p-map: 7.0.2 p-wait-for: 5.0.2 parallel-transform: 1.2.0 - parse-github-url: 1.0.2 + parse-github-url: 1.0.3 parse-gitignore: 2.0.0 path-key: 4.0.0 prettyjson: 1.2.5 pump: 3.0.0 raw-body: 2.5.2 read-package-up: 11.0.0 - semver: 7.6.0 + readdirp: 3.6.0 + semver: 7.6.2 source-map-support: 0.5.21 strip-ansi-control-characters: 2.0.0 tabtab: 3.0.2 - tempy: 3.0.0 + tempy: 3.1.0 terminal-link: 3.0.0 - through2-filter: 3.0.0 - through2-map: 3.0.0 - to-readable-stream: 3.0.0 + through2-filter: 4.0.0 + through2-map: 4.0.0 toml: 3.0.0 tomlify-j0.4: 3.0.0 ulid: 2.3.0 unixify: 1.0.0 - update-notifier: 6.0.2 + update-notifier: 7.0.0 uuid: 9.0.1 - wait-port: 1.0.4 + wait-port: 1.1.0 write-file-atomic: 5.0.1 - ws: 8.14.2 - zod: 3.22.4 + ws: 8.17.1 + zod: 3.23.8 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -20571,7 +20097,7 @@ snapshots: map-obj: 5.0.2 path-exists: 5.0.0 - netlify-redirect-parser@14.2.2: + netlify-redirect-parser@14.3.0: dependencies: '@iarna/toml': 2.2.5 fast-safe-stringify: 2.1.1 @@ -20581,37 +20107,33 @@ snapshots: netlify-redirector@0.5.0: {} - netlify@13.1.15: + netlify@13.1.20: dependencies: - '@netlify/open-api': 2.30.0 + '@netlify/open-api': 2.34.0 lodash-es: 4.17.21 micro-api-client: 3.3.0 node-fetch: 3.3.2 omit.js: 2.0.2 p-wait-for: 4.1.0 - qs: 6.12.1 + qs: 6.13.0 no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.2 + tslib: 2.6.3 - node-abi@3.62.0: + node-abi@3.67.0: dependencies: - semver: 7.6.0 + semver: 7.6.3 node-addon-api@6.1.0: {} - node-addon-api@7.1.0: {} + node-addon-api@7.1.1: {} node-domexception@1.0.0: {} node-fetch-native@1.6.4: {} - node-fetch@2.6.12: - dependencies: - whatwg-url: 5.0.0 - node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -20628,7 +20150,7 @@ snapshots: node-int64@0.4.0: {} - node-releases@2.0.14: {} + node-releases@2.0.18: {} node-schedule@2.1.1: dependencies: @@ -20638,7 +20160,7 @@ snapshots: node-source-walk@6.0.2: dependencies: - '@babel/parser': 7.24.5 + '@babel/parser': 7.25.4 node-stream-zip@1.15.0: {} @@ -20649,19 +20171,19 @@ snapshots: is-plain-obj: 4.1.0 normalize-node-version: 12.4.0 path-exists: 5.0.0 - semver: 7.6.0 + semver: 7.6.3 - nodemon@3.1.0: + nodemon@3.1.4: dependencies: chokidar: 3.6.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.6.0 + semver: 7.6.3 simple-update-notifier: 2.0.0 supports-color: 5.5.0 - touch: 3.1.0 + touch: 3.1.1 undefsafe: 2.0.5 noms@0.0.0: @@ -20669,17 +20191,11 @@ snapshots: inherits: 2.0.4 readable-stream: 1.0.34 - noop2@2.0.0: {} - - nopt@1.0.10: - dependencies: - abbrev: 1.1.1 - nopt@5.0.0: dependencies: abbrev: 1.1.1 - nopt@7.2.0: + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -20687,27 +20203,19 @@ snapshots: dependencies: all-node-versions: 11.3.0 filter-obj: 5.1.0 - semver: 7.6.0 - - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 + semver: 7.6.3 normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.13.1 - semver: 7.6.0 + is-core-module: 2.15.1 + semver: 7.6.3 validate-npm-package-license: 3.0.4 - normalize-package-data@6.0.0: + normalize-package-data@6.0.2: dependencies: - hosted-git-info: 7.0.1 - is-core-module: 2.13.1 - semver: 7.6.0 + hosted-git-info: 7.0.2 + semver: 7.6.3 validate-npm-package-license: 3.0.4 normalize-path@2.1.1: @@ -20718,8 +20226,26 @@ snapshots: normalize-url@8.0.1: {} + npm-install-checks@6.3.0: + dependencies: + semver: 7.6.3 + npm-normalize-package-bin@3.0.1: {} + npm-package-arg@11.0.3: + dependencies: + hosted-git-info: 7.0.2 + proc-log: 4.2.0 + semver: 7.6.3 + validate-npm-package-name: 5.0.1 + + npm-pick-manifest@9.1.0: + dependencies: + npm-install-checks: 6.3.0 + npm-normalize-package-bin: 3.0.1 + npm-package-arg: 11.0.3 + semver: 7.6.3 + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -20739,28 +20265,19 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.9: {} + nwsapi@2.2.12: {} object-assign@4.1.1: {} - object-copy@0.1.0: - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 + object-inspect@1.13.2: {} - object-inspect@1.13.1: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 object-keys@1.1.1: {} - object-pairs@0.1.0: {} - - object-values@1.0.0: {} - - object-visit@1.0.1: - dependencies: - isobject: 3.0.1 - object.assign@4.1.5: dependencies: call-bind: 1.0.7 @@ -20787,16 +20304,6 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.3 - object.hasown@1.1.4: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - object.pick@1.3.0: - dependencies: - isobject: 3.0.1 - object.values@1.2.0: dependencies: call-bind: 1.0.7 @@ -20809,7 +20316,7 @@ snapshots: dependencies: destr: 2.0.3 node-fetch-native: 1.6.4 - ufo: 1.5.3 + ufo: 1.5.4 ohash@1.1.3: {} @@ -20874,28 +20381,28 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - ora@6.3.1: + ora@8.0.1: dependencies: chalk: 5.3.0 cli-cursor: 4.0.0 cli-spinners: 2.9.2 is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 + is-unicode-supported: 2.0.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 strip-ansi: 7.1.0 - wcwidth: 1.0.1 os-name@5.1.0: dependencies: - macos-release: 3.2.0 + macos-release: 3.3.0 windows-release: 5.1.1 os-tmpdir@1.0.2: {} outdent@0.5.0: {} - outvariant@1.4.2: {} + outvariant@1.4.3: {} p-cancelable@3.0.0: {} @@ -20919,6 +20426,10 @@ snapshots: dependencies: p-map: 5.5.0 + p-filter@4.1.0: + dependencies: + p-map: 7.0.2 + p-finally@1.0.0: {} p-limit@2.3.0: @@ -20931,7 +20442,7 @@ snapshots: p-limit@4.0.0: dependencies: - yocto-queue: 1.0.0 + yocto-queue: 1.1.1 p-locate@4.1.0: dependencies: @@ -20957,6 +20468,8 @@ snapshots: p-map@6.0.0: {} + p-map@7.0.2: {} + p-reduce@3.0.0: {} p-retry@5.1.2: @@ -20988,7 +20501,9 @@ snapshots: dependencies: p-timeout: 6.1.2 - package-json-validator@0.6.4: + package-json-from-dist@1.0.0: {} + + package-json-validator@0.6.5: dependencies: optimist: 0.6.1 @@ -20997,7 +20512,7 @@ snapshots: got: 12.6.1 registry-auth-token: 5.0.2 registry-url: 6.0.1 - semver: 7.6.0 + semver: 7.6.3 parallel-transform@1.2.0: dependencies: @@ -21008,7 +20523,7 @@ snapshots: param-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.6.3 parent-module@1.0.1: dependencies: @@ -21025,7 +20540,7 @@ snapshots: parse-entities@4.0.1: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 @@ -21034,30 +20549,30 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - parse-github-url@1.0.2: {} + parse-github-url@1.0.3: {} parse-gitignore@2.0.0: {} parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 parse-json@7.1.1: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 - json-parse-even-better-errors: 3.0.1 + json-parse-even-better-errors: 3.0.2 lines-and-columns: 2.0.4 type-fest: 3.13.1 parse-json@8.1.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 index-to-position: 0.1.2 - type-fest: 4.18.1 + type-fest: 4.25.0 parse-ms@3.0.0: {} @@ -21074,9 +20589,7 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.6.2 - - pascalcase@0.1.1: {} + tslib: 2.6.3 path-browserify@1.0.1: {} @@ -21092,10 +20605,10 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.2: + path-scurry@1.11.1: dependencies: - lru-cache: 10.2.2 - minipass: 7.0.4 + lru-cache: 10.4.3 + minipass: 7.1.2 path-to-regexp@0.1.7: {} @@ -21107,11 +20620,11 @@ snapshots: pathe@1.1.2: {} - peek-readable@5.0.0: {} + peek-readable@5.1.4: {} pend@1.2.0: {} - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -21124,21 +20637,21 @@ snapshots: readable-stream: 4.5.2 split2: 4.2.0 - pino-std-serializers@6.2.2: {} + pino-std-serializers@7.0.0: {} - pino@8.21.0: + pino@9.3.2: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.5.0 on-exit-leak-free: 2.1.2 pino-abstract-transport: 1.2.0 - pino-std-serializers: 6.2.2 - process-warning: 3.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.1 - thread-stream: 2.7.0 + sonic-boom: 4.0.1 + thread-stream: 3.1.0 pirates@4.0.6: {} @@ -21150,10 +20663,10 @@ snapshots: dependencies: find-up: 6.3.0 - pkg-types@1.1.0: + pkg-types@1.2.0: dependencies: confbox: 0.1.7 - mlly: 1.7.0 + mlly: 1.7.1 pathe: 1.1.2 pony-cause@2.1.11: {} @@ -21166,79 +20679,77 @@ snapshots: transitivePeerDependencies: - supports-color - posix-character-classes@0.1.1: {} - possible-typed-array-names@1.0.0: {} - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.5.0): dependencies: - lilconfig: 3.1.1 - yaml: 2.4.2 + lilconfig: 3.1.2 optionalDependencies: - postcss: 8.4.38 - ts-node: 10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + jiti: 1.21.6 + postcss: 8.4.39 + yaml: 2.5.0 - postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + postcss-loader@8.1.1(postcss@8.4.39)(typescript@5.5.3)(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: - cosmiconfig: 9.0.0(typescript@5.4.5) - jiti: 1.21.0 - postcss: 8.4.38 - semver: 7.6.0 + cosmiconfig: 9.0.0(typescript@5.5.3) + jiti: 1.21.6 + postcss: 8.4.39 + semver: 7.6.3 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) transitivePeerDependencies: - typescript - postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + postcss-loader@8.1.1(postcss@8.4.39)(typescript@5.5.3)(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: - cosmiconfig: 9.0.0(typescript@5.4.5) - jiti: 1.21.0 - postcss: 8.4.38 - semver: 7.6.0 + cosmiconfig: 9.0.0(typescript@5.5.3) + jiti: 1.21.6 + postcss: 8.4.39 + semver: 7.6.3 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) transitivePeerDependencies: - typescript - postcss-modules-extract-imports@3.1.0(postcss@8.4.38): + postcss-modules-extract-imports@3.1.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 - postcss-modules-local-by-default@4.0.5(postcss@8.4.38): + postcss-modules-local-by-default@4.0.5(postcss@8.4.39): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 + postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.38): + postcss-modules-scope@3.2.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 + postcss: 8.4.39 + postcss-selector-parser: 6.1.2 - postcss-modules-values@4.0.0(postcss@8.4.38): + postcss-modules-values@4.0.0(postcss@8.4.39): dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 + icss-utils: 5.1.0(postcss@8.4.39) + postcss: 8.4.39 - postcss-selector-parser@6.0.16: + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss-values-parser@6.0.2(postcss@8.4.38): + postcss-values-parser@6.0.2(postcss@8.4.39): dependencies: color-name: 1.1.4 is-url-superb: 4.0.0 - postcss: 8.4.38 + postcss: 8.4.39 quote-unquote: 1.0.0 - postcss@8.4.38: + postcss@8.4.39: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 prebuild-install@7.1.2: @@ -21249,7 +20760,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 1.0.2 - node-abi: 3.62.0 + node-abi: 3.67.0 pump: 3.0.0 rc: 1.2.8 simple-get: 4.0.1 @@ -21292,12 +20803,12 @@ snapshots: precond@0.2.3: {} - preferred-pm@3.1.3: + preferred-pm@3.1.4: dependencies: find-up: 5.0.0 find-yarn-workspace-root2: 1.2.16 path-exists: 4.0.0 - which-pm: 2.0.0 + which-pm: 2.2.0 prelude-ls@1.2.1: {} @@ -21324,7 +20835,7 @@ snapshots: dependencies: parse-ms: 3.0.0 - pretty-ms@9.0.0: + pretty-ms@9.1.0: dependencies: parse-ms: 4.0.0 @@ -21337,12 +20848,19 @@ snapshots: process-nextick-args@2.0.1: {} - process-warning@2.3.2: {} - process-warning@3.0.0: {} + process-warning@4.0.0: {} + process@0.11.10: {} + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -21393,7 +20911,7 @@ snapshots: dependencies: side-channel: 1.0.6 - qs@6.12.1: + qs@6.13.0: dependencies: side-channel: 1.0.6 @@ -21405,15 +20923,13 @@ snapshots: quick-format-unescaped@4.0.4: {} - quick-lru@4.0.1: {} - quick-lru@5.1.1: {} quote-unquote@1.0.0: {} radix3@1.1.2: {} - rambda@9.2.0: {} + rambda@9.3.0: {} random-bytes@1.0.0: {} @@ -21445,14 +20961,14 @@ snapshots: react-error-boundary@4.0.13(react@18.3.1): dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 react: 18.3.1 - react-i18next@14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-i18next@15.0.0(i18next@23.12.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.25.4 html-parse-stringify: 3.0.1 - i18next: 23.11.3 + i18next: 23.12.1 react: 18.3.1 optionalDependencies: react-dom: 18.3.1(react@18.3.1) @@ -21465,16 +20981,16 @@ snapshots: react-refresh@0.14.2: {} - react-router-dom@6.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/router': 1.16.0 + '@remix-run/router': 1.18.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router: 6.23.0(react@18.3.1) + react-router: 6.25.1(react@18.3.1) - react-router@6.23.0(react@18.3.1): + react-router@6.25.1(react@18.3.1): dependencies: - '@remix-run/router': 1.16.0 + '@remix-run/router': 1.18.0 react: 18.3.1 react-shallow-renderer@16.15.0(react@18.3.1): @@ -21496,20 +21012,14 @@ snapshots: read-package-json-fast@3.0.2: dependencies: - json-parse-even-better-errors: 3.0.1 + json-parse-even-better-errors: 3.0.2 npm-normalize-package-bin: 3.0.1 read-package-up@11.0.0: dependencies: find-up-simple: 1.0.0 read-pkg: 9.0.1 - type-fest: 4.18.1 - - read-pkg-up@7.0.1: - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 + type-fest: 4.25.0 read-pkg-up@9.1.0: dependencies: @@ -21517,13 +21027,6 @@ snapshots: read-pkg: 7.1.0 type-fest: 2.19.0 - read-pkg@5.2.0: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - read-pkg@7.1.0: dependencies: '@types/normalize-package-data': 2.4.4 @@ -21534,15 +21037,15 @@ snapshots: read-pkg@9.0.1: dependencies: '@types/normalize-package-data': 2.4.4 - normalize-package-data: 6.0.0 + normalize-package-data: 6.0.2 parse-json: 8.1.0 - type-fest: 4.18.1 + type-fest: 4.25.0 unicorn-magic: 0.1.0 - read-workspaces@1.2.0: + read-workspaces@1.2.2: dependencies: '@npmcli/map-workspaces': 3.0.6 - '@pnpm/workspace.read-manifest': 1.0.3 + '@pnpm/workspace.read-manifest': 2.2.0 read-pkg: 9.0.1 read-yaml-file@1.1.0: @@ -21596,14 +21099,6 @@ snapshots: dependencies: minimatch: 5.1.6 - readdirp@2.2.1: - dependencies: - graceful-fs: 4.2.11 - micromatch: 3.1.10 - readable-stream: 2.3.8 - transitivePeerDependencies: - - supports-color - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -21627,7 +21122,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 globalthis: 1.0.4 - which-builtin-type: 1.1.3 + which-builtin-type: 1.1.4 regenerate-unicode-properties@10.1.1: dependencies: @@ -21639,12 +21134,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.24.5 - - regex-not@1.0.2: - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 + '@babel/runtime': 7.25.4 regexp.prototype.flags@1.5.2: dependencies: @@ -21664,7 +21154,7 @@ snapshots: registry-auth-token@5.0.2: dependencies: - '@pnpm/npm-conf': 2.2.2 + '@pnpm/npm-conf': 2.3.1 registry-url@6.0.1: dependencies: @@ -21685,18 +21175,18 @@ snapshots: remark-parse@11.0.0: dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.1 micromark-util-types: 2.0.0 - unified: 11.0.4 + unified: 11.0.5 transitivePeerDependencies: - supports-color remark-stringify@11.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdast-util-to-markdown: 2.1.0 - unified: 11.0.4 + unified: 11.0.5 remove-trailing-separator@1.1.0: {} @@ -21708,16 +21198,12 @@ snapshots: lodash: 4.17.21 strip-ansi: 6.0.1 - repeat-element@1.1.4: {} - repeat-string@1.6.1: {} require-directory@2.1.1: {} require-from-string@2.0.2: {} - require-main-filename@2.0.0: {} - require-package-name@2.0.1: {} requireindex@1.2.0: {} @@ -21739,19 +21225,17 @@ snapshots: resolve-from@5.0.0: {} - resolve-url@0.2.1: {} - resolve.exports@2.0.2: {} resolve@1.22.8: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 resolve@2.0.0-next.5: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -21769,9 +21253,9 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - ret@0.1.15: {} + ret@0.4.3: {} - ret@0.2.2: {} + retry@0.12.0: {} retry@0.13.1: {} @@ -21779,38 +21263,36 @@ snapshots: reusify@1.0.4: {} - reverse-arguments@1.0.0: {} - - rfdc@1.3.1: {} + rfdc@1.4.1: {} rimraf@3.0.2: dependencies: glob: 7.2.3 - rimraf@5.0.5: + rimraf@5.0.10: dependencies: - glob: 10.3.12 + glob: 10.4.5 - rollup@4.17.2: + rollup@4.21.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.21.0 + '@rollup/rollup-android-arm64': 4.21.0 + '@rollup/rollup-darwin-arm64': 4.21.0 + '@rollup/rollup-darwin-x64': 4.21.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.0 + '@rollup/rollup-linux-arm-musleabihf': 4.21.0 + '@rollup/rollup-linux-arm64-gnu': 4.21.0 + '@rollup/rollup-linux-arm64-musl': 4.21.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.0 + '@rollup/rollup-linux-riscv64-gnu': 4.21.0 + '@rollup/rollup-linux-s390x-gnu': 4.21.0 + '@rollup/rollup-linux-x64-gnu': 4.21.0 + '@rollup/rollup-linux-x64-musl': 4.21.0 + '@rollup/rollup-win32-arm64-msvc': 4.21.0 + '@rollup/rollup-win32-ia32-msvc': 4.21.0 + '@rollup/rollup-win32-x64-msvc': 4.21.0 fsevents: 2.3.3 run-applescript@7.0.0: {} @@ -21848,13 +21330,9 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 - safe-regex2@2.0.0: + safe-regex2@3.1.0: dependencies: - ret: 0.2.2 - - safe-regex@1.1.0: - dependencies: - ret: 0.1.15 + ret: 0.4.3 safe-stable-stringify@2.4.3: {} @@ -21877,9 +21355,9 @@ snapshots: schema-utils@4.2.0: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) - ajv-keywords: 5.1.0(ajv@8.13.0) + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) secure-compare@3.0.1: {} @@ -21898,9 +21376,7 @@ snapshots: semver-diff@4.0.0: dependencies: - semver: 7.6.0 - - semver@5.7.2: {} + semver: 7.6.3 semver@6.3.1: {} @@ -21908,6 +21384,10 @@ snapshots: dependencies: lru-cache: 6.0.0 + semver@7.6.2: {} + + semver@7.6.3: {} + send@0.18.0: dependencies: debug: 2.6.9 @@ -21953,7 +21433,7 @@ snapshots: set-blocking@2.0.0: {} - set-cookie-parser@2.6.0: {} + set-cookie-parser@2.7.0: {} set-function-length@1.2.2: dependencies: @@ -21971,13 +21451,6 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 - set-value@2.0.1: - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - setprototypeof@1.1.0: {} setprototypeof@1.2.0: {} @@ -21992,7 +21465,7 @@ snapshots: detect-libc: 2.0.3 node-addon-api: 6.1.0 prebuild-install: 7.1.2 - semver: 7.6.0 + semver: 7.6.3 simple-get: 4.0.1 tar-fs: 3.0.6 tunnel-agent: 0.6.0 @@ -22009,8 +21482,6 @@ snapshots: shebang-regex@3.0.0: {} - shell-quote-word@1.0.1: {} - shell-quote@1.8.1: {} side-channel@1.0.6: @@ -22018,7 +21489,7 @@ snapshots: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + object-inspect: 1.13.2 signal-exit@3.0.7: {} @@ -22038,7 +21509,7 @@ snapshots: simple-update-notifier@2.0.0: dependencies: - semver: 7.6.0 + semver: 7.6.3 sisteransi@1.0.5: {} @@ -22051,44 +21522,17 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 - smartwrap@2.0.2: + slice-ansi@7.1.0: dependencies: - array.prototype.flat: 1.3.2 - breakword: 1.0.6 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 - smol-toml@1.1.4: {} + smol-toml@1.3.0: {} snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 - - snapdragon-node@2.1.1: - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - - snapdragon-util@3.0.1: - dependencies: - kind-of: 3.2.2 - - snapdragon@0.8.2: - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color + tslib: 2.6.3 sockjs@0.3.24: dependencies: @@ -22096,15 +21540,10 @@ snapshots: uuid: 8.3.2 websocket-driver: 0.7.4 - sonic-boom@3.8.1: + sonic-boom@4.0.1: dependencies: atomic-sleep: 1.0.0 - sonic-forest@1.0.2(tslib@2.6.2): - dependencies: - tree-dump: 1.0.1(tslib@2.6.2) - tslib: 2.6.2 - sort-keys-length@1.0.1: dependencies: sort-keys: 1.1.2 @@ -22128,14 +21567,6 @@ snapshots: source-map-js@1.2.0: {} - source-map-resolve@0.5.3: - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - source-map-support@0.5.13: dependencies: buffer-from: 1.1.2 @@ -22146,10 +21577,6 @@ snapshots: buffer-from: 1.1.2 source-map: 0.6.1 - source-map-url@0.4.1: {} - - source-map@0.5.7: {} - source-map@0.6.1: {} source-map@0.7.4: {} @@ -22166,20 +21593,20 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 + spdx-license-ids: 3.0.20 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 + spdx-license-ids: 3.0.20 - spdx-license-ids@3.0.17: {} + spdx-license-ids@3.0.20: {} spdy-transport@3.0.0: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -22190,7 +21617,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -22198,10 +21625,6 @@ snapshots: transitivePeerDependencies: - supports-color - split-string@3.1.0: - dependencies: - extend-shallow: 3.0.2 - split2@1.1.1: dependencies: through2: 2.0.5 @@ -22222,39 +21645,33 @@ snapshots: stackframe@1.3.4: {} - static-extend@0.1.2: - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - statuses@1.5.0: {} statuses@2.0.1: {} std-env@3.7.0: {} - stdin-discarder@0.1.0: - dependencies: - bl: 5.1.0 + stdin-discarder@0.2.2: {} - stream-transform@2.1.3: + stop-iteration-iterator@1.0.0: dependencies: - mixme: 0.5.10 + internal-slot: 1.0.7 streamroller@3.1.5: dependencies: date-format: 4.0.14 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color - streamx@2.16.1: + streamx@2.19.0: dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 + text-decoder: 1.1.1 optionalDependencies: - bare-events: 2.2.2 + bare-events: 2.4.2 strict-event-emitter@0.5.1: {} @@ -22286,7 +21703,16 @@ snapshots: emoji-regex: 10.3.0 strip-ansi: 7.1.0 - string.fromcodepoint@0.2.1: {} + string-width@7.2.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + + string.prototype.includes@2.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 string.prototype.matchall@4.0.11: dependencies: @@ -22303,6 +21729,11 @@ snapshots: set-function-name: 2.0.2 side-channel: 1.0.6 + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + string.prototype.trim@1.2.9: dependencies: call-bind: 1.0.7 @@ -22380,24 +21811,24 @@ snapshots: strip-outer@2.0.0: {} - strtok3@7.0.0: + strtok3@7.1.1: dependencies: '@tokenizer/token': 0.3.0 - peek-readable: 5.0.0 + peek-readable: 5.1.4 - style-loader@3.3.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + style-loader@3.3.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - style-loader@3.3.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + style-loader@3.3.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 - glob: 10.3.12 + glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -22428,7 +21859,7 @@ snapshots: svg-parser@2.0.4: {} - svgo@3.2.0: + svgo@3.3.2: dependencies: '@trysound/sax': 0.2.0 commander: 7.2.0 @@ -22436,32 +21867,32 @@ snapshots: css-tree: 2.3.1 css-what: 6.1.0 csso: 5.0.5 - picocolors: 1.0.0 + picocolors: 1.0.1 - swc-loader@0.2.6(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + swc-loader@0.2.6(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) '@swc/counter': 0.1.3 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - swc-loader@0.2.6(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + swc-loader@0.2.6(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) '@swc/counter': 0.1.3 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) symbol-tree@3.2.4: {} - synckit@0.9.0: + synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.2 + tslib: 2.6.3 system-architecture@0.1.0: {} tabtab@3.0.2: dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 es6-promisify: 6.1.1 inquirer: 6.5.2 minimist: 1.2.8 @@ -22484,8 +21915,8 @@ snapshots: pump: 3.0.0 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 2.3.0 - bare-path: 2.1.2 + bare-fs: 2.3.1 + bare-path: 2.1.3 tar-stream@2.2.0: dependencies: @@ -22499,7 +21930,7 @@ snapshots: dependencies: b4a: 1.6.6 fast-fifo: 1.3.2 - streamx: 2.16.1 + streamx: 2.19.0 tar@6.2.1: dependencies: @@ -22510,12 +21941,12 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - temp-dir@2.0.0: {} + temp-dir@3.0.0: {} - tempy@3.0.0: + tempy@3.1.0: dependencies: is-stream: 3.0.0 - temp-dir: 2.0.0 + temp-dir: 3.0.0 type-fest: 2.19.0 unique-string: 3.0.0 @@ -22526,45 +21957,32 @@ snapshots: ansi-escapes: 5.0.0 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4)): - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.31.0 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4) - optionalDependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - esbuild: 0.19.12 - - terser-webpack-plugin@5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + terser-webpack-plugin@5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.31.0 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + terser: 5.31.6 + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - esbuild: 0.19.12 + '@swc/core': 1.7.0(@swc/helpers@0.5.12) - terser-webpack-plugin@5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.31.0 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + terser: 5.31.6 + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) optionalDependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) - terser@5.31.0: + terser@5.31.6: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 + acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 @@ -22574,6 +21992,10 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-decoder@1.1.1: + dependencies: + b4a: 1.6.6 + text-hex@1.0.0: {} text-table@0.2.0: {} @@ -22586,37 +22008,37 @@ snapshots: dependencies: any-promise: 1.3.0 - thingies@1.21.0(tslib@2.6.2): + thingies@1.21.0(tslib@2.6.3): dependencies: - tslib: 2.6.2 + tslib: 2.6.3 - thread-stream@2.7.0: + thread-stream@3.1.0: dependencies: real-require: 0.2.0 - through2-filter@3.0.0: + through2-filter@4.0.0: dependencies: - through2: 2.0.5 - xtend: 4.0.2 + through2: 4.0.2 - through2-map@3.0.0: + through2-map@4.0.0: dependencies: - through2: 2.0.5 - xtend: 4.0.2 + through2: 4.0.2 through2@2.0.5: dependencies: readable-stream: 2.3.8 xtend: 4.0.2 + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + through@2.3.8: {} thunky@1.1.0: {} time-zone@1.0.0: {} - tiny-lru@11.2.6: {} - tmp-promise@3.0.3: dependencies: tmp: 0.2.3 @@ -22631,37 +22053,11 @@ snapshots: to-fast-properties@2.0.0: {} - to-no-case@1.0.2: {} - - to-object-path@0.3.0: - dependencies: - kind-of: 3.2.2 - - to-pascal-case@1.0.0: - dependencies: - to-space-case: 1.0.0 - - to-readable-stream@3.0.0: {} - - to-regex-range@2.1.1: - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - to-regex@3.0.2: - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - - to-space-case@1.0.0: - dependencies: - to-no-case: 1.0.2 + toad-cache@3.7.0: {} toidentifier@1.0.1: {} @@ -22674,9 +22070,7 @@ snapshots: tomlify-j0.4@3.0.0: {} - touch@3.1.0: - dependencies: - nopt: 1.0.10 + touch@3.1.1: {} tough-cookie@4.1.4: dependencies: @@ -22695,14 +22089,12 @@ snapshots: dependencies: punycode: 2.3.1 - tree-dump@1.0.1(tslib@2.6.2): + tree-dump@1.0.2(tslib@2.6.3): dependencies: - tslib: 2.6.2 + tslib: 2.6.3 tree-kill@1.2.2: {} - trim-newlines@3.0.1: {} - trim-repeated@2.0.0: dependencies: escape-string-regexp: 5.0.0 @@ -22711,51 +22103,72 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.4.5 + typescript: 5.5.3 ts-dedent@2.2.0: {} ts-interface-checker@0.1.13: {} - ts-jest@29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.19.12)(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)))(typescript@5.5.3): dependencies: bs-logger: 0.2.6 + ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.6.0 - typescript: 5.4.5 + semver: 7.6.3 + typescript: 5.5.3 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 + '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.5) - esbuild: 0.19.12 + babel-jest: 29.7.0(@babel/core@7.25.2) + + ts-node@10.9.2(@swc/core@1.7.0(@swc/helpers@0.5.12))(@types/node@22.5.0)(typescript@5.5.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.5.0 + acorn: 8.12.1 + acorn-walk: 8.3.3 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.5.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.7.0(@swc/helpers@0.5.12) - ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5): + ts-node@10.9.2(@swc/core@1.7.0)(@types/node@20.14.11)(typescript@5.5.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.7 - acorn: 8.11.3 - acorn-walk: 8.3.2 + '@types/node': 20.14.11 + acorn: 8.12.1 + acorn-walk: 8.3.3 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.4.5 + typescript: 5.5.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) + '@swc/core': 1.7.0(@swc/helpers@0.5.12) tsconfig-paths@3.15.0: dependencies: @@ -22766,48 +22179,41 @@ snapshots: tslib@1.14.1: {} - tslib@2.6.2: {} + tslib@2.6.3: {} tsscmp@1.0.6: {} - tsup@8.0.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))(typescript@5.4.5): + tsup@8.1.2(@swc/core@1.7.0)(jiti@1.21.6)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.5.0): dependencies: - bundle-require: 4.1.0(esbuild@0.19.12) + bundle-require: 5.0.0(esbuild@0.23.1) cac: 6.7.14 chokidar: 3.6.0 - debug: 4.3.4(supports-color@5.5.0) - esbuild: 0.19.12 + consola: 3.2.3 + debug: 4.3.6(supports-color@5.5.0) + esbuild: 0.23.1 execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.17(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + postcss-load-config: 6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.5.0) resolve-from: 5.0.0 - rollup: 4.17.2 + rollup: 4.21.0 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: - '@swc/core': 1.4.17(@swc/helpers@0.5.11) - postcss: 8.4.38 - typescript: 5.4.5 + '@swc/core': 1.7.0(@swc/helpers@0.5.12) + postcss: 8.4.39 + typescript: 5.5.3 transitivePeerDependencies: + - jiti - supports-color - - ts-node + - tsx + - yaml - tsutils@3.21.0(typescript@5.4.5): + tsutils@3.21.0(typescript@5.5.3): dependencies: tslib: 1.14.1 - typescript: 5.4.5 - - tty-table@4.2.3: - dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 + typescript: 5.5.3 tunnel-agent@0.6.0: dependencies: @@ -22846,14 +22252,10 @@ snapshots: type-detect@4.0.8: {} - type-fest@0.13.1: {} - type-fest@0.20.2: {} type-fest@0.21.3: {} - type-fest@0.6.0: {} - type-fest@0.8.1: {} type-fest@1.4.0: {} @@ -22862,7 +22264,7 @@ snapshots: type-fest@3.13.1: {} - type-fest@4.18.1: {} + type-fest@4.25.0: {} type-is@1.6.18: dependencies: @@ -22907,9 +22309,9 @@ snapshots: typedarray@0.0.6: {} - typescript@5.4.5: {} + typescript@5.5.3: {} - ufo@1.5.3: {} + ufo@1.5.4: {} uid-safe@2.1.5: dependencies: @@ -22935,7 +22337,9 @@ snapshots: undici-types@5.26.5: {} - unenv@1.9.0: + undici-types@6.19.8: {} + + unenv@1.10.0: dependencies: consola: 3.2.3 defu: 6.1.4 @@ -22943,10 +22347,6 @@ snapshots: node-fetch-native: 1.6.4 pathe: 1.1.2 - unescape-js@1.1.4: - dependencies: - string.fromcodepoint: 0.2.1 - unicode-canonical-property-names-ecmascript@2.0.0: {} unicode-match-property-ecmascript@2.0.0: @@ -22965,85 +22365,79 @@ snapshots: '@types/concat-stream': 2.0.3 '@types/debug': 4.1.12 '@types/is-empty': 1.2.3 - '@types/node': 20.12.7 - '@types/unist': 3.0.2 + '@types/node': 20.14.11 + '@types/unist': 3.0.3 concat-stream: 2.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.6(supports-color@5.5.0) extend: 3.0.2 - glob: 10.3.12 - ignore: 5.3.1 + glob: 10.4.5 + ignore: 5.3.2 is-empty: 1.2.0 is-plain-obj: 4.1.0 load-plugin: 6.0.3 parse-json: 7.1.1 trough: 2.2.0 - unist-util-inspect: 8.0.0 - vfile: 6.0.1 + unist-util-inspect: 8.1.0 + vfile: 6.0.2 vfile-message: 4.0.2 vfile-reporter: 8.1.1 vfile-statistics: 3.0.0 - yaml: 2.4.2 + yaml: 2.5.0 transitivePeerDependencies: + - bluebird - supports-color - unified@11.0.4: + unified@11.0.5: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 bail: 2.0.2 devlop: 1.1.0 extend: 3.0.2 is-plain-obj: 4.1.0 trough: 2.2.0 - vfile: 6.0.1 - - union-value@1.0.1: - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 + vfile: 6.0.2 union@0.5.0: dependencies: - qs: 6.12.1 + qs: 6.13.0 unique-string@3.0.0: dependencies: crypto-random-string: 4.0.0 - unist-util-inspect@8.0.0: + unist-util-inspect@8.1.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is@6.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-position-from-estree@2.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-remove-position@5.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-visit: 5.0.0 unist-util-stringify-position@2.0.3: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-stringify-position@4.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-visit-parents@6.0.1: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit@5.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 @@ -23058,7 +22452,7 @@ snapshots: unix-dgram@2.0.6: dependencies: bindings: 1.5.0 - nan: 2.19.0 + nan: 2.20.0 optional: true unixify@1.0.0: @@ -23067,25 +22461,20 @@ snapshots: unpipe@1.0.0: {} - unset-value@1.0.0: - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - - unstorage@1.10.2(@netlify/blobs@7.3.0): + unstorage@1.10.2(@netlify/blobs@7.4.0): dependencies: anymatch: 3.1.3 chokidar: 3.6.0 destr: 2.0.3 - h3: 1.11.1 + h3: 1.12.0 listhen: 1.7.2 - lru-cache: 10.2.2 + lru-cache: 10.4.3 mri: 1.2.0 node-fetch-native: 1.6.4 ofetch: 1.3.4 - ufo: 1.5.3 + ufo: 1.5.4 optionalDependencies: - '@netlify/blobs': 7.3.0 + '@netlify/blobs': 7.4.0 transitivePeerDependencies: - uWebSockets.js @@ -23101,26 +22490,30 @@ snapshots: upath@2.0.1: {} - update-browserslist-db@1.0.14(browserslist@4.23.0): + update-browserslist-db@1.1.0(browserslist@4.23.2): dependencies: - browserslist: 4.23.0 + browserslist: 4.23.2 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 - update-notifier@6.0.2: + update-browserslist-db@1.1.0(browserslist@4.23.3): + dependencies: + browserslist: 4.23.3 + escalade: 3.1.2 + picocolors: 1.0.1 + + update-notifier@7.0.0: dependencies: boxen: 7.1.1 chalk: 5.3.0 configstore: 6.0.0 - has-yarn: 3.0.0 import-lazy: 4.0.0 - is-ci: 3.0.1 + is-in-ci: 0.1.0 is-installed-globally: 0.4.0 is-npm: 6.0.0 - is-yarn-global: 0.4.1 latest-version: 7.0.0 pupa: 3.1.0 - semver: 7.6.0 + semver: 7.6.3 semver-diff: 4.0.0 xdg-basedir: 5.1.0 @@ -23130,8 +22523,6 @@ snapshots: dependencies: punycode: 2.3.1 - urix@0.1.0: {} - url-join@4.0.1: {} url-parse@1.5.10: @@ -23145,8 +22536,6 @@ snapshots: dependencies: react: 18.3.1 - use@3.1.1: {} - useless-lib@2.1.0: {} useless-lib@3.0.0: {} @@ -23170,7 +22559,7 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - v8-to-istanbul@9.2.0: + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 '@types/istanbul-lib-coverage': 2.0.6 @@ -23185,9 +22574,7 @@ snapshots: dependencies: builtins: 5.1.0 - validate-npm-package-name@5.0.0: - dependencies: - builtins: 5.1.0 + validate-npm-package-name@5.0.1: {} vary@1.1.2: {} @@ -23195,7 +22582,7 @@ snapshots: vfile-message@4.0.2: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 vfile-reporter@8.1.1: @@ -23204,29 +22591,27 @@ snapshots: string-width: 6.1.0 supports-color: 9.4.0 unist-util-stringify-position: 4.0.0 - vfile: 6.0.1 + vfile: 6.0.2 vfile-message: 4.0.2 vfile-sort: 4.0.0 vfile-statistics: 3.0.0 vfile-sort@4.0.0: dependencies: - vfile: 6.0.1 + vfile: 6.0.2 vfile-message: 4.0.2 vfile-statistics@3.0.0: dependencies: - vfile: 6.0.1 + vfile: 6.0.2 vfile-message: 4.0.2 - vfile@6.0.1: + vfile@6.0.2: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vlq@0.2.3: {} - void-elements@3.1.0: {} vue-template-compiler@2.7.16: @@ -23234,22 +22619,22 @@ snapshots: de-indent: 1.0.2 he: 1.2.0 - vue-tsc@1.8.27(typescript@5.4.5): + vue-tsc@1.8.27(typescript@5.5.3): dependencies: '@volar/typescript': 1.11.1 - '@vue/language-core': 1.8.27(typescript@5.4.5) - semver: 7.6.0 - typescript: 5.4.5 + '@vue/language-core': 1.8.27(typescript@5.5.3) + semver: 7.6.3 + typescript: 5.5.3 w3c-xmlserializer@4.0.0: dependencies: xml-name-validator: 4.0.0 - wait-port@1.0.4: + wait-port@1.1.0: dependencies: chalk: 4.1.2 commander: 9.5.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -23259,7 +22644,7 @@ snapshots: dependencies: makeerror: 1.0.12 - watchpack@2.4.1: + watchpack@2.4.2: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 @@ -23271,6 +22656,7 @@ snapshots: wcwidth@1.0.1: dependencies: defaults: 1.0.4 + optional: true web-streams-polyfill@3.3.3: {} @@ -23280,48 +22666,48 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0): + webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0))(webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 envinfo: 7.13.0 fastest-levenshtein: 1.0.16 - import-local: 3.1.0 + import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.91.0) + webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.93.0) - webpack-dev-middleware@7.2.1(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + webpack-dev-middleware@7.4.2(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: colorette: 2.0.20 - memfs: 4.9.2 + memfs: 4.11.1 mime-types: 2.1.35 on-finished: 2.4.1 range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - webpack-dev-middleware@7.2.1(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)): + webpack-dev-middleware@7.4.2(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: colorette: 2.0.20 - memfs: 4.9.2 + memfs: 4.11.1 mime-types: 2.1.35 on-finished: 2.4.1 range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) - webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.91.0): + webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.93.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -23329,7 +22715,7 @@ snapshots: '@types/serve-index': 1.9.4 '@types/serve-static': 1.15.7 '@types/sockjs': 0.3.36 - '@types/ws': 8.5.10 + '@types/ws': 8.5.12 ansi-html-community: 0.0.8 bonjour-service: 1.2.1 chokidar: 3.6.0 @@ -23340,29 +22726,29 @@ snapshots: express: 4.19.2 graceful-fs: 4.2.11 html-entities: 2.5.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.4) + http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.5) ipaddr.js: 2.2.0 - launch-editor: 2.6.1 + launch-editor: 2.8.1 open: 10.1.0 p-retry: 6.2.0 - rimraf: 5.0.5 + rimraf: 5.0.10 schema-utils: 4.2.0 selfsigned: 2.4.1 serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.2.1(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - ws: 8.17.0 + webpack-dev-middleware: 7.4.2(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + ws: 8.18.0 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) transitivePeerDependencies: - bufferutil - debug - supports-color - utf-8-validate - webpack-dev-server@5.0.4(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)): + webpack-dev-server@5.0.4(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -23370,7 +22756,7 @@ snapshots: '@types/serve-index': 1.9.4 '@types/serve-static': 1.15.7 '@types/sockjs': 0.3.36 - '@types/ws': 8.5.10 + '@types/ws': 8.5.12 ansi-html-community: 0.0.8 bonjour-service: 1.2.1 chokidar: 3.6.0 @@ -23381,21 +22767,21 @@ snapshots: express: 4.19.2 graceful-fs: 4.2.11 html-entities: 2.5.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.4) + http-proxy-middleware: 2.0.6(@types/express@4.17.21)(debug@4.3.5) ipaddr.js: 2.2.0 - launch-editor: 2.6.1 + launch-editor: 2.8.1 open: 10.1.0 p-retry: 6.2.0 - rimraf: 5.0.5 + rimraf: 5.0.10 schema-utils: 4.2.0 selfsigned: 2.4.1 serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.2.1(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - ws: 8.17.0 + webpack-dev-middleware: 7.4.2(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + ws: 8.18.0 optionalDependencies: - webpack: 5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12) + webpack: 5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)) transitivePeerDependencies: - bufferutil - debug @@ -23410,50 +22796,19 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.5.2 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)) - watchpack: 2.4.1 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4): + webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.5.2 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.23.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -23464,29 +22819,27 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(esbuild@0.19.12)(webpack-cli@5.1.4)) - watchpack: 2.4.1 + terser-webpack-plugin: 5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))) + watchpack: 2.4.2 webpack-sources: 3.2.3 - optionalDependencies: - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4): + webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.5.2 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.23.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -23497,11 +22850,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack@5.91.0(@swc/core@1.4.17(@swc/helpers@0.5.11))(webpack-cli@5.1.4)) - watchpack: 2.4.1 + terser-webpack-plugin: 5.3.10(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack@5.93.0(@swc/core@1.7.0(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.91.0) + webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.93.0) transitivePeerDependencies: - '@swc/core' - esbuild @@ -23547,7 +22900,7 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.1.3: + which-builtin-type@1.1.4: dependencies: function.prototype.name: 1.1.6 has-tostringtag: 1.0.2 @@ -23569,9 +22922,7 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.3 - which-module@2.0.1: {} - - which-pm@2.0.0: + which-pm@2.2.0: dependencies: load-yaml-file: 0.2.0 path-exists: 4.0.0 @@ -23592,6 +22943,10 @@ snapshots: dependencies: isexe: 2.0.0 + which@4.0.0: + dependencies: + isexe: 3.1.1 + wide-align@1.1.5: dependencies: string-width: 4.2.3 @@ -23606,25 +22961,25 @@ snapshots: dependencies: execa: 5.1.1 - winston-transport@4.7.0: + winston-transport@4.7.1: dependencies: - logform: 2.6.0 + logform: 2.6.1 readable-stream: 3.6.2 triple-beam: 1.4.1 - winston@3.13.0: + winston@3.14.2: dependencies: '@colors/colors': 1.6.0 '@dabh/diagnostics': 2.0.3 - async: 3.2.5 + async: 3.2.6 is-stream: 2.0.1 - logform: 2.6.0 + logform: 2.6.1 one-time: 1.0.0 readable-stream: 3.6.2 safe-stable-stringify: 2.4.3 stack-trace: 0.0.10 triple-beam: 1.4.1 - winston-transport: 4.7.0 + winston-transport: 4.7.1 word-wrap@1.2.5: {} @@ -23648,6 +23003,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} write-file-atomic@3.0.3: @@ -23667,9 +23028,9 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.14.2: {} + ws@8.17.1: {} - ws@8.17.0: {} + ws@8.18.0: {} ws@8.5.0: {} @@ -23686,8 +23047,6 @@ snapshots: xtend@4.0.2: {} - y18n@4.0.3: {} - y18n@5.0.8: {} yallist@2.1.2: {} @@ -23696,37 +23055,18 @@ snapshots: yallist@4.0.0: {} - yaml-eslint-parser@1.2.2: + yaml-eslint-parser@1.2.3: dependencies: eslint-visitor-keys: 3.4.3 lodash: 4.17.21 - yaml: 2.4.2 + yaml: 2.5.0 - yaml@2.4.2: {} - - yargs-parser@18.1.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 + yaml@2.5.0: {} yargs-parser@20.2.9: {} yargs-parser@21.1.1: {} - yargs@15.4.1: - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - yargs@16.2.0: dependencies: cliui: 7.0.4 @@ -23758,20 +23098,20 @@ snapshots: yocto-queue@0.1.0: {} - yocto-queue@1.0.0: {} + yocto-queue@1.1.1: {} - zip-stream@5.0.2: - dependencies: - archiver-utils: 4.0.1 - compress-commons: 5.0.3 - readable-stream: 3.6.2 + yoctocolors-cjs@2.1.2: {} - zod-validation-error@3.2.0(zod@3.23.6): + zip-stream@6.0.1: dependencies: - zod: 3.23.6 + archiver-utils: 5.0.2 + compress-commons: 6.0.2 + readable-stream: 4.5.2 - zod@3.22.4: {} + zod-validation-error@3.3.1(zod@3.23.8): + dependencies: + zod: 3.23.8 - zod@3.23.6: {} + zod@3.23.8: {} zwitch@2.0.4: {} diff --git a/samples/basic/another-remote-module/package.json b/samples/basic/another-remote-module/package.json index cabfc12ab..395d3022b 100644 --- a/samples/basic/another-remote-module/package.json +++ b/samples/basic/another-remote-module/package.json @@ -15,36 +15,38 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "cross-env": "7.0.3", "eslint": "8.57.0", "http-server": "14.1.1", - "netlify-cli": "17.23.1", - "nodemon": "3.1.0", - "typescript": "5.4.5", - "webpack": "5.91.0", + "netlify-cli": "17.33.4", + "nodemon": "3.1.4", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, "dependencies": { "@basic/shared": "workspace:*", "@basic/shell": "workspace:*", - "@react-aria/toast": "3.0.0-beta.10", - "@react-stately/toast": "3.0.0-beta.2", + "@react-aria/toast": "3.0.0-beta.12", + "@react-stately/toast": "3.0.0-beta.4", "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0", + "react-router-dom": "6.25.1", "useless-lib": "3.0.0" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/another-remote-module/src/dev/index.tsx b/samples/basic/another-remote-module/src/dev/index.tsx index c4d8dbd1d..5bbe40fc8 100644 --- a/samples/basic/another-remote-module/src/dev/index.tsx +++ b/samples/basic/another-remote-module/src/dev/index.tsx @@ -6,16 +6,14 @@ import { createRoot } from "react-dom/client"; import { register as registerModule } from "../register.tsx"; import { App } from "./App.tsx"; import { registerDev } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; // Create the shell runtime. -// Services, loggers and sessionAccessor could be reuse through a shared packages or faked when in isolation. +// Services and loggers could be reuse through a shared packages or faked when in isolation. const runtime = new FireflyRuntime({ - loggers: [new ConsoleLogger()], - sessionAccessor + loggers: [new ConsoleLogger()] }); -await registerLocalModules([registerShell(sessionManager), registerLayouts(), registerDev, registerModule], runtime); +await registerLocalModules([registerShell(), registerLayouts(), registerDev, registerModule], runtime); const root = createRoot(document.getElementById("root")!); diff --git a/samples/basic/another-remote-module/src/dev/session.ts b/samples/basic/another-remote-module/src/dev/session.ts deleted file mode 100644 index 7a6445a85..000000000 --- a/samples/basic/another-remote-module/src/dev/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session, SessionManager } from "@basic/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager() as SessionManager; - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/basic/host/package.json b/samples/basic/host/package.json index 800279742..a30d7fd08 100644 --- a/samples/basic/host/package.json +++ b/samples/basic/host/package.json @@ -17,22 +17,22 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "copyfiles": "2.4.1", "eslint": "8.57.0", "http-server": "14.1.1", - "netlify-cli": "17.23.1", - "nodemon": "3.1.0", - "typescript": "5.4.5", - "webpack": "5.91.0", + "netlify-cli": "17.33.4", + "nodemon": "3.1.4", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -40,14 +40,16 @@ "@basic/local-module": "workspace:*", "@basic/shared": "workspace:*", "@basic/shell": "workspace:*", - "@react-aria/toast": "3.0.0-beta.10", - "@react-stately/toast": "3.0.0-beta.2", + "@react-aria/toast": "3.0.0-beta.12", + "@react-stately/toast": "3.0.0-beta.4", "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0", + "react-router-dom": "6.25.1", "useless-lib": "^2.0.0" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/host/src/bootstrap.tsx b/samples/basic/host/src/bootstrap.tsx index ac78b9172..c12ed7f0f 100644 --- a/samples/basic/host/src/bootstrap.tsx +++ b/samples/basic/host/src/bootstrap.tsx @@ -7,7 +7,6 @@ import { createRoot } from "react-dom/client"; import { Remotes } from "../remotes.js"; import { App } from "./App.tsx"; import { registerHost } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -16,15 +15,14 @@ import { version } from "useless-lib"; console.log("[basic-sample] host:", version); const runtime = new FireflyRuntime({ - loggers: [new ConsoleLogger()], - sessionAccessor + loggers: [new ConsoleLogger()] }); const context: AppContext = { name: "Test app" }; -await registerLocalModules([registerShell(sessionManager, { host: "@basic/host" }), registerLayouts({ host: "@basic/host" }), registerHost, registerLocalModule], runtime, { context }); +await registerLocalModules([registerShell({ host: "@basic/host" }), registerLayouts({ host: "@basic/host" }), registerHost, registerLocalModule], runtime, { context }); await registerRemoteModules(Remotes, runtime, { context }); diff --git a/samples/basic/host/src/session.ts b/samples/basic/host/src/session.ts deleted file mode 100644 index 7a6445a85..000000000 --- a/samples/basic/host/src/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session, SessionManager } from "@basic/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager() as SessionManager; - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/basic/local-module/package.json b/samples/basic/local-module/package.json index 642be2dee..0b03646a0 100644 --- a/samples/basic/local-module/package.json +++ b/samples/basic/local-module/package.json @@ -26,28 +26,27 @@ "@squide/firefly": "*", "react": "*", "react-dom": "*", - "react-error-boundary": "*", "react-router-dom": "*" }, "devDependencies": { - "@react-aria/toast": "3.0.0-beta.10", - "@react-stately/toast": "3.0.0-beta.2", + "@react-aria/toast": "3.0.0-beta.12", + "@react-stately/toast": "3.0.0-beta.4", "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5", - "webpack": "5.91.0", + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -58,7 +57,9 @@ "@squide/firefly": "workspace:*", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0" + "react-router-dom": "6.25.1" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/local-module/src/dev/index.tsx b/samples/basic/local-module/src/dev/index.tsx index 02ada0bd9..a36aba50a 100644 --- a/samples/basic/local-module/src/dev/index.tsx +++ b/samples/basic/local-module/src/dev/index.tsx @@ -6,16 +6,14 @@ import { createRoot } from "react-dom/client"; import { registerLocalModule } from "../register.tsx"; import { App } from "./App.tsx"; import { registerDev } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; // Create the shell runtime. -// Services, loggers and sessionAccessor could be reuse through a shared packages or faked when in isolation. +// Services and loggers could be reuse through a shared packages or faked when in isolation. const runtime = new FireflyRuntime({ - loggers: [new ConsoleLogger()], - sessionAccessor + loggers: [new ConsoleLogger()] }); -await registerLocalModules([registerShell(sessionManager), registerLayouts(), registerDev, registerLocalModule], runtime); +await registerLocalModules([registerShell(), registerLayouts(), registerDev, registerLocalModule], runtime); const root = createRoot(document.getElementById("root")!); diff --git a/samples/basic/local-module/src/dev/session.ts b/samples/basic/local-module/src/dev/session.ts deleted file mode 100644 index 7a6445a85..000000000 --- a/samples/basic/local-module/src/dev/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session, SessionManager } from "@basic/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager() as SessionManager; - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/basic/remote-module/package.json b/samples/basic/remote-module/package.json index 148165256..6c3cd1e3f 100644 --- a/samples/basic/remote-module/package.json +++ b/samples/basic/remote-module/package.json @@ -15,36 +15,38 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "cross-env": "7.0.3", "eslint": "8.57.0", "http-server": "14.1.1", - "netlify-cli": "17.23.1", - "nodemon": "3.1.0", - "typescript": "5.4.5", - "webpack": "5.91.0", + "netlify-cli": "17.33.4", + "nodemon": "3.1.4", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, "dependencies": { "@basic/shared": "workspace:*", "@basic/shell": "workspace:*", - "@react-aria/toast": "3.0.0-beta.10", - "@react-stately/toast": "3.0.0-beta.2", + "@react-aria/toast": "3.0.0-beta.12", + "@react-stately/toast": "3.0.0-beta.4", "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0", + "react-router-dom": "6.25.1", "useless-lib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/remote-module/src/dev/index.tsx b/samples/basic/remote-module/src/dev/index.tsx index 971039c9d..bf9815042 100644 --- a/samples/basic/remote-module/src/dev/index.tsx +++ b/samples/basic/remote-module/src/dev/index.tsx @@ -6,18 +6,16 @@ import { createRoot } from "react-dom/client"; import { register as registerModule } from "../register.tsx"; import { App } from "./App.tsx"; import { registerDev } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; // Create the shell runtime. -// Services, loggers and sessionAccessor could be reuse through a shared packages or faked when in isolation. +// Services and loggers could be reuse through a shared packages or faked when in isolation. const runtime = new FireflyRuntime({ - loggers: [new ConsoleLogger()], - sessionAccessor + loggers: [new ConsoleLogger()] }); // Registering the remote module as a static module because the "register" function // is local when developing in isolation. -await registerLocalModules([registerShell(sessionManager), registerLayouts(), registerDev, registerModule], runtime); +await registerLocalModules([registerShell(), registerLayouts(), registerDev, registerModule], runtime); const root = createRoot(document.getElementById("root")!); diff --git a/samples/basic/remote-module/src/dev/session.ts b/samples/basic/remote-module/src/dev/session.ts deleted file mode 100644 index 7a6445a85..000000000 --- a/samples/basic/remote-module/src/dev/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session, SessionManager } from "@basic/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager() as SessionManager; - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/basic/shared/package.json b/samples/basic/shared/package.json index e58042645..2e62cadec 100644 --- a/samples/basic/shared/package.json +++ b/samples/basic/shared/package.json @@ -22,19 +22,21 @@ "@squide/firefly": "*", "react": "*", "react-dom": "*", - "react-error-boundary": "*", "react-router-dom": "*" }, "devDependencies": { "@squide/firefly": "workspace:*", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/shared/src/layouts/FederatedTabsLayout.tsx b/samples/basic/shared/src/layouts/FederatedTabsLayout.tsx index b17602edd..5bb7b836d 100644 --- a/samples/basic/shared/src/layouts/FederatedTabsLayout.tsx +++ b/samples/basic/shared/src/layouts/FederatedTabsLayout.tsx @@ -1,4 +1,4 @@ -import { useNavigationItems, useRenderedNavigationItems, type NavigationLinkRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; +import { useRenderedNavigationItems, useRuntimeNavigationItems, type NavigationLinkRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; import { Suspense } from "react"; import { Link, Outlet } from "react-router-dom"; @@ -27,7 +27,7 @@ const renderSection: RenderSectionFunction = elements => { }; export function FederatedTabsLayout({ host }: FederatedTabsLayoutProps) { - const navigationItems = useNavigationItems({ menuId: "/federated-tabs" }); + const navigationItems = useRuntimeNavigationItems({ menuId: "/federated-tabs" }); const renderedTabs = useRenderedNavigationItems(navigationItems, renderItem, renderSection); return ( diff --git a/samples/basic/shared/src/session.ts b/samples/basic/shared/src/session.ts index a433b0c30..d9ff1b03c 100644 --- a/samples/basic/shared/src/session.ts +++ b/samples/basic/shared/src/session.ts @@ -1,3 +1,5 @@ +import { createContext, useContext } from "react"; + export interface Session { user: { name: string; @@ -6,6 +8,24 @@ export interface Session { export interface SessionManager { setSession: (session: Session) => void; - getSession: () => Session; + getSession: () => Session | undefined; clearSession: () => void; } + +export const SessionManagerContext = createContext(undefined); + +export function useSessionManager() { + return useContext(SessionManagerContext); +} + +export function useSession() { + const sessionManager = useSessionManager(); + + return sessionManager?.getSession(); +} + +export function useIsAuthenticated() { + const sessionManager = useSessionManager(); + + return !!sessionManager?.getSession(); +} diff --git a/samples/basic/shell/package.json b/samples/basic/shell/package.json index 85515edf0..30614044e 100644 --- a/samples/basic/shell/package.json +++ b/samples/basic/shell/package.json @@ -22,23 +22,27 @@ "@basic/shared": "*", "@react-aria/toast": "*", "@react-stately/toast": "*", + "@squide/fakes": "*", "@squide/firefly": "*", "react": "*", "react-dom": "*", - "react-error-boundary": "*", "react-router-dom": "*" }, "devDependencies": { "@basic/shared": "workspace:*", + "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/basic/shell/src/AppRouter.tsx b/samples/basic/shell/src/AppRouter.tsx index 50e39629a..c27867542 100644 --- a/samples/basic/shell/src/AppRouter.tsx +++ b/samples/basic/shell/src/AppRouter.tsx @@ -1,17 +1,13 @@ -import { useToastListener } from "@basic/shared"; -import { AppRouter as FireflyAppRouter } from "@squide/firefly"; +import { SessionManagerContext, useToastListener } from "@basic/shared"; +import { AppRouter as FireflyAppRouter, useIsBootstrapping } from "@squide/firefly"; import { useCallback } from "react"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import { AppRouterErrorBoundary } from "./AppRouterErrorBoundary.tsx"; +import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom"; +import { Loading } from "./Loading.tsx"; +import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; import { ToastContainer, useToastContainer } from "./toast.tsx"; +import { useSessionManagerInstance } from "./useSessionManagerInstance.ts"; -function Loading() { - return ( -
                                      Loading...
                                      - ); -} - -export function AppRouter() { +function BootstrappingRoute() { const { toastState, addToast } = useToastContainer(); const handleShowToast = useCallback((message: string) => { @@ -20,17 +16,43 @@ export function AppRouter() { useToastListener(handleShowToast); + const sessionManager = useSessionManagerInstance(); + + if (useIsBootstrapping()) { + return ; + } + + return ( + + + + + + ); +} + +export function AppRouter() { return ( - - } - errorElement={} - waitForMsw={false} - > - {(routes, providerProps) => ( - - )} - - + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + errorElement: , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + ); } diff --git a/samples/basic/shell/src/AppRouterErrorBoundary.tsx b/samples/basic/shell/src/AppRouterErrorBoundary.tsx deleted file mode 100644 index 49d9babaa..000000000 --- a/samples/basic/shell/src/AppRouterErrorBoundary.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useLogger } from "@squide/firefly"; -import { useCallback, useEffect } from "react"; -import { useNavigate } from "react-router-dom"; - -export function AppRouterErrorBoundary({ error }: { error?: Error }) { - const logger = useLogger(); - const navigate = useNavigate(); - - const handleReloadButtonClick = useCallback(() => { - navigate(0); - }, [navigate]); - - useEffect(() => { - logger.error("[shell] An unmanaged error occurred while bootstrapping the application", error); - }, [error, logger]); - - return ( -
                                      -

                                      Unmanaged error

                                      -

                                      An unmanaged error occurred while bootstrapping the application.

                                      -

                                      👉 {error?.message}

                                      -

                                      {error?.stack}

                                      -
                                      - -
                                      - ); -} diff --git a/samples/basic/shell/src/AuthenticatedLayout.tsx b/samples/basic/shell/src/AuthenticatedLayout.tsx index c21c98633..f17b50565 100644 --- a/samples/basic/shell/src/AuthenticatedLayout.tsx +++ b/samples/basic/shell/src/AuthenticatedLayout.tsx @@ -1,15 +1,16 @@ -import { useApplicationEventBusListener, type Session, type SessionManager } from "@basic/shared"; -import { isNavigationLink, useNavigationItems, useRenderedNavigationItems, useSession, type NavigationLinkRenderProps, type NavigationSectionRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; +import { useApplicationEventBusListener, useSessionManager } from "@basic/shared"; +import { isNavigationLink, useNavigationItems, useRenderedNavigationItems, type NavigationLinkRenderProps, type NavigationSectionRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; import { Suspense, useCallback, type MouseEvent, type ReactNode } from "react"; import { Link, Outlet, useNavigate } from "react-router-dom"; +import { Loading } from "./Loading.tsx"; -type RenderLinkItemFunction = (item: NavigationLinkRenderProps, index: number, level: number) => ReactNode; +type RenderLinkItemFunction = (item: NavigationLinkRenderProps, key: string) => ReactNode; -type RenderSectionItemFunction = (item: NavigationSectionRenderProps, index: number, level: number) => ReactNode; +type RenderSectionItemFunction = (item: NavigationSectionRenderProps, key: string) => ReactNode; -const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps: { highlight, ...additionalProps } }, index, level) => { +const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps: { highlight, ...additionalProps } }, key) => { return ( -
                                    • +
                                    • {label} @@ -17,9 +18,9 @@ const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalPr ); }; -const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, level) => { +const renderSectionItem: RenderSectionItemFunction = ({ label, section }, key) => { return ( -
                                    • +
                                    • {label}
                                      ({section}) @@ -28,24 +29,21 @@ const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, ); }; -const renderItem: RenderItemFunction = (item, index, level) => { - return isNavigationLink(item) ? renderLinkItem(item, index, level) : renderSectionItem(item, index, level); +const renderItem: RenderItemFunction = (item, key) => { + return isNavigationLink(item) ? renderLinkItem(item, key) : renderSectionItem(item, key); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
                                        +
                                          {elements}
                                        ); }; -export interface AuthenticatedLayoutProps { - sessionManager: SessionManager; -} - -export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps) { - const session = useSession() as Session; +export function AuthenticatedLayout() { + const sessionManager = useSessionManager(); + const session = sessionManager?.getSession(); const navigate = useNavigate(); @@ -58,7 +56,7 @@ export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps const handleDisconnect = useCallback((event: MouseEvent) => { event.preventDefault(); - sessionManager.clearSession(); + sessionManager?.clearSession(); navigate("/logout"); }, [navigate, sessionManager]); @@ -79,7 +77,7 @@ export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps
                          - Loading...
          }> + }> diff --git a/samples/basic/shell/src/AuthenticationBoundary.tsx b/samples/basic/shell/src/AuthenticationBoundary.tsx index 6eddf0531..aa65dcd25 100644 --- a/samples/basic/shell/src/AuthenticationBoundary.tsx +++ b/samples/basic/shell/src/AuthenticationBoundary.tsx @@ -1,8 +1,18 @@ -import { useIsAuthenticated } from "@squide/firefly"; +import { useIsAuthenticated } from "@basic/shared"; +import { useLogger } from "@squide/firefly"; import { Navigate, Outlet } from "react-router-dom"; export function AuthenticationBoundary() { - return useIsAuthenticated() ? : ; + const logger = useLogger(); + const isAuthenticated = useIsAuthenticated(); + + if (isAuthenticated) { + return ; + } + + logger.debug("[shell] The user is not authenticated, redirecting to the login page."); + + return ; } /** @alias */ diff --git a/samples/basic/shell/src/Loading.tsx b/samples/basic/shell/src/Loading.tsx new file mode 100644 index 000000000..16a3c3731 --- /dev/null +++ b/samples/basic/shell/src/Loading.tsx @@ -0,0 +1,5 @@ +export function Loading() { + return ( +
          Loading...
          + ); +} diff --git a/samples/basic/shell/src/LoginPage.tsx b/samples/basic/shell/src/LoginPage.tsx index c5b8ccbfe..5a6842e7d 100644 --- a/samples/basic/shell/src/LoginPage.tsx +++ b/samples/basic/shell/src/LoginPage.tsx @@ -1,14 +1,14 @@ -import type { SessionManager } from "@basic/shared"; -import { useIsAuthenticated } from "@squide/firefly"; +import { useIsAuthenticated, useSessionManager } from "@basic/shared"; import { useCallback, useState, type ChangeEvent, type MouseEvent } from "react"; import { Navigate, useNavigate } from "react-router-dom"; export interface LoginProps { - sessionManager: SessionManager; host?: string; } -export function LoginPage({ sessionManager, host }: LoginProps) { +export function LoginPage({ host }: LoginProps) { + const sessionManager = useSessionManager(); + const [username, setUserName] = useState(""); const [password, setPassword] = useState(""); @@ -18,7 +18,7 @@ export function LoginPage({ sessionManager, host }: LoginProps) { event.preventDefault(); if (username === "temp" && password === "temp") { - sessionManager.setSession({ + sessionManager?.setSession({ user: { name: username } diff --git a/samples/basic/shell/src/register.tsx b/samples/basic/shell/src/register.tsx index 6281dfb48..383f7642d 100644 --- a/samples/basic/shell/src/register.tsx +++ b/samples/basic/shell/src/register.tsx @@ -1,6 +1,4 @@ -import type { SessionManager } from "@basic/shared"; import { ManagedRoutes, type FireflyRuntime, type ModuleRegisterFunction } from "@squide/firefly"; -import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; import { RootLayout } from "./RootLayout.tsx"; export interface RegisterShellOptions { @@ -8,50 +6,43 @@ export interface RegisterShellOptions { host?: string; } -function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, host?: string) { +function registerRoutes(runtime: FireflyRuntime, host?: string) { runtime.registerRoute({ - // Pathless route to declare a root layout. + // Pathless route to declare a root layout and a root error boundary. $visibility: "public", - element: , + $name: "root-layout", + element: + }, { + hoist: true + }); + + runtime.registerRoute({ + // Pathless route to declare an authenticated boundary. + lazy: () => import("./AuthenticationBoundary.tsx"), children: [ { - // Pathless route to declare a root error boundary. - // Public pages like the login and logout pages will be rendered under this pathless route. - $visibility: "public", - $name: "root-error-boundary", - errorElement: , + // Pathless route to declare an authenticated layout. + lazy: async () => { + const { AuthenticatedLayout } = await import("./AuthenticatedLayout.tsx"); + + return { + element: + }; + }, children: [ { - // Pathless route to declare an authenticated boundary. - lazy: () => import("./AuthenticationBoundary.tsx"), + // Pathless route to declare an error boundary inside the layout instead of outside. + // It's quite useful to prevent losing the layout when an unmanaged error occurs. + lazy: () => import("./ModuleErrorBoundary.tsx"), children: [ - { - // Pathless route to declare an authenticated layout. - lazy: async () => { - const { AuthenticatedLayout } = await import("./AuthenticatedLayout.tsx"); - - return { - element: - }; - }, - children: [ - { - // Pathless route to declare an error boundary inside the layout instead of outside. - // It's quite useful to prevent losing the layout when an unmanaged error occurs. - lazy: () => import("./ModuleErrorBoundary.tsx"), - children: [ - ManagedRoutes - ] - } - ] - } + ManagedRoutes ] } ] } ] }, { - hoist: true + parentName: "root-layout" }); runtime.registerRoute({ @@ -61,11 +52,11 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, const { LoginPage } = await import("./LoginPage.tsx"); return { - element: + element: }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -79,7 +70,7 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -93,13 +84,13 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); } -export function registerShell(sessionManager: SessionManager, { host }: RegisterShellOptions = {}) { +export function registerShell({ host }: RegisterShellOptions = {}) { const register: ModuleRegisterFunction = runtime => { - return registerRoutes(runtime, sessionManager, host); + return registerRoutes(runtime, host); }; return register; diff --git a/samples/basic/shell/src/useSessionManagerInstance.ts b/samples/basic/shell/src/useSessionManagerInstance.ts new file mode 100644 index 000000000..109a71e49 --- /dev/null +++ b/samples/basic/shell/src/useSessionManagerInstance.ts @@ -0,0 +1,23 @@ +import type { Session, SessionManager } from "@basic/shared"; +import { LocalStorageSessionManager } from "@squide/fakes"; +import { useMemo } from "react"; + +class MySessionManager implements SessionManager { + readonly #localStorageSessionManager = new LocalStorageSessionManager(); + + setSession(session: Session) { + this.#localStorageSessionManager.setSession(session); + } + + getSession() { + return this.#localStorageSessionManager.getSession(); + } + + clearSession() { + this.#localStorageSessionManager.clearSession(); + } +} + +export function useSessionManagerInstance() { + return useMemo(() => new MySessionManager(), []); +} diff --git a/samples/endpoints/host/mocks/characterHandlers.ts b/samples/endpoints/host/mocks/characterHandlers.ts index ae64a6e73..535e5eb73 100644 --- a/samples/endpoints/host/mocks/characterHandlers.ts +++ b/samples/endpoints/host/mocks/characterHandlers.ts @@ -1,13 +1,13 @@ /* eslint-disable max-len */ import { HttpResponse, http, type HttpHandler } from "msw"; -import { readonlySessionLocalStorage } from "./session.ts"; +import { sessionAccessor } from "./session.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. export const characterHandlers: HttpHandler[] = [ http.get("/api/character/1,2", async () => { - const session = readonlySessionLocalStorage.getSession(); + const session = sessionAccessor.getSession(); if (!session) { return new HttpResponse(null, { diff --git a/samples/endpoints/host/mocks/session.ts b/samples/endpoints/host/mocks/session.ts index ffe98a2da..28b4b3e13 100644 --- a/samples/endpoints/host/mocks/session.ts +++ b/samples/endpoints/host/mocks/session.ts @@ -1,5 +1,5 @@ -import { FakeSessionKey } from "@endpoints/shared"; -import { ReadonlySessionLocalStorage } from "@squide/fakes"; +import { FakeSessionStorageKey } from "@endpoints/shared"; +import { LocalStorageSessionAccessor } from "@squide/fakes"; export interface Session { userId: number; @@ -7,4 +7,4 @@ export interface Session { preferredLanguage: string; } -export const readonlySessionLocalStorage = new ReadonlySessionLocalStorage({ key: FakeSessionKey }); +export const sessionAccessor = new LocalStorageSessionAccessor({ key: FakeSessionStorageKey }); diff --git a/samples/endpoints/host/package.json b/samples/endpoints/host/package.json index 136c636a2..14e943514 100644 --- a/samples/endpoints/host/package.json +++ b/samples/endpoints/host/package.json @@ -1,63 +1,65 @@ { - "name": "@endpoints/host", - "author": "Workleap", - "version": "0.0.0", - "description": "Host application to showcase Squide.", - "private": true, - "license": "Apache-2.0", - "type": "module", - "scripts": { - "dev": "cross-env USE_MSW=true nodemon", - "build": "cross-env USE_MSW=true pnpm build:webpack && pnpm build:copy-redirects && pnpm build:copy-public-files", - "build:webpack": "webpack --config webpack.build.js", - "build:copy-redirects": "copyfiles _redirects dist", - "build:copy-public-files": "copyfiles -u 1 public/favicon.png public/mockServiceWorker.js dist", - "serve-build": "pnpm http-server dist -p 8080 -P http://localhost:8080? -c-1", - "deploy": "netlify deploy --dir=samples/endpoints/host/dist --site=4bde6b8b-cea6-487f-913b-acec9332eb2f --prod" - }, - "devDependencies": { - "@squide/fakes": "workspace:*", - "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@tanstack/react-query": "5.32.0", - "@types/react": "18.3.1", - "@types/react-dom": "18.3.0", - "@workleap/browserslist-config": "2.0.1", - "@workleap/eslint-plugin": "3.2.2", - "@workleap/swc-configs": "2.2.3", - "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", - "copyfiles": "2.4.1", - "cross-env": "7.0.3", - "eslint": "8.57.0", - "http-server": "14.1.1", - "netlify-cli": "17.23.1", - "nodemon": "3.1.0", - "typescript": "5.4.5", - "webpack": "5.91.0", - "webpack-cli": "5.1.4", - "webpack-dev-server": "5.0.4" - }, - "dependencies": { - "@endpoints/i18next": "workspace:*", - "@endpoints/layouts": "workspace:*", - "@endpoints/local-module": "workspace:*", - "@endpoints/shared": "workspace:*", - "@endpoints/shell": "workspace:*", - "@squide/fakes": "workspace:*", - "@squide/firefly": "workspace:*", - "@squide/i18next": "workspace:*", - "i18next": "23.11.3", - "i18next-browser-languagedetector": "7.2.1", - "msw": "2.2.14", - "react": "18.3.1", - "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-i18next": "14.1.1", - "react-router-dom": "6.23.0" - }, - "msw": { - "workerDirectory": "public" - } + "name": "@endpoints/host", + "author": "Workleap", + "version": "0.0.0", + "description": "Host application to showcase Squide.", + "private": true, + "license": "Apache-2.0", + "type": "module", + "scripts": { + "dev": "cross-env USE_MSW=true nodemon", + "build": "cross-env USE_MSW=true pnpm build:webpack && pnpm build:copy-redirects && pnpm build:copy-public-files", + "build:webpack": "webpack --config webpack.build.js", + "build:copy-redirects": "copyfiles _redirects dist", + "build:copy-public-files": "copyfiles -u 1 public/favicon.png public/mockServiceWorker.js dist", + "serve-build": "pnpm http-server dist -p 8080 -P http://localhost:8080? -c-1", + "deploy": "netlify deploy --dir=samples/endpoints/host/dist --site=4bde6b8b-cea6-487f-913b-acec9332eb2f --prod" + }, + "devDependencies": { + "@squide/firefly-webpack-configs": "workspace:*", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@tanstack/react-query": "5.51.9", + "@types/react": "18.3.3", + "@types/react-dom": "18.3.0", + "@workleap/browserslist-config": "2.0.1", + "@workleap/eslint-plugin": "3.2.2", + "@workleap/swc-configs": "2.2.3", + "@workleap/typescript-configs": "3.0.2", + "browserslist": "4.23.2", + "copyfiles": "2.4.1", + "cross-env": "7.0.3", + "eslint": "8.57.0", + "http-server": "14.1.1", + "netlify-cli": "17.33.4", + "nodemon": "3.1.4", + "typescript": "5.5.3", + "webpack": "5.93.0", + "webpack-cli": "5.1.4", + "webpack-dev-server": "5.0.4" + }, + "dependencies": { + "@endpoints/i18next": "workspace:*", + "@endpoints/layouts": "workspace:*", + "@endpoints/local-module": "workspace:*", + "@endpoints/shared": "workspace:*", + "@endpoints/shell": "workspace:*", + "@squide/fakes": "workspace:*", + "@squide/firefly": "workspace:*", + "@squide/i18next": "workspace:*", + "i18next": "23.12.1", + "i18next-browser-languagedetector": "8.0.0", + "msw": "2.3.1", + "react": "18.3.1", + "react-dom": "18.3.1", + "react-error-boundary": "4.0.13", + "react-i18next": "15.0.0", + "react-router-dom": "6.25.1" + }, + "msw": { + "workerDirectory": "public" + }, + "engines": { + "node": ">=20.0.0" + } } diff --git a/samples/endpoints/host/src/App.tsx b/samples/endpoints/host/src/App.tsx index 5a50fafe6..81c1dae08 100644 --- a/samples/endpoints/host/src/App.tsx +++ b/samples/endpoints/host/src/App.tsx @@ -1,7 +1,7 @@ import { LoggerTelemetryService } from "@endpoints/shared"; import { AppRouter } from "@endpoints/shell"; import { useLogger } from "@squide/firefly"; -import { sessionManager } from "./session.ts"; +import { QueryProvider } from "./QueryProvider.tsx"; export function App() { const logger = useLogger(); @@ -9,10 +9,11 @@ export function App() { const telemetryService = new LoggerTelemetryService(logger); return ( - + + + ); } diff --git a/samples/endpoints/host/src/QueryProvider.tsx b/samples/endpoints/host/src/QueryProvider.tsx new file mode 100644 index 000000000..e630fb1c1 --- /dev/null +++ b/samples/endpoints/host/src/QueryProvider.tsx @@ -0,0 +1,27 @@ +import { isApiError } from "@endpoints/shared"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import type { PropsWithChildren } from "react"; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + retry: (failureCount, error) => { + if (isApiError(error) && (error.status === 401 || error.status === 403)) { + return false; + } + + return failureCount <= 2; + }, + refetchInterval: 5 * 1000 + } + } +}); + +export function QueryProvider({ children }: PropsWithChildren) { + return ( + + {children} + + ); +} diff --git a/samples/endpoints/host/src/bootstrap.tsx b/samples/endpoints/host/src/bootstrap.tsx index 9119c2572..96b84e9ff 100644 --- a/samples/endpoints/host/src/bootstrap.tsx +++ b/samples/endpoints/host/src/bootstrap.tsx @@ -1,24 +1,22 @@ import { createI18NextPlugin } from "@endpoints/i18next"; import { registerLocalModule } from "@endpoints/local-module"; import { registerShell } from "@endpoints/shell"; -import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, registerRemoteModules, setMswAsStarted } from "@squide/firefly"; +import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, registerRemoteModules, setMswAsReady } from "@squide/firefly"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { Remotes } from "../remotes.js"; import { App } from "./App.tsx"; import { registerHost } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; const consoleLogger = new ConsoleLogger(); const runtime = new FireflyRuntime({ useMsw: !!process.env.USE_MSW, - plugins: [createI18NextPlugin()], - loggers: [consoleLogger], - sessionAccessor + plugins: [x => createI18NextPlugin(x)], + loggers: [consoleLogger] }); -await registerLocalModules([registerShell(sessionManager, { host: "@endpoints/host" }), registerHost, registerLocalModule], runtime); +await registerLocalModules([registerShell({ host: "@endpoints/host" }), registerHost, registerLocalModule], runtime); await registerRemoteModules(Remotes, runtime); @@ -31,7 +29,7 @@ if (runtime.isMswEnabled) { startMsw(runtime.requestHandlers) .then(() => { // Indicate to resources that are dependent on MSW that the service has been started. - setMswAsStarted(); + setMswAsReady(); }) .catch((error: unknown) => { consoleLogger.debug("[host-app] An error occured while starting MSW.", error); diff --git a/samples/endpoints/host/src/register.tsx b/samples/endpoints/host/src/register.tsx index c2ee37533..742a96e27 100644 --- a/samples/endpoints/host/src/register.tsx +++ b/samples/endpoints/host/src/register.tsx @@ -1,30 +1,15 @@ import type { FireflyRuntime, ModuleRegisterFunction } from "@squide/firefly"; import { I18nextNavigationItemLabel } from "@squide/i18next"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { i18n } from "i18next"; -import type { ReactNode } from "react"; +import type { PropsWithChildren } from "react"; +import { QueryProvider } from "./QueryProvider.tsx"; import { initI18next } from "./i18next.ts"; -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, - retry: failureCount => { - return failureCount <= 2; - } - } - } -}); - -interface ProvidersProps { - children: ReactNode; -} - -function Providers({ children }: ProvidersProps) { +function Providers({ children }: PropsWithChildren) { return ( - + {children} - + ); } @@ -41,6 +26,7 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n) { }); runtime.registerNavigationItem({ + $key: "home", $label: , $priority: 999, to: "/" diff --git a/samples/endpoints/host/src/session.ts b/samples/endpoints/host/src/session.ts deleted file mode 100644 index 454ede829..000000000 --- a/samples/endpoints/host/src/session.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Session, SessionManager } from "@endpoints/shared"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export class InMemorySessionManager implements SessionManager { - #session?: Session; - - setSession(session: Session) { - this.#session = session; - } - - getSession() { - return this.#session; - } - - clearSession() { - this.#session = undefined; - } -} - -export const sessionManager = new InMemorySessionManager(); - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/endpoints/i18next/package.json b/samples/endpoints/i18next/package.json index ee7aa7582..6f4b8bb9d 100644 --- a/samples/endpoints/i18next/package.json +++ b/samples/endpoints/i18next/package.json @@ -33,8 +33,11 @@ "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/i18next/src/createI18nextPlugin.ts b/samples/endpoints/i18next/src/createI18nextPlugin.ts index c7d0d11f0..60ca5ec8e 100644 --- a/samples/endpoints/i18next/src/createI18nextPlugin.ts +++ b/samples/endpoints/i18next/src/createI18nextPlugin.ts @@ -1,8 +1,9 @@ import type { LanguageKey } from "@endpoints/shared"; +import type { Runtime } from "@squide/core"; import { i18nextPlugin, type i18nextPluginOptions } from "@squide/i18next"; -export function createI18NextPlugin(options?: i18nextPluginOptions) { - const plugin = new i18nextPlugin(["en-US", "fr-CA"], "en-US", "language", options); +export function createI18NextPlugin(runtime: Runtime, options?: i18nextPluginOptions) { + const plugin = new i18nextPlugin(["en-US", "fr-CA"], "en-US", "language", options, runtime); // By default, detect user default language for anonymous pages. // If the user is authenticated, the language will be changed for the persisted user diff --git a/samples/endpoints/layouts/package.json b/samples/endpoints/layouts/package.json index 425467204..ec26faada 100644 --- a/samples/endpoints/layouts/package.json +++ b/samples/endpoints/layouts/package.json @@ -35,14 +35,17 @@ "@endpoints/shared": "workspace:*", "@squide/firefly": "workspace:*", "@squide/i18next": "workspace:*", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/layouts/src/FederatedTabsLayout.tsx b/samples/endpoints/layouts/src/FederatedTabsLayout.tsx index 03f89ff8a..bd354f212 100644 --- a/samples/endpoints/layouts/src/FederatedTabsLayout.tsx +++ b/samples/endpoints/layouts/src/FederatedTabsLayout.tsx @@ -1,4 +1,4 @@ -import { useNavigationItems, useRenderedNavigationItems, type NavigationLinkRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; +import { useRenderedNavigationItems, useRuntimeNavigationItems, type NavigationLinkRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; import { useI18nextInstance } from "@squide/i18next"; import { Suspense, useCallback, type MouseEvent } from "react"; import { ErrorBoundary } from "react-error-boundary"; @@ -59,7 +59,7 @@ export function FederatedTabsLayout({ host }: FederatedTabsLayoutProps) { const i18nextInstance = useI18nextInstance(i18NextInstanceKey); const { t } = useTranslation("FederatedTabsLayout", { i18n: i18nextInstance }); - const navigationItems = useNavigationItems({ menuId: "/federated-tabs" }); + const navigationItems = useRuntimeNavigationItems({ menuId: "/federated-tabs" }); const renderedTabs = useRenderedNavigationItems(navigationItems, renderItem, renderSection); return ( diff --git a/samples/endpoints/layouts/src/registerLayouts.tsx b/samples/endpoints/layouts/src/registerLayouts.tsx index 01c5895ba..4b417d40e 100644 --- a/samples/endpoints/layouts/src/registerLayouts.tsx +++ b/samples/endpoints/layouts/src/registerLayouts.tsx @@ -20,6 +20,7 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n, host?: s }); runtime.registerNavigationItem({ + $key: "federated-tabs", $label: , to: "/federated-tabs" }); diff --git a/samples/endpoints/local-module/mocks/characterHandlers.ts b/samples/endpoints/local-module/mocks/characterHandlers.ts index fbec22065..f82a221a1 100644 --- a/samples/endpoints/local-module/mocks/characterHandlers.ts +++ b/samples/endpoints/local-module/mocks/characterHandlers.ts @@ -1,7 +1,7 @@ /* eslint-disable max-len */ import { HttpResponse, http, type HttpHandler } from "msw"; -import { readonlySessionLocalStorage } from "./session.ts"; +import { sessionAccessor } from "./session.ts"; function simulateDelay(delay: number) { return new Promise(resolve => { @@ -17,7 +17,7 @@ export const characterHandlers: HttpHandler[] = [ http.get("/api/character/1,2", async () => { await simulateDelay(2000); - const session = readonlySessionLocalStorage.getSession(); + const session = sessionAccessor.getSession(); if (!session) { return new HttpResponse(null, { diff --git a/samples/endpoints/local-module/mocks/featureAHandlers.ts b/samples/endpoints/local-module/mocks/featureAHandlers.ts new file mode 100644 index 000000000..af2093e67 --- /dev/null +++ b/samples/endpoints/local-module/mocks/featureAHandlers.ts @@ -0,0 +1,35 @@ +import { HttpResponse, http, type HttpHandler } from "msw"; +import { featureFlagsAccessor } from "./featureFlags.ts"; +import { sessionAccessor } from "./session.ts"; + +export const featureAHandlers: HttpHandler[] = [ + http.get("/api/feature-a", async () => { + const session = sessionAccessor.getSession(); + + if (!session) { + return new HttpResponse(null, { + status: 401 + }); + } + + const featureFlags = featureFlagsAccessor.getFeatureFlags(); + + if (!featureFlags.featureA) { + return new HttpResponse(null, { + status: 403 + }); + } + + const isEn = session.preferredLanguage === "en-US"; + + if (isEn) { + return HttpResponse.json({ + message: "This page is only available if the featureA flag is active." + }); + } else { + return HttpResponse.json({ + message: "Cette page est uniquement disponible si la fonctionnalité featureA est activé." + }); + } + }) +]; diff --git a/samples/endpoints/local-module/mocks/featureFlags.ts b/samples/endpoints/local-module/mocks/featureFlags.ts new file mode 100644 index 000000000..375472705 --- /dev/null +++ b/samples/endpoints/local-module/mocks/featureFlags.ts @@ -0,0 +1,3 @@ +import { LocalStorageFeatureFlagsAccessor } from "@endpoints/shared"; + +export const featureFlagsAccessor = new LocalStorageFeatureFlagsAccessor(); diff --git a/samples/endpoints/local-module/mocks/handlers.ts b/samples/endpoints/local-module/mocks/handlers.ts index 711988e41..4295907df 100644 --- a/samples/endpoints/local-module/mocks/handlers.ts +++ b/samples/endpoints/local-module/mocks/handlers.ts @@ -1,6 +1,7 @@ import type { HttpHandler } from "msw"; import { characterHandlers } from "./characterHandlers.ts"; +import { featureAHandlers } from "./featureAHandlers.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. -export const requestHandlers: HttpHandler[] = characterHandlers; +export const requestHandlers: HttpHandler[] = [...characterHandlers, ...featureAHandlers]; diff --git a/samples/endpoints/local-module/mocks/session.ts b/samples/endpoints/local-module/mocks/session.ts index ffe98a2da..28b4b3e13 100644 --- a/samples/endpoints/local-module/mocks/session.ts +++ b/samples/endpoints/local-module/mocks/session.ts @@ -1,5 +1,5 @@ -import { FakeSessionKey } from "@endpoints/shared"; -import { ReadonlySessionLocalStorage } from "@squide/fakes"; +import { FakeSessionStorageKey } from "@endpoints/shared"; +import { LocalStorageSessionAccessor } from "@squide/fakes"; export interface Session { userId: number; @@ -7,4 +7,4 @@ export interface Session { preferredLanguage: string; } -export const readonlySessionLocalStorage = new ReadonlySessionLocalStorage({ key: FakeSessionKey }); +export const sessionAccessor = new LocalStorageSessionAccessor({ key: FakeSessionStorageKey }); diff --git a/samples/endpoints/local-module/package.json b/samples/endpoints/local-module/package.json index 98aa80166..c76bcfa8d 100644 --- a/samples/endpoints/local-module/package.json +++ b/samples/endpoints/local-module/package.json @@ -23,9 +23,8 @@ "peerDependencies": { "@endpoints/shared": "*", "@endpoints/shell": "*", - "@squide/fakes": "*", "@squide/firefly": "*", - "@tanstack/react-query": "rc", + "@tanstack/react-query": "5.32.0", "msw": "*", "react": "*", "react-dom": "*", @@ -34,24 +33,24 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@tanstack/react-query-devtools": "5.32.0", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@tanstack/react-query-devtools": "5.51.9", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "cross-env": "7.0.3", "eslint": "8.57.0", "http-server": "14.1.1", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5", - "webpack": "5.91.0", + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -63,17 +62,20 @@ "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "@squide/i18next": "workspace:*", - "@tanstack/react-query": "5.32.0", - "i18next": "23.11.3", - "i18next-browser-languagedetector": "7.2.1", - "msw": "2.2.14", + "@tanstack/react-query": "5.51.9", + "i18next": "23.12.1", + "i18next-browser-languagedetector": "8.0.0", + "msw": "2.3.1", "react": "18.3.1", "react-dom": "18.3.1", "react-error-boundary": "4.0.13", - "react-i18next": "14.1.1", - "react-router-dom": "6.23.0" + "react-i18next": "15.0.0", + "react-router-dom": "6.25.1" }, "msw": { "workerDirectory": "public" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/local-module/src/FeatureAPage.tsx b/samples/endpoints/local-module/src/FeatureAPage.tsx index f9c699cd4..f3ca75258 100644 --- a/samples/endpoints/local-module/src/FeatureAPage.tsx +++ b/samples/endpoints/local-module/src/FeatureAPage.tsx @@ -1,4 +1,7 @@ +import { fetchJson, useTelemetryService } from "@endpoints/shared"; import { useI18nextInstance } from "@squide/i18next"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { useEffect } from "react"; import { Trans, useTranslation } from "react-i18next"; import { i18NextInstanceKey } from "./i18next.ts"; @@ -6,6 +9,17 @@ export function FeatureAPage() { const i18nextInstance = useI18nextInstance(i18NextInstanceKey); const { t } = useTranslation("FeatureAPage", { i18n: i18nextInstance }); + const telemetryService = useTelemetryService(); + + useEffect(() => { + telemetryService?.track("Mounting FeatureAPage from remote-1."); + }, [telemetryService]); + + + const { data } = useSuspenseQuery({ queryKey: ["/api/feature-a"], queryFn: () => { + return fetchJson("/api/feature-a"); + } }); + return ( <>

          {t("title")}

          @@ -17,14 +31,7 @@ export function FeatureAPage() { components={{ code: }} />

          -

          - }} - /> -

          +

          ); } diff --git a/samples/endpoints/local-module/src/QueryProvider.tsx b/samples/endpoints/local-module/src/QueryProvider.tsx new file mode 100644 index 000000000..1f0414d19 --- /dev/null +++ b/samples/endpoints/local-module/src/QueryProvider.tsx @@ -0,0 +1,30 @@ +import { isApiError } from "@endpoints/shared"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import type { PropsWithChildren } from "react"; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + retry: (failureCount, error) => { + if (isApiError(error) && (error.status === 401 || error.status === 403)) { + return false; + } + + return failureCount <= 2; + } + } + } +}); + +export function QueryProvider({ children }: PropsWithChildren) { + return ( + + {children} + {process.env.ISOLATED && ( + + )} + + ); +} diff --git a/samples/endpoints/local-module/src/dev/App.tsx b/samples/endpoints/local-module/src/dev/App.tsx index 5a50fafe6..7121ef31a 100644 --- a/samples/endpoints/local-module/src/dev/App.tsx +++ b/samples/endpoints/local-module/src/dev/App.tsx @@ -1,7 +1,7 @@ import { LoggerTelemetryService } from "@endpoints/shared"; import { AppRouter } from "@endpoints/shell"; import { useLogger } from "@squide/firefly"; -import { sessionManager } from "./session.ts"; +import { QueryProvider } from "../QueryProvider.tsx"; export function App() { const logger = useLogger(); @@ -9,10 +9,11 @@ export function App() { const telemetryService = new LoggerTelemetryService(logger); return ( - + + + ); } diff --git a/samples/endpoints/local-module/src/dev/index.tsx b/samples/endpoints/local-module/src/dev/index.tsx index 1dfd6cc92..5bbb0c33f 100644 --- a/samples/endpoints/local-module/src/dev/index.tsx +++ b/samples/endpoints/local-module/src/dev/index.tsx @@ -1,25 +1,23 @@ import { createI18NextPlugin } from "@endpoints/i18next"; import { registerShell } from "@endpoints/shell"; -import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, setMswAsStarted } from "@squide/firefly"; +import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, setMswAsReady } from "@squide/firefly"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { registerLocalModule } from "../register.tsx"; import { App } from "./App.tsx"; import { registerDev } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; const consoleLogger = new ConsoleLogger(); // Create the shell runtime. -// Services, loggers and sessionAccessor could be reuse through a shared packages or faked when in isolation. +// Services and loggers could be reuse through a shared packages or faked when in isolation. const runtime = new FireflyRuntime({ useMsw: !!process.env.USE_MSW, - plugins: [createI18NextPlugin()], - loggers: [consoleLogger], - sessionAccessor + plugins: [x => createI18NextPlugin(x)], + loggers: [consoleLogger] }); -await registerLocalModules([registerShell(sessionManager), registerDev, registerLocalModule], runtime); +await registerLocalModules([registerShell(), registerDev, registerLocalModule], runtime); // Register MSW after the local modules has been registered since the request handlers // will be registered by the modules. @@ -31,7 +29,7 @@ if (runtime.isMswEnabled) { startMsw(runtime.requestHandlers) .then(() => { // Indicate to resources that are dependent on MSW that the service has been started. - setMswAsStarted(); + setMswAsReady(); }) .catch((error: unknown) => { consoleLogger.debug("[host-app] An error occured while starting MSW.", error); diff --git a/samples/endpoints/local-module/src/dev/session.ts b/samples/endpoints/local-module/src/dev/session.ts deleted file mode 100644 index d92f1c08d..000000000 --- a/samples/endpoints/local-module/src/dev/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session } from "@endpoints/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager(); - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/endpoints/local-module/src/locales/en-US/resources.json b/samples/endpoints/local-module/src/locales/en-US/resources.json index a7bf52340..afe128eff 100644 --- a/samples/endpoints/local-module/src/locales/en-US/resources.json +++ b/samples/endpoints/local-module/src/locales/en-US/resources.json @@ -16,8 +16,7 @@ }, "FeatureAPage": { "title": "Feature A", - "servedBy": "This page is served by @endpoints/local-module", - "message": "This page is only available if the featureA flag is active." + "servedBy": "This page is served by @endpoints/local-module" }, "CharactersTab": { "title": "Characters", diff --git a/samples/endpoints/local-module/src/locales/fr-CA/resources.json b/samples/endpoints/local-module/src/locales/fr-CA/resources.json index 3376fa245..4e3134dff 100644 --- a/samples/endpoints/local-module/src/locales/fr-CA/resources.json +++ b/samples/endpoints/local-module/src/locales/fr-CA/resources.json @@ -16,8 +16,7 @@ }, "FeatureAPage": { "title": "Fonctionnalité A", - "servedBy": "Cette page est servi par @endpoints/local-module", - "message": "Cette page est uniquement disponible si la fonctionnalité featureA est activé." + "servedBy": "Cette page est servi par @endpoints/local-module" }, "CharactersTab": { "title": "Personnages", diff --git a/samples/endpoints/local-module/src/register.tsx b/samples/endpoints/local-module/src/register.tsx index d267c45a9..876d7b5f0 100644 --- a/samples/endpoints/local-module/src/register.tsx +++ b/samples/endpoints/local-module/src/register.tsx @@ -1,35 +1,20 @@ import type { DeferredRegistrationData } from "@endpoints/shared"; import type { DeferredRegistrationFunction, FireflyRuntime, ModuleRegisterFunction } from "@squide/firefly"; import { I18nextNavigationItemLabel } from "@squide/i18next"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import type { i18n } from "i18next"; import type { ReactNode } from "react"; +import { QueryProvider } from "./QueryProvider.tsx"; import { initI18next } from "./i18next.ts"; -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, - retry: failureCount => { - return failureCount <= 2; - } - } - } -}); - interface ProvidersProps { children: ReactNode; } function Providers({ children }: ProvidersProps) { return ( - + {children} - {process.env.ISOLATED && ( - - )} - + ); } @@ -58,30 +43,35 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n): Deferre parentPath: "/federated-tabs" }); + runtime.registerRoute({ + path: "/feature-a", + lazy: async () => { + const { FeatureAPage } = await import("./FeatureAPage.tsx"); + + return { + element: + }; + } + }); + runtime.registerNavigationItem({ + $key: "subscription", $label: , to: "/subscription" }); runtime.registerNavigationItem({ + $key: "characters-tab", $label: , to: "/federated-tabs" }, { menuId: "/federated-tabs" }); - return ({ featureFlags } = {}) => { - if (!runtime.getSession()) { - throw new Error("The deferred registrations are broken as they are executed before the protected data has been loaded."); - } - + return ({ featureFlags }) => { if (featureFlags?.featureA) { - runtime.registerRoute({ - path: "/feature-a", - lazy: () => import("./FeatureAPage.tsx") - }); - runtime.registerNavigationItem({ + $key: "feature-a", $label: , to: "/feature-a" }); diff --git a/samples/endpoints/remote-module/mocks/episodeHandlers.ts b/samples/endpoints/remote-module/mocks/episodeHandlers.ts index 863dabce8..5e025ba2e 100644 --- a/samples/endpoints/remote-module/mocks/episodeHandlers.ts +++ b/samples/endpoints/remote-module/mocks/episodeHandlers.ts @@ -1,13 +1,13 @@ /* eslint-disable max-len */ import { HttpResponse, http, type HttpHandler } from "msw"; -import { readonlySessionLocalStorage } from "./session.ts"; +import { sessionAccessor } from "./session.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. export const episodeHandlers: HttpHandler[] = [ http.get("/api/episode/1,2", async () => { - const session = readonlySessionLocalStorage.getSession(); + const session = sessionAccessor.getSession(); if (!session) { return new HttpResponse(null, { diff --git a/samples/endpoints/remote-module/mocks/featureBHandlers.ts b/samples/endpoints/remote-module/mocks/featureBHandlers.ts new file mode 100644 index 000000000..b7cc3f5c0 --- /dev/null +++ b/samples/endpoints/remote-module/mocks/featureBHandlers.ts @@ -0,0 +1,35 @@ +import { HttpResponse, http, type HttpHandler } from "msw"; +import { featureFlagsAccessor } from "./featureFlags.ts"; +import { sessionAccessor } from "./session.ts"; + +export const featureBHandlers: HttpHandler[] = [ + http.get("/api/feature-b", async () => { + const session = sessionAccessor.getSession(); + + if (!session) { + return new HttpResponse(null, { + status: 401 + }); + } + + const featureFlags = featureFlagsAccessor.getFeatureFlags(); + + if (!featureFlags.featureB) { + return new HttpResponse(null, { + status: 403 + }); + } + + const isEn = session.preferredLanguage === "en-US"; + + if (isEn) { + return HttpResponse.json({ + message: "This page is only available if the featureB flag is active." + }); + } else { + return HttpResponse.json({ + message: "Cette page est uniquement disponible si la fonctionnalité featureB est activé." + }); + } + }) +]; diff --git a/samples/endpoints/remote-module/mocks/featureCHandlers.ts b/samples/endpoints/remote-module/mocks/featureCHandlers.ts new file mode 100644 index 000000000..6a0271f50 --- /dev/null +++ b/samples/endpoints/remote-module/mocks/featureCHandlers.ts @@ -0,0 +1,35 @@ +import { HttpResponse, http, type HttpHandler } from "msw"; +import { featureFlagsAccessor } from "./featureFlags.ts"; +import { sessionAccessor } from "./session.ts"; + +export const featureCHandlers: HttpHandler[] = [ + http.get("/api/feature-c", async () => { + const session = sessionAccessor.getSession(); + + if (!session) { + return new HttpResponse(null, { + status: 401 + }); + } + + const featureFlags = featureFlagsAccessor.getFeatureFlags(); + + if (!featureFlags.featureC) { + return new HttpResponse(null, { + status: 403 + }); + } + + const isEn = session.preferredLanguage === "en-US"; + + if (isEn) { + return HttpResponse.json({ + message: "This page is only available if the featureC flag is active." + }); + } else { + return HttpResponse.json({ + message: "Cette page est uniquement disponible si la fonctionnalité featureC est activé." + }); + } + }) +]; diff --git a/samples/endpoints/remote-module/mocks/featureFlags.ts b/samples/endpoints/remote-module/mocks/featureFlags.ts new file mode 100644 index 000000000..375472705 --- /dev/null +++ b/samples/endpoints/remote-module/mocks/featureFlags.ts @@ -0,0 +1,3 @@ +import { LocalStorageFeatureFlagsAccessor } from "@endpoints/shared"; + +export const featureFlagsAccessor = new LocalStorageFeatureFlagsAccessor(); diff --git a/samples/endpoints/remote-module/mocks/handlers.ts b/samples/endpoints/remote-module/mocks/handlers.ts index 90047b4b9..5be5da8e4 100644 --- a/samples/endpoints/remote-module/mocks/handlers.ts +++ b/samples/endpoints/remote-module/mocks/handlers.ts @@ -1,8 +1,10 @@ import type { HttpHandler } from "msw"; import { episodeHandlers } from "./episodeHandlers.ts"; +import { featureBHandlers } from "./featureBHandlers.ts"; +import { featureCHandlers } from "./featureCHandlers.ts"; import { locationHandlers } from "./locationHandlers.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. -export const requestHandlers: HttpHandler[] = [...episodeHandlers, ...locationHandlers]; +export const requestHandlers: HttpHandler[] = [...episodeHandlers, ...locationHandlers, ...featureBHandlers, ...featureCHandlers]; diff --git a/samples/endpoints/remote-module/mocks/locationHandlers.ts b/samples/endpoints/remote-module/mocks/locationHandlers.ts index 0f9e6582c..56974947d 100644 --- a/samples/endpoints/remote-module/mocks/locationHandlers.ts +++ b/samples/endpoints/remote-module/mocks/locationHandlers.ts @@ -1,13 +1,13 @@ /* eslint-disable max-len */ import { HttpResponse, http, type HttpHandler } from "msw"; -import { readonlySessionLocalStorage } from "./session.ts"; +import { sessionAccessor } from "./session.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. export const locationHandlers: HttpHandler[] = [ http.get("/api/location/1,2,3", async () => { - const session = readonlySessionLocalStorage.getSession(); + const session = sessionAccessor.getSession(); if (!session) { return new HttpResponse(null, { diff --git a/samples/endpoints/remote-module/mocks/session.ts b/samples/endpoints/remote-module/mocks/session.ts index ffe98a2da..28b4b3e13 100644 --- a/samples/endpoints/remote-module/mocks/session.ts +++ b/samples/endpoints/remote-module/mocks/session.ts @@ -1,5 +1,5 @@ -import { FakeSessionKey } from "@endpoints/shared"; -import { ReadonlySessionLocalStorage } from "@squide/fakes"; +import { FakeSessionStorageKey } from "@endpoints/shared"; +import { LocalStorageSessionAccessor } from "@squide/fakes"; export interface Session { userId: number; @@ -7,4 +7,4 @@ export interface Session { preferredLanguage: string; } -export const readonlySessionLocalStorage = new ReadonlySessionLocalStorage({ key: FakeSessionKey }); +export const sessionAccessor = new LocalStorageSessionAccessor({ key: FakeSessionStorageKey }); diff --git a/samples/endpoints/remote-module/package.json b/samples/endpoints/remote-module/package.json index 3e70e6f57..65b5c9603 100644 --- a/samples/endpoints/remote-module/package.json +++ b/samples/endpoints/remote-module/package.json @@ -21,24 +21,24 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "workspace:*", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@tanstack/react-query-devtools": "5.32.0", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@tanstack/react-query-devtools": "5.51.9", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "copyfiles": "2.4.1", "cross-env": "7.0.3", "eslint": "8.57.0", "http-server": "14.1.1", - "netlify-cli": "17.23.1", - "nodemon": "3.1.0", - "typescript": "5.4.5", - "webpack": "5.91.0", + "netlify-cli": "17.33.4", + "nodemon": "3.1.4", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -50,17 +50,20 @@ "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "@squide/i18next": "workspace:*", - "@tanstack/react-query": "5.32.0", - "i18next": "23.11.3", - "i18next-browser-languagedetector": "7.2.1", - "msw": "2.2.14", + "@tanstack/react-query": "5.51.9", + "i18next": "23.12.1", + "i18next-browser-languagedetector": "8.0.0", + "msw": "2.3.1", "react": "18.3.1", "react-dom": "18.3.1", "react-error-boundary": "4.0.13", - "react-i18next": "14.1.1", - "react-router-dom": "6.23.0" + "react-i18next": "15.0.0", + "react-router-dom": "6.25.1" }, "msw": { "workerDirectory": "public" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/remote-module/src/FeatureBPage.tsx b/samples/endpoints/remote-module/src/FeatureBPage.tsx index 1b0308320..009586759 100644 --- a/samples/endpoints/remote-module/src/FeatureBPage.tsx +++ b/samples/endpoints/remote-module/src/FeatureBPage.tsx @@ -1,5 +1,6 @@ -import { useTelemetryService } from "@endpoints/shared"; +import { fetchJson, useTelemetryService } from "@endpoints/shared"; import { useI18nextInstance } from "@squide/i18next"; +import { useSuspenseQuery } from "@tanstack/react-query"; import { useEffect } from "react"; import { Trans, useTranslation } from "react-i18next"; import { i18NextInstanceKey } from "./i18next.ts"; @@ -14,6 +15,10 @@ export function FeatureBPage() { telemetryService?.track("Mounting FeatureBPage from remote-1."); }, [telemetryService]); + const { data } = useSuspenseQuery({ queryKey: ["/api/feature-b"], queryFn: () => { + return fetchJson("/api/feature-b"); + } }); + return ( <>

          {t("title")}

          @@ -25,14 +30,7 @@ export function FeatureBPage() { components={{ code: }} />

          -

          - }} - /> -

          +

          ); } diff --git a/samples/endpoints/remote-module/src/FeatureCPage.tsx b/samples/endpoints/remote-module/src/FeatureCPage.tsx index 2ec981733..722c71fa7 100644 --- a/samples/endpoints/remote-module/src/FeatureCPage.tsx +++ b/samples/endpoints/remote-module/src/FeatureCPage.tsx @@ -1,5 +1,6 @@ -import { useTelemetryService } from "@endpoints/shared"; +import { fetchJson, useTelemetryService } from "@endpoints/shared"; import { useI18nextInstance } from "@squide/i18next"; +import { useSuspenseQuery } from "@tanstack/react-query"; import { useEffect } from "react"; import { Trans, useTranslation } from "react-i18next"; import { i18NextInstanceKey } from "./i18next.ts"; @@ -11,9 +12,13 @@ export function FeatureCPage() { const telemetryService = useTelemetryService(); useEffect(() => { - telemetryService?.track("Mounting FeatureBPage from remote-1."); + telemetryService?.track("Mounting FeatureCPage from remote-1."); }, [telemetryService]); + const { data } = useSuspenseQuery({ queryKey: ["/api/feature-c"], queryFn: () => { + return fetchJson("/api/feature-c"); + } }); + return ( <>

          {t("title")}

          @@ -25,14 +30,7 @@ export function FeatureCPage() { components={{ code: }} />

          -

          - }} - /> -

          +

          ); } diff --git a/samples/endpoints/remote-module/src/QueryProvider.tsx b/samples/endpoints/remote-module/src/QueryProvider.tsx new file mode 100644 index 000000000..65c72eae0 --- /dev/null +++ b/samples/endpoints/remote-module/src/QueryProvider.tsx @@ -0,0 +1,31 @@ +import { isApiError } from "@endpoints/shared"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import type { PropsWithChildren } from "react"; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + retry: (failureCount, error) => { + if (isApiError(error) && (error.status === 401 || error.status === 403)) { + return false; + } + + return failureCount <= 2; + }, + refetchInterval: 5 * 1000 + } + } +}); + +export function QueryProvider({ children }: PropsWithChildren) { + return ( + + {children} + {process.env.ISOLATED && ( + + )} + + ); +} diff --git a/samples/endpoints/remote-module/src/dev/App.tsx b/samples/endpoints/remote-module/src/dev/App.tsx index 6a2d6e934..82a07ab1e 100644 --- a/samples/endpoints/remote-module/src/dev/App.tsx +++ b/samples/endpoints/remote-module/src/dev/App.tsx @@ -1,7 +1,7 @@ import { LoggerTelemetryService } from "@endpoints/shared"; import { AppRouter } from "@endpoints/shell"; import { useLogger } from "@squide/firefly"; -import { sessionManager } from "./session.ts"; +import { QueryProvider } from "../QueryProvider.tsx"; export function App() { const logger = useLogger(); @@ -9,11 +9,12 @@ export function App() { const telemetryService = new LoggerTelemetryService(logger); return ( - + + + ); } diff --git a/samples/endpoints/remote-module/src/dev/index.tsx b/samples/endpoints/remote-module/src/dev/index.tsx index 8d541f6b2..f3c9a1ad4 100644 --- a/samples/endpoints/remote-module/src/dev/index.tsx +++ b/samples/endpoints/remote-module/src/dev/index.tsx @@ -1,27 +1,25 @@ import { createI18NextPlugin } from "@endpoints/i18next"; import { registerShell } from "@endpoints/shell"; -import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, setMswAsStarted } from "@squide/firefly"; +import { ConsoleLogger, FireflyRuntime, RuntimeContext, registerLocalModules, setMswAsReady } from "@squide/firefly"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { register as registerModule } from "../register.tsx"; import { App } from "./App.tsx"; import { registerDev } from "./register.tsx"; -import { sessionAccessor, sessionManager } from "./session.ts"; const consoleLogger = new ConsoleLogger(); // Create the shell runtime. -// Services, loggers and sessionAccessor could be reuse through a shared packages or faked when in isolation. +// Services and loggers could be reuse through a shared packages or faked when in isolation. const runtime = new FireflyRuntime({ useMsw: !!process.env.USE_MSW, - plugins: [createI18NextPlugin()], - loggers: [consoleLogger], - sessionAccessor + plugins: [x => createI18NextPlugin(x)], + loggers: [consoleLogger] }); // Registering the remote module as a static module because the "register" function // is local when developing in isolation. -await registerLocalModules([registerShell(sessionManager), registerDev, registerModule], runtime); +await registerLocalModules([registerShell(), registerDev, registerModule], runtime); // Register MSW after the local modules has been registered since the request handlers // will be registered by the modules. @@ -33,7 +31,7 @@ if (runtime.isMswEnabled) { startMsw(runtime.requestHandlers) .then(() => { // Indicate to resources that are dependent on MSW that the service has been started. - setMswAsStarted(); + setMswAsReady(); }) .catch((error: unknown) => { consoleLogger.debug("[host-app] An error occured while starting MSW.", error); diff --git a/samples/endpoints/remote-module/src/dev/session.ts b/samples/endpoints/remote-module/src/dev/session.ts deleted file mode 100644 index d92f1c08d..000000000 --- a/samples/endpoints/remote-module/src/dev/session.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Session } from "@endpoints/shared"; -import { LocalStorageSessionManager } from "@squide/fakes"; -import type { SessionAccessorFunction } from "@squide/firefly"; - -export const sessionManager = new LocalStorageSessionManager(); - -export const sessionAccessor: SessionAccessorFunction = () => { - return sessionManager.getSession(); -}; diff --git a/samples/endpoints/remote-module/src/locales/en-US/resources.json b/samples/endpoints/remote-module/src/locales/en-US/resources.json index 76587ba5e..35980b5bb 100644 --- a/samples/endpoints/remote-module/src/locales/en-US/resources.json +++ b/samples/endpoints/remote-module/src/locales/en-US/resources.json @@ -13,8 +13,7 @@ }, "FeatureBPage": { "title": "Feature B", - "servedBy": "This page is served by @endpoints/remote-module", - "message": "This page is only available if the featureB flag is active." + "servedBy": "This page is served by @endpoints/remote-module" }, "FeatureCPage": { "title": "Feature C", diff --git a/samples/endpoints/remote-module/src/locales/fr-CA/resources.json b/samples/endpoints/remote-module/src/locales/fr-CA/resources.json index ae058ab05..b204893f0 100644 --- a/samples/endpoints/remote-module/src/locales/fr-CA/resources.json +++ b/samples/endpoints/remote-module/src/locales/fr-CA/resources.json @@ -14,8 +14,7 @@ }, "FeatureBPage": { "title": "Fonctionnalité B", - "servedBy": "Cette page est servi par @endpoints/remote-module", - "message": "Cette page est uniquement disponible si la fonctionnalité featureB est activé." + "servedBy": "Cette page est servi par @endpoints/remote-module" }, "FeatureCPage": { "title": "Fonctionnalité C", diff --git a/samples/endpoints/remote-module/src/register.tsx b/samples/endpoints/remote-module/src/register.tsx index e89c4ba50..9acf8c5bf 100644 --- a/samples/endpoints/remote-module/src/register.tsx +++ b/samples/endpoints/remote-module/src/register.tsx @@ -1,35 +1,20 @@ import type { DeferredRegistrationData } from "@endpoints/shared"; import type { DeferredRegistrationFunction, FireflyRuntime, ModuleRegisterFunction } from "@squide/firefly"; import { I18nextNavigationItemLabel } from "@squide/i18next"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import type { i18n } from "i18next"; import type { ReactNode } from "react"; +import { QueryProvider } from "./QueryProvider.tsx"; import { initI18next } from "./i18next.ts"; -export const queryClient = new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, - retry: failureCount => { - return failureCount <= 2; - } - } - } -}); - interface ProvidersProps { children: ReactNode; } function Providers({ children }: ProvidersProps) { return ( - + {children} - {process.env.ISOLATED && ( - - )} - + ); } @@ -45,7 +30,7 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n): Deferre }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -87,7 +72,30 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n): Deferre parentPath: "/federated-tabs" }); + runtime.registerRoute({ + path: "/feature-b", + lazy: async () => { + const { FeatureBPage } = await import("./FeatureBPage.tsx"); + + return { + element: + }; + } + }); + + runtime.registerRoute({ + path: "/feature-c", + lazy: async () => { + const { FeatureCPage } = await import("./FeatureCPage.tsx"); + + return { + element: + }; + } + }); + runtime.registerNavigationItem({ + $key: "episodes-tab", $label: , to: "/federated-tabs/episodes" }, { @@ -95,6 +103,7 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n): Deferre }); runtime.registerNavigationItem({ + $key: "locations-tab", $label: , to: "/federated-tabs/locations" }, { @@ -102,36 +111,25 @@ function registerRoutes(runtime: FireflyRuntime, i18nextInstance: i18n): Deferre }); runtime.registerNavigationItem({ + $key: "failing-tab", $label: , to: "/federated-tabs/failing" }, { menuId: "/federated-tabs" }); - return ({ featureFlags } = {}) => { - if (!runtime.getSession()) { - throw new Error("The deferred registratons are broken again as they are executed before the protected data has been loaded."); - } - + return ({ featureFlags }) => { if (featureFlags?.featureB) { - runtime.registerRoute({ - path: "/feature-b", - lazy: () => import("./FeatureBPage.tsx") - }); - runtime.registerNavigationItem({ + $key: "feature-b", $label: , to: "/feature-b" }); } if (featureFlags?.featureC) { - runtime.registerRoute({ - path: "/feature-c", - lazy: () => import("./FeatureCPage.tsx") - }); - runtime.registerNavigationItem({ + $key: "feature-c", $label: , to: "/feature-c" }); diff --git a/samples/endpoints/shared/package.json b/samples/endpoints/shared/package.json index bff1227ae..474addfd9 100644 --- a/samples/endpoints/shared/package.json +++ b/samples/endpoints/shared/package.json @@ -19,20 +19,25 @@ "build": "tsup --config ./tsup.build.ts" }, "peerDependencies": { + "@squide/fakes": "*", "@squide/firefly": "*", "react": "*", "react-dom": "*" }, "devDependencies": { + "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/shared/src/featureFlags.ts b/samples/endpoints/shared/src/featureFlags.ts index 853c4118e..a1519ab35 100644 --- a/samples/endpoints/shared/src/featureFlags.ts +++ b/samples/endpoints/shared/src/featureFlags.ts @@ -1,3 +1,4 @@ +import { LocalStorageAccessor, LocalStorageManager } from "@squide/fakes"; import { createContext, useContext } from "react"; export interface FeatureFlags { @@ -6,6 +7,56 @@ export interface FeatureFlags { featureC: boolean; } +const DefaultFeatureFlags = { + featureA: true, + featureB: true, + featureC: false +}; + +export class LocalStorageFeatureFlagsManager { + readonly #localStorageManager: LocalStorageManager; + + constructor() { + this.#localStorageManager = new LocalStorageManager("app-feature-flags"); + } + + setFeatureFlags(featureFlags: FeatureFlags) { + this.#localStorageManager.setObjectValue(featureFlags); + } + + getFeatureFlags() { + const featureFlags = this.#localStorageManager.getObjectValue(); + + if (featureFlags) { + return featureFlags; + } + + return DefaultFeatureFlags; + } + + clearFeatureFlags() { + this.#localStorageManager.clearStorage(); + } +} + +export class LocalStorageFeatureFlagsAccessor { + readonly #localStorageAccessor: LocalStorageAccessor; + + constructor() { + this.#localStorageAccessor = new LocalStorageAccessor("app-feature-flags"); + } + + getFeatureFlags() { + const featureFlags = this.#localStorageAccessor.getObjectValue(); + + if (featureFlags) { + return featureFlags; + } + + return DefaultFeatureFlags; + } +} + export const FeatureFlagsContext = createContext(undefined); export function useFeatureFlags() { diff --git a/samples/endpoints/shared/src/session.ts b/samples/endpoints/shared/src/session.ts index b8ebae44e..56f78018b 100644 --- a/samples/endpoints/shared/src/session.ts +++ b/samples/endpoints/shared/src/session.ts @@ -1,5 +1,8 @@ +import { createContext, useContext } from "react"; import type { LanguageKey } from "./i18next.ts"; +export const FakeSessionStorageKey = "squide-endpoints-msw-session-v2"; + export interface Session { user: { id: number; @@ -9,9 +12,25 @@ export interface Session { } export interface SessionManager { - setSession: (session: Session) => void; getSession: () => Session | undefined; clearSession: () => void; } -export const FakeSessionKey = "squide-endpoints-msw-session-v2"; +export const SessionManagerContext = createContext(undefined); + +export function useSessionManager() { + return useContext(SessionManagerContext); +} + +export function useSession() { + const sessionManager = useSessionManager(); + + return sessionManager?.getSession(); +} + +export function useIsAuthenticated() { + const sessionManager = useSessionManager(); + + return !!sessionManager?.getSession(); +} + diff --git a/samples/endpoints/shell/mocks/featureFlags.ts b/samples/endpoints/shell/mocks/featureFlags.ts new file mode 100644 index 000000000..e1fd29171 --- /dev/null +++ b/samples/endpoints/shell/mocks/featureFlags.ts @@ -0,0 +1,3 @@ +import { LocalStorageFeatureFlagsManager } from "@endpoints/shared"; + +export const featureFlagsManager = new LocalStorageFeatureFlagsManager(); diff --git a/samples/endpoints/shell/mocks/featureFlagsHandlers.ts b/samples/endpoints/shell/mocks/featureFlagsHandlers.ts index e4b4b3de4..c0b9a3115 100644 --- a/samples/endpoints/shell/mocks/featureFlagsHandlers.ts +++ b/samples/endpoints/shell/mocks/featureFlagsHandlers.ts @@ -1,16 +1,41 @@ import { HttpResponse, http, type HttpHandler } from "msw"; +import { featureFlagsManager } from "./featureFlags.ts"; import { simulateDelay } from "./simulateDelay.ts"; // Must specify the return type, otherwise we get a TS2742: The inferred type cannot be named without a reference to X. This is likely not portable. // A type annotation is necessary. export const featureFlagsHandlers: HttpHandler[] = [ http.get("/api/feature-flags", async () => { + const featureFlags = featureFlagsManager.getFeatureFlags(); + await simulateDelay(500); - return HttpResponse.json({ - featureA: true, + return HttpResponse.json(featureFlags); + }), + http.post("/api/shuffle-feature-flags", async () => { + const newFeatureFlags = { + featureA: Math.random() < 0.5, featureB: true, - featureC: false + featureC: Math.random() < 0.5 + }; + + featureFlagsManager.setFeatureFlags(newFeatureFlags); + + console.log("[endpoints] New feature flags are:", newFeatureFlags); + + return new HttpResponse(null, { + status: 200 + }); + }), + http.post("/api/deactivate-feature-b", async () => { + featureFlagsManager.setFeatureFlags({ + featureA: true, + featureB: false, + featureC: true + }); + + return new HttpResponse(null, { + status: 200 }); }) ]; diff --git a/samples/endpoints/shell/mocks/session.ts b/samples/endpoints/shell/mocks/session.ts index 86bb2deb4..99365d656 100644 --- a/samples/endpoints/shell/mocks/session.ts +++ b/samples/endpoints/shell/mocks/session.ts @@ -1,4 +1,4 @@ -import { FakeSessionKey } from "@endpoints/shared"; +import { FakeSessionStorageKey } from "@endpoints/shared"; import { LocalStorageSessionManager } from "@squide/fakes"; export interface Session { @@ -7,4 +7,4 @@ export interface Session { preferredLanguage: string; } -export const sessionManager = new LocalStorageSessionManager({ key: FakeSessionKey }); +export const sessionManager = new LocalStorageSessionManager({ key: FakeSessionStorageKey }); diff --git a/samples/endpoints/shell/mocks/sessionHandlers.ts b/samples/endpoints/shell/mocks/sessionHandlers.ts index e405a5abf..a977bebf9 100644 --- a/samples/endpoints/shell/mocks/sessionHandlers.ts +++ b/samples/endpoints/shell/mocks/sessionHandlers.ts @@ -17,5 +17,24 @@ export const sessionHandlers: HttpHandler[] = [ await simulateDelay(500); return HttpResponse.json(session); + }), + http.post("/api/update-session", async () => { + const session = sessionManager.getSession(); + + if (!session) { + return new HttpResponse(null, { + status: 401 + }); + } + + sessionManager.setSession({ + userId: session.userId, + username: Math.random().toString(20), + preferredLanguage: session.preferredLanguage + }); + + return new HttpResponse(null, { + status: 200 + }); }) ]; diff --git a/samples/endpoints/shell/package.json b/samples/endpoints/shell/package.json index 9a2dda5e8..a19e9bdc0 100644 --- a/samples/endpoints/shell/package.json +++ b/samples/endpoints/shell/package.json @@ -24,6 +24,7 @@ "@squide/fakes": "*", "@squide/firefly": "*", "@squide/i18next": "*", + "@tanstack/react-query": "*", "i18next": "*", "i18next-browser-languagedetector": "*", "msw": "*", @@ -40,15 +41,18 @@ "@squide/fakes": "workspace:*", "@squide/firefly": "workspace:*", "@squide/i18next": "workspace:*", - "@types/node": "20.12.7", - "@types/react": "18.3.1", + "@types/node": "20.14.11", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "nodemon": "3.1.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "nodemon": "3.1.4", + "tsup": "8.1.2", + "typescript": "5.5.3" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/samples/endpoints/shell/src/AppRouter.tsx b/samples/endpoints/shell/src/AppRouter.tsx index 239e738a8..41a671b46 100644 --- a/samples/endpoints/shell/src/AppRouter.tsx +++ b/samples/endpoints/shell/src/AppRouter.tsx @@ -1,149 +1,137 @@ -import { FeatureFlagsContext, SubscriptionContext, TelemetryServiceContext, fetchJson, isApiError, type FeatureFlags, type Session, type SessionManager, type Subscription, type TelemetryService } from "@endpoints/shared"; -import { AppRouter as FireflyAppRouter, completeModuleRegistrations, useLogger, useRuntime, type Logger } from "@squide/firefly"; -import { useChangeLanguage, useI18nextInstance } from "@squide/i18next"; -import { useCallback, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import { AppRouterErrorBoundary } from "./AppRouterErrorBoundary.tsx"; -import { i18NextInstanceKey } from "./i18next.ts"; -import { useRefState } from "./useRefState.tsx"; - -export interface AppRouterProps { - waitForMsw: boolean; - sessionManager: SessionManager; +import { FeatureFlagsContext, SessionManagerContext, SubscriptionContext, TelemetryServiceContext, fetchJson, isApiError, type FeatureFlags, type Session, type Subscription, type TelemetryService } from "@endpoints/shared"; +import { AppRouter as FireflyAppRouter, useDeferredRegistrations, useIsBootstrapping, useLogger, useProtectedDataQueries, usePublicDataQueries } from "@squide/firefly"; +import { useChangeLanguage } from "@squide/i18next"; +import { useEffect, useMemo } from "react"; +import { Outlet, RouterProvider, createBrowserRouter } from "react-router-dom"; +import { Loading } from "./Loading.tsx"; +import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; +import { useSessionManagerInstance } from "./useSessionManagerInstance.ts"; + +interface BootstrappingRouteProps { telemetryService: TelemetryService; } -async function fetchPublicData(setFeatureFlags: (featureFlags: FeatureFlags) => void, signal: AbortSignal, logger: Logger) { - const data = await fetchJson("/api/feature-flags", { - signal - }); - - logger.debug("[shell] %cFeature flags are ready%c:", "color: white; background-color: green;", "", data); - - setFeatureFlags(data); -} +function BootstrappingRoute({ telemetryService }: BootstrappingRouteProps) { + const logger = useLogger(); -async function fetchSession(signal: AbortSignal) { - const data = await fetchJson("/api/session", { - signal - }); + const [featureFlags] = usePublicDataQueries([ + { + queryKey: ["/api/feature-flags"], + queryFn: async () => { + const data = await fetchJson("/api/feature-flags"); - const session: Session = { - user: { - id: data.userId, - name: data.username, - preferredLanguage: data.preferredLanguage + return data as FeatureFlags; + } } - }; - - return session; -} - -async function fetchSubscription(signal: AbortSignal) { - const data = await fetchJson("/api/subscription", { - signal - }); + ]); - return data as Subscription; -} - -function fetchProtectedData( - setSession: (session: Session) => void, - setSubscription: (subscription: Subscription) => void, - setIsProtectedDataLoaded: (isProtectedDataLoaded: boolean) => void, - signal: AbortSignal, - logger: Logger -) { - const sessionPromise = fetchSession(signal); - const subscriptionPromise = fetchSubscription(signal); - - return Promise.all([sessionPromise, subscriptionPromise]) - .then(([session, subscription]) => { - logger.debug("[shell] %cSession is ready%c:", "color: white; background-color: green;", "", session); - - setSession(session); - - logger.debug("[shell] %cSubscription is ready%c:", "color: white; background-color: green;", "", subscription); - - setSubscription(subscription); - setIsProtectedDataLoaded(true); - }) - .catch((error: unknown) => { - if (isApiError(error) && error.status === 401) { - setIsProtectedDataLoaded(true); - - // The authentication boundary will redirect to the login page. - return; + useEffect(() => { + if (featureFlags) { + logger.debug("[shell] %cFeature flags has been fetched%c:", "color: white; background-color: green;", "", featureFlags); + } + }, [featureFlags, logger]); + + const [session, subscription] = useProtectedDataQueries([ + { + queryKey: ["/api/session"], + queryFn: async () => { + const data = await fetchJson("/api/session"); + + const result: Session = { + user: { + id: data.userId, + name: data.username, + preferredLanguage: data.preferredLanguage + } + }; + + return result; } + }, + { + queryKey: ["/api/subscription"], + queryFn: async () => { + const data = await fetchJson("/api/subscription"); - throw error; - }); -} - -function Loading() { - const i18nextInstance = useI18nextInstance(i18NextInstanceKey); - const { t } = useTranslation("AppRouter", { i18n: i18nextInstance }); - - return ( -
          {t("loadingMessage")}
          - ); -} - -export function AppRouter({ waitForMsw, sessionManager, telemetryService }: AppRouterProps) { - const [featureFlags, setFeatureFlags] = useState(); - - const [subscriptionRef, setSubscription] = useRefState(); - const [isProtectedDataLoaded, setIsProtectedDataLoaded] = useState(false); - - const logger = useLogger(); - const runtime = useRuntime(); + return data as Subscription; + } + } + ], error => isApiError(error) && error.status === 401); const changeLanguage = useChangeLanguage(); - const handleLoadPublicData = useCallback((signal: AbortSignal) => { - return fetchPublicData(setFeatureFlags, signal, logger); - }, [logger]); - - const handleLoadProtectedData = useCallback((signal: AbortSignal) => { - const setSession = (session: Session) => { - sessionManager.setSession(session); + useEffect(() => { + if (session) { + logger.debug("[shell] %cSession has been fetched%c:", "color: white; background-color: green;", "", session); // When the session has been retrieved, update the language to match the user // preferred language. changeLanguage(session.user.preferredLanguage); - }; + } + }, [session, changeLanguage, logger]); + + useEffect(() => { + if (subscription) { + logger.debug("[shell] %cSubscription has been fetched%c:", "color: white; background-color: green;", "", subscription); + } + }, [subscription, logger]); + + useDeferredRegistrations(useMemo(() => ({ + featureFlags, + session + }), [featureFlags, session])); - return fetchProtectedData(setSession, setSubscription, setIsProtectedDataLoaded, signal, logger); - }, [logger, sessionManager, changeLanguage, setSubscription]); + const sessionManager = useSessionManagerInstance(session!); - const handleCompleteRegistrations = useCallback(() => { - return completeModuleRegistrations(runtime, { - featureFlags, - session: sessionManager.getSession() - }); - }, [runtime, featureFlags, sessionManager]); + if (useIsBootstrapping()) { + return ; + } return ( - - - } - errorElement={} - waitForMsw={waitForMsw} - onLoadPublicData={handleLoadPublicData} - onLoadProtectedData={handleLoadProtectedData} - isPublicDataLoaded={!!featureFlags} - isProtectedDataLoaded={isProtectedDataLoaded} - onCompleteRegistrations={handleCompleteRegistrations} - > - {(routes, providerProps) => ( - - )} - - - + + + + + + + ); } + +export interface AppRouterProps { + waitForMsw: boolean; + telemetryService: TelemetryService; +} + +export function AppRouter(props: AppRouterProps) { + const { + waitForMsw, + telemetryService + } = props; + + return ( + + {({ rootRoute, registeredRoutes, routerProviderProps }) => { + return ( + , + errorElement: , + children: registeredRoutes + } + ] + } + ])} + {...routerProviderProps} + /> + ); + }} + + ); +} diff --git a/samples/endpoints/shell/src/AppRouterErrorBoundary.tsx b/samples/endpoints/shell/src/AppRouterErrorBoundary.tsx deleted file mode 100644 index 3c5fa5b78..000000000 --- a/samples/endpoints/shell/src/AppRouterErrorBoundary.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useLogger } from "@squide/firefly"; -import { useI18nextInstance } from "@squide/i18next"; -import { useCallback, useEffect } from "react"; -import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; -import { i18NextInstanceKey } from "./i18next.ts"; - -export function AppRouterErrorBoundary({ error }: { error?: Error }) { - const i18nextInstance = useI18nextInstance(i18NextInstanceKey); - const { t } = useTranslation("AppRouterErrorBoundary", { i18n: i18nextInstance }); - - const logger = useLogger(); - const navigate = useNavigate(); - - const handleReloadButtonClick = useCallback(() => { - navigate(0); - }, [navigate]); - - useEffect(() => { - logger.error("[shell] An unmanaged error occurred while bootstrapping the application", error); - }, [error, logger]); - - return ( -
          -

          {t("title")}

          -

          {t("message")}

          -

          👉 {error?.message}

          -

          {error?.stack}

          -
          - -
          - ); -} diff --git a/samples/endpoints/shell/src/AuthenticatedLayout.tsx b/samples/endpoints/shell/src/AuthenticatedLayout.tsx index 4f0526988..91987ee4e 100644 --- a/samples/endpoints/shell/src/AuthenticatedLayout.tsx +++ b/samples/endpoints/shell/src/AuthenticatedLayout.tsx @@ -1,18 +1,19 @@ -import { postJson, toSubscriptionStatusLabel, useSubscription, type Session, type SessionManager } from "@endpoints/shared"; -import { isNavigationLink, useLogger, useNavigationItems, useRenderedNavigationItems, useSession, type NavigationLinkRenderProps, type NavigationSectionRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; +import { postJson, toSubscriptionStatusLabel, useSessionManager, useSubscription } from "@endpoints/shared"; +import { isNavigationLink, useLogger, useNavigationItems, useRenderedNavigationItems, type NavigationLinkRenderProps, type NavigationSectionRenderProps, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; import { useI18nextInstance } from "@squide/i18next"; import { Suspense, useCallback, type MouseEvent, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { Link, Outlet, useNavigate } from "react-router-dom"; +import { Loading } from "./Loading.tsx"; import { i18NextInstanceKey } from "./i18next.ts"; -type RenderLinkItemFunction = (item: NavigationLinkRenderProps, index: number, level: number) => ReactNode; +type RenderLinkItemFunction = (item: NavigationLinkRenderProps, key: string) => ReactNode; -type RenderSectionItemFunction = (item: NavigationSectionRenderProps, index: number, level: number) => ReactNode; +type RenderSectionItemFunction = (item: NavigationSectionRenderProps, key: string) => ReactNode; -const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps: { highlight, ...additionalProps } }, index, level) => { +const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalProps: { highlight, ...additionalProps } }, key) => { return ( -
        • +
        • {label} @@ -20,9 +21,9 @@ const renderLinkItem: RenderLinkItemFunction = ({ label, linkProps, additionalPr ); }; -const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, level) => { +const renderSectionItem: RenderSectionItemFunction = ({ label, section }, key) => { return ( -
        • +
        • {label}
          ({section}) @@ -31,28 +32,25 @@ const renderSectionItem: RenderSectionItemFunction = ({ label, section }, index, ); }; -const renderItem: RenderItemFunction = (item, index, level) => { - return isNavigationLink(item) ? renderLinkItem(item, index, level) : renderSectionItem(item, index, level); +const renderItem: RenderItemFunction = (item, key) => { + return isNavigationLink(item) ? renderLinkItem(item, key) : renderSectionItem(item, key); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
            +
              {elements}
            ); }; -export interface AuthenticatedLayoutProps { - sessionManager: SessionManager; -} - -export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps) { +export function AuthenticatedLayout() { const i18nextInstance = useI18nextInstance(i18NextInstanceKey); const { t } = useTranslation("AuthenticatedLayout", { i18n: i18nextInstance }); const logger = useLogger(); - const session = useSession() as Session; + const sessionManager = useSessionManager(); + const session = sessionManager?.getSession(); const subscription = useSubscription(); const subscriptionStatusLabel = toSubscriptionStatusLabel(subscription!.status, { @@ -63,12 +61,12 @@ export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps const navigate = useNavigate(); - const handleDisconnect = useCallback(async (event: MouseEvent) => { + const handleDisconnect = useCallback((event: MouseEvent) => { event.preventDefault(); - await postJson("/api/logout") + postJson("/api/logout") .then(() => { - sessionManager.clearSession(); + sessionManager?.clearSession(); logger.debug("[shell] The user session has been cleared."); @@ -79,6 +77,33 @@ export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps }); }, [logger, navigate, sessionManager]); + const handleUpdateSession = useCallback((event: MouseEvent) => { + event.preventDefault(); + + postJson("/api/update-session") + .then(() => { + logger.debug("[shell] Updated the user session."); + }); + }, [logger]); + + const handleShuffleFeatureFlags = useCallback((event: MouseEvent) => { + event.preventDefault(); + + postJson("/api/shuffle-feature-flags") + .then(() => { + logger.debug("[shell] Shuffled the feature flags."); + }); + }, [logger]); + + const handleDeactivateFeatureB = useCallback((event: MouseEvent) => { + event.preventDefault(); + + postJson("/api/deactivate-feature-b") + .then(() => { + logger.debug("[shell] Deactivated feature B."); + }); + }, [logger]); + const navigationItems = useNavigationItems(); const renderedNavigationItems = useRenderedNavigationItems(navigationItems, renderItem, renderSection); @@ -93,13 +118,28 @@ export function AuthenticatedLayout({ sessionManager }: AuthenticatedLayoutProps {/* eslint-disable-next-line max-len */} ({t("subscriptionLabel")}: {subscriptionStatusLabel}-{t("userLabel")}: {session?.user?.name}/{session?.user?.preferredLanguage})
          +
          + +
          +
          + +
          +
          + +
        - {t("loadingMessage")}}> + }> diff --git a/samples/endpoints/shell/src/AuthenticationBoundary.tsx b/samples/endpoints/shell/src/AuthenticationBoundary.tsx index a40149c91..7ac1d70e3 100644 --- a/samples/endpoints/shell/src/AuthenticationBoundary.tsx +++ b/samples/endpoints/shell/src/AuthenticationBoundary.tsx @@ -1,4 +1,5 @@ -import { useIsAuthenticated, useLogger } from "@squide/firefly"; +import { useIsAuthenticated } from "@endpoints/shared"; +import { useLogger } from "@squide/firefly"; import { Navigate, Outlet } from "react-router-dom"; export function AuthenticationBoundary() { diff --git a/samples/endpoints/shell/src/Loading.tsx b/samples/endpoints/shell/src/Loading.tsx new file mode 100644 index 000000000..a117d8577 --- /dev/null +++ b/samples/endpoints/shell/src/Loading.tsx @@ -0,0 +1,37 @@ +import { useI18nextInstance } from "@squide/i18next"; +import { useTranslation } from "react-i18next"; +import { i18NextInstanceKey } from "./i18next.ts"; + +// export function Loading() { +// const [show, setShow] = useState(false); + +// const i18nextInstance = useI18nextInstance(i18NextInstanceKey); +// const { t } = useTranslation("AppRouter", { i18n: i18nextInstance }); + +// useEffect(() => { +// const timeoutId = setTimeout(() => { +// setShow(true); +// }, 500); + +// return () => { +// clearTimeout(timeoutId); +// }; +// }, []); + +// if (show) { +// return ( +//
        {t("loadingMessage")}
        +// ); +// } + +// return null; +// } + +export function Loading() { + const i18nextInstance = useI18nextInstance(i18NextInstanceKey); + const { t } = useTranslation("AppRouter", { i18n: i18nextInstance }); + + return ( +
        {t("loadingMessage")}
        + ); +} diff --git a/samples/endpoints/shell/src/LoginPage.tsx b/samples/endpoints/shell/src/LoginPage.tsx index 07d616b8f..06b2ae6de 100644 --- a/samples/endpoints/shell/src/LoginPage.tsx +++ b/samples/endpoints/shell/src/LoginPage.tsx @@ -1,9 +1,7 @@ import { isApiError, postJson } from "@endpoints/shared"; -import { useIsAuthenticated } from "@squide/firefly"; import { useI18nextInstance } from "@squide/i18next"; import { useCallback, useState, type ChangeEvent, type MouseEvent } from "react"; import { Trans, useTranslation } from "react-i18next"; -import { Navigate } from "react-router-dom"; import { i18NextInstanceKey } from "./i18next.ts"; export interface LoginPageProps { @@ -29,7 +27,7 @@ export function LoginPage({ host }: LoginPageProps) { .then(() => { setIsBusy(false); - // Reloading the whole application so the "RootRoute" component states are reinitialize. + // Reloading the whole application so the "RootRoute" component states are re-initialize. // If we use navigate("/") instead, since "isProtectedDataLoaded" might already be true in the case // of Logout -> Login, the rendering will bypass the loading of the protected data (including the session) // which will result in an incoherent state. @@ -56,12 +54,6 @@ export function LoginPage({ host }: LoginPageProps) { setPassword(event.target.value); }, []); - const isAuthenticated = useIsAuthenticated(); - - if (isAuthenticated) { - return ; - } - return ( <>

        {t("title")}

        diff --git a/samples/endpoints/shell/src/ModuleErrorBoundary.tsx b/samples/endpoints/shell/src/ModuleErrorBoundary.tsx index 0c50c959a..4dc79508b 100644 --- a/samples/endpoints/shell/src/ModuleErrorBoundary.tsx +++ b/samples/endpoints/shell/src/ModuleErrorBoundary.tsx @@ -1,4 +1,4 @@ -import { useLogger } from "@squide/firefly"; +import { isGlobalDataQueriesError, useLogger } from "@squide/firefly"; import { useI18nextInstance } from "@squide/i18next"; import { useCallback, useEffect } from "react"; import { useTranslation } from "react-i18next"; @@ -28,7 +28,13 @@ export function ModuleErrorBoundary() { }, []); useEffect(() => { - logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error); + if (isRouteErrorResponse(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, `${error.status} ${error.statusText}`); + } else if (isGlobalDataQueriesError(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error.message, error.errors); + } else { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error); + } }, [location.pathname, error, logger]); return ( diff --git a/samples/endpoints/shell/src/RootErrorBoundary.tsx b/samples/endpoints/shell/src/RootErrorBoundary.tsx index bc9ba269c..2fb2832ea 100644 --- a/samples/endpoints/shell/src/RootErrorBoundary.tsx +++ b/samples/endpoints/shell/src/RootErrorBoundary.tsx @@ -1,6 +1,6 @@ -import { useLogger } from "@squide/firefly"; +import { isGlobalDataQueriesError, useLogger } from "@squide/firefly"; import { useI18nextInstance } from "@squide/i18next"; -import { useCallback } from "react"; +import { useCallback, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { isRouteErrorResponse, useLocation, useRouteError } from "react-router-dom"; import { i18NextInstanceKey } from "./i18next.ts"; @@ -27,7 +27,15 @@ export function RootErrorBoundary() { window.location.reload(); }, []); - logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error); + useEffect(() => { + if (isRouteErrorResponse(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, `${error.status} ${error.statusText}`); + } else if (isGlobalDataQueriesError(error)) { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error.message, error.errors); + } else { + logger.error(`[shell] An unmanaged error occurred while rendering the route with path ${location.pathname}`, error); + } + }, [location.pathname, error, logger]); return (
        diff --git a/samples/endpoints/shell/src/locales/en-US/resources.json b/samples/endpoints/shell/src/locales/en-US/resources.json index 649fb29eb..836163813 100644 --- a/samples/endpoints/shell/src/locales/en-US/resources.json +++ b/samples/endpoints/shell/src/locales/en-US/resources.json @@ -10,8 +10,10 @@ "paidLabel": "Paid", "notPaidLabel": "Not paid", "userLabel": "User", - "disconnectButtonLabel": "Disconnect", - "loadingMessage": "Loading..." + "updateSessionButtonLabel": "Update session", + "shuffleFeatureFlagsLabel": "Shuffle feature flags", + "deactivateFeatureBLabel": "Deactivate feature B", + "disconnectButtonLabel": "Disconnect" }, "ModuleErrorBoundary": { "title": "Unmanaged error", diff --git a/samples/endpoints/shell/src/locales/fr-CA/resources.json b/samples/endpoints/shell/src/locales/fr-CA/resources.json index 78f0009a4..8dd84c960 100644 --- a/samples/endpoints/shell/src/locales/fr-CA/resources.json +++ b/samples/endpoints/shell/src/locales/fr-CA/resources.json @@ -10,8 +10,10 @@ "paidLabel": "Payé", "notPaidLabel": "Non payé", "userLabel": "Utilisateur", - "disconnectButtonLabel": "Se déconnecter", - "loadingMessage": "Chargement..." + "updateSessionButtonLabel": "Modifier la session", + "shuffleFeatureFlagsLabel": "Brasser les feature flags", + "deactivateFeatureBLabel": "Désactiver la feature B", + "disconnectButtonLabel": "Se déconnecter" }, "ModuleErrorBoundary": { "title": "Erreur non gérée", diff --git a/samples/endpoints/shell/src/register.tsx b/samples/endpoints/shell/src/register.tsx index cce4bcc19..895d335e5 100644 --- a/samples/endpoints/shell/src/register.tsx +++ b/samples/endpoints/shell/src/register.tsx @@ -1,7 +1,5 @@ import { registerLayouts } from "@endpoints/layouts"; -import type { SessionManager } from "@endpoints/shared"; import { ManagedRoutes, mergeDeferredRegistrations, type FireflyRuntime, type ModuleRegisterFunction } from "@squide/firefly"; -import { RootErrorBoundary } from "./RootErrorBoundary.tsx"; import { RootLayout } from "./RootLayout.tsx"; import { initI18next } from "./i18next.ts"; @@ -10,55 +8,49 @@ export interface RegisterShellOptions { host?: string; } -function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, host?: string) { +function registerRoutes(runtime: FireflyRuntime, host?: string) { runtime.registerRoute({ // Pathless route to declare a root layout and a root error boundary. $visibility: "public", - element: , + $name: "root-layout", + element: + }, { + hoist: true + }); + + runtime.registerRoute({ + // Pathless route to declare an authenticated boundary. + lazy: () => import("./AuthenticationBoundary.tsx"), children: [ { - // Public pages like the login and logout pages will be rendered under this pathless route. - $visibility: "public", - $name: "root-error-boundary", - errorElement: , + // Pathless route to declare an authenticated layout. + lazy: async () => { + const { AuthenticatedLayout } = await import("./AuthenticatedLayout.tsx"); + + return { + element: + }; + }, children: [ { - // Pathless route to declare an authenticated boundary. - lazy: () => import("./AuthenticationBoundary.tsx"), + // Pathless route to declare an error boundary inside the layout instead of outside. + // It's quite useful to prevent losing the layout when an unmanaged error occurs. + lazy: async () => { + const { ModuleErrorBoundary } = await import("./ModuleErrorBoundary.tsx"); + + return { + errorElement: + }; + }, children: [ - { - // Pathless route to declare an authenticated layout. - lazy: async () => { - const { AuthenticatedLayout } = await import("./AuthenticatedLayout.tsx"); - - return { - element: - }; - }, - children: [ - { - // Pathless route to declare an error boundary inside the layout instead of outside. - // It's quite useful to prevent losing the layout when an unmanaged error occurs. - lazy: async () => { - const { ModuleErrorBoundary } = await import("./ModuleErrorBoundary.tsx"); - - return { - errorElement: - }; - }, - children: [ - ManagedRoutes - ] - } - ] - } + ManagedRoutes ] } ] } ] }, { - hoist: true + parentName: "root-layout" }); runtime.registerRoute({ @@ -72,7 +64,7 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -86,7 +78,7 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); runtime.registerRoute({ @@ -100,7 +92,7 @@ function registerRoutes(runtime: FireflyRuntime, sessionManager: SessionManager, }; } }, { - parentName: "root-error-boundary" + parentName: "root-layout" }); } @@ -114,7 +106,7 @@ async function registerMsw(runtime: FireflyRuntime) { } } -export function registerShell(sessionManager: SessionManager, { host }: RegisterShellOptions = {}) { +export function registerShell({ host }: RegisterShellOptions = {}) { const register: ModuleRegisterFunction = async runtime => { initI18next(runtime); @@ -122,7 +114,7 @@ export function registerShell(sessionManager: SessionManager, { host }: Register return mergeDeferredRegistrations([ registerLayouts(runtime, { host }), - registerRoutes(runtime, sessionManager, host) + registerRoutes(runtime, host) ]); }; diff --git a/samples/endpoints/shell/src/useRefState.tsx b/samples/endpoints/shell/src/useRefState.tsx deleted file mode 100644 index 91db7e114..000000000 --- a/samples/endpoints/shell/src/useRefState.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useCallback, useRef, type RefObject } from "react"; - -export function useRefState(initialValue?: T): [RefObject, (newValue: T) => void] { - const valueRef = useRef(initialValue); - - const setValue = useCallback((newValue: T) => { - if (valueRef.current !== newValue) { - valueRef.current = newValue; - } - }, [valueRef]); - - return [valueRef, setValue]; -} diff --git a/samples/endpoints/shell/src/useSessionManagerInstance.ts b/samples/endpoints/shell/src/useSessionManagerInstance.ts new file mode 100644 index 000000000..74a977992 --- /dev/null +++ b/samples/endpoints/shell/src/useSessionManagerInstance.ts @@ -0,0 +1,30 @@ +import type { Session, SessionManager } from "@endpoints/shared"; +import { useQueryClient, type QueryClient } from "@tanstack/react-query"; +import { useMemo } from "react"; + +class TanstackQuerySessionManager implements SessionManager { + #session: Session | undefined; + readonly #queryClient: QueryClient; + + constructor(session: Session, queryClient: QueryClient) { + this.#session = session; + this.#queryClient = queryClient; + } + + getSession() { + return this.#session; + } + + clearSession() { + this.#session = undefined; + + this.#queryClient.invalidateQueries({ queryKey: ["/api/session"], refetchType: "inactive" }); + this.#queryClient.invalidateQueries({ queryKey: ["/api/subscription"], refetchType: "inactive" }); + } +} + +export function useSessionManagerInstance(session: Session) { + const queryClient = useQueryClient(); + + return useMemo(() => new TanstackQuerySessionManager(session, queryClient), [session, queryClient]); +} diff --git a/templates/getting-started/apps/host/package.json b/templates/getting-started/apps/host/package.json index 741025c6d..ecef4886d 100644 --- a/templates/getting-started/apps/host/package.json +++ b/templates/getting-started/apps/host/package.json @@ -11,19 +11,19 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "3.0.0", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "eslint": "8.57.0", - "postcss": "8.4.38", - "typescript": "5.4.5", - "webpack": "5.91.0", + "postcss": "8.4.39", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -32,7 +32,9 @@ "@squide/firefly": "8.0.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0" + "react-router-dom": "6.25.1" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/templates/getting-started/apps/host/src/NotFoundPage.tsx b/templates/getting-started/apps/host/src/NotFoundPage.tsx deleted file mode 100644 index bca1b04cd..000000000 --- a/templates/getting-started/apps/host/src/NotFoundPage.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export function NotFoundPage() { - return ( -
        Not found! Please try another page.
        - ); -} diff --git a/templates/getting-started/apps/host/src/RootLayout.tsx b/templates/getting-started/apps/host/src/RootLayout.tsx index 836a129fb..5d593eb57 100644 --- a/templates/getting-started/apps/host/src/RootLayout.tsx +++ b/templates/getting-started/apps/host/src/RootLayout.tsx @@ -1,14 +1,8 @@ -import { - isNavigationLink, - useNavigationItems, - useRenderedNavigationItems, - type RenderItemFunction, - type RenderSectionFunction -} from "@squide/firefly"; +import { isNavigationLink, useFireflyNavigationItems, useRenderedNavigationItems, type RenderItemFunction, type RenderSectionFunction } from "@squide/firefly"; import { Suspense } from "react"; import { Link, Outlet } from "react-router-dom"; -const renderItem: RenderItemFunction = (item, index, level) => { +const renderItem: RenderItemFunction = (item, key) => { // To keep thing simple, this sample doesn't support nested navigation items. // For an example including support for nested navigation items, have a look at // https://gsoft-inc.github.io/wl-squide/reference/routing/userenderednavigationitems/ @@ -19,7 +13,7 @@ const renderItem: RenderItemFunction = (item, index, level) => { const { label, linkProps, additionalProps } = item; return ( -
      • +
      • {label} @@ -27,9 +21,9 @@ const renderItem: RenderItemFunction = (item, index, level) => { ); }; -const renderSection: RenderSectionFunction = (elements, index, level) => { +const renderSection: RenderSectionFunction = (elements, key) => { return ( -
          +
            {elements}
          ); @@ -37,7 +31,7 @@ const renderSection: RenderSectionFunction = (elements, index, level) => { export function RootLayout() { // Retrieve the navigation items registered by the remote modules. - const navigationItems = useNavigationItems(); + const navigationItems = useFireflyNavigationItems(); // Transform the navigation items into React elements. const navigationElements = useRenderedNavigationItems(navigationItems, renderItem, renderSection); diff --git a/templates/getting-started/apps/host/src/register.tsx b/templates/getting-started/apps/host/src/register.tsx index 4ef6f602f..6ef47f302 100644 --- a/templates/getting-started/apps/host/src/register.tsx +++ b/templates/getting-started/apps/host/src/register.tsx @@ -1,6 +1,5 @@ import { ManagedRoutes, type FireflyRuntime, type ModuleRegisterFunction } from "@squide/firefly"; import { HomePage } from "./HomePage.tsx"; -import { NotFoundPage } from "./NotFoundPage.tsx"; import { RootLayout } from "./RootLayout.tsx"; export const registerHost: ModuleRegisterFunction = runtime => { @@ -16,14 +15,6 @@ export const registerHost: ModuleRegisterFunction = runtime => { hoist: true }); - runtime.registerRoute({ - $visibility: "public", - path: "*", - element: - }, { - hoist: true - }); - runtime.registerRoute({ index: true, element: diff --git a/templates/getting-started/apps/local-module/package.json b/templates/getting-started/apps/local-module/package.json index 10881c50b..99bbc77f2 100644 --- a/templates/getting-started/apps/local-module/package.json +++ b/templates/getting-started/apps/local-module/package.json @@ -17,19 +17,21 @@ "build": "tsup --config ./tsup.build.ts" }, "devDependencies": { - "@types/react": "18.3.1", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/eslint-plugin": "3.2.2", "@workleap/tsup-configs": "3.0.6", "eslint": "8.57.0", - "tsup": "8.0.2", - "typescript": "5.4.5" + "tsup": "8.1.2", + "typescript": "5.5.3" }, "dependencies": { "@squide/firefly": "8.0.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0" + "react-router-dom": "6.25.1" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/templates/getting-started/apps/local-module/src/register.tsx b/templates/getting-started/apps/local-module/src/register.tsx index 07e5f6968..e0c898d38 100644 --- a/templates/getting-started/apps/local-module/src/register.tsx +++ b/templates/getting-started/apps/local-module/src/register.tsx @@ -8,6 +8,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "local-page", $label: "Local/Page", to: "/local/page" }); diff --git a/templates/getting-started/apps/remote-module/package.json b/templates/getting-started/apps/remote-module/package.json index b33d5c0e2..c14265edf 100644 --- a/templates/getting-started/apps/remote-module/package.json +++ b/templates/getting-started/apps/remote-module/package.json @@ -11,19 +11,19 @@ }, "devDependencies": { "@squide/firefly-webpack-configs": "3.0.0", - "@swc/core": "1.4.17", - "@swc/helpers": "0.5.11", - "@types/react": "18.3.1", + "@swc/core": "1.7.0", + "@swc/helpers": "0.5.12", + "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@workleap/browserslist-config": "2.0.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/swc-configs": "2.2.3", "@workleap/typescript-configs": "3.0.2", - "browserslist": "4.23.0", + "browserslist": "4.23.2", "eslint": "8.57.0", - "postcss": "8.4.38", - "typescript": "5.4.5", - "webpack": "5.91.0", + "postcss": "8.4.39", + "typescript": "5.5.3", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4" }, @@ -31,7 +31,9 @@ "@squide/firefly": "8.0.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-error-boundary": "4.0.13", - "react-router-dom": "6.23.0" + "react-router-dom": "6.25.1" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/templates/getting-started/apps/remote-module/src/register.tsx b/templates/getting-started/apps/remote-module/src/register.tsx index 6fb02aaa7..44a9da417 100644 --- a/templates/getting-started/apps/remote-module/src/register.tsx +++ b/templates/getting-started/apps/remote-module/src/register.tsx @@ -8,6 +8,7 @@ export const register: ModuleRegisterFunction = runtime => { }); runtime.registerNavigationItem({ + $key: "remote-page", $label: "Remote/Page", to: "/remote/page" }); diff --git a/templates/getting-started/package.json b/templates/getting-started/package.json index 33b6cb366..16cfa22a6 100644 --- a/templates/getting-started/package.json +++ b/templates/getting-started/package.json @@ -15,13 +15,14 @@ "update-outdated-deps": "pnpm update -r --latest !eslint" }, "devDependencies": { - "@typescript-eslint/parser": "7.8.0", + "@typescript-eslint/parser": "7.16.1", "@workleap/eslint-plugin": "3.2.2", "@workleap/typescript-configs": "3.0.2", "eslint": "8.57.0", - "typescript": "5.4.5" + "typescript": "5.5.3" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.0.0", + "pnpm": ">=9" } }