From 3c4e6bc2c3397d5ffc680dc474d4b81044bb94e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20L=C3=A1z=C3=A1r?= Date: Sun, 19 Jan 2025 01:45:01 +0100 Subject: [PATCH] feat: enhanced error handling and a ton of bugfixes showcased in a new example app (#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update brings significant improvements, including a brand-new __Pokémon example app__ designed to demonstrate the framework's enhanced error handling and caching capabilities and to showcase superb performance. In addition to the example app, this PR introduces a series of crucial bug fixes, navigation improvements, and optimizations to both client-side and server-side behavior. A new `Form` navigation component has been introduced to simplify navigation based on form interactions. This component allows developers to trigger navigation based on form submissions or specific input values, without requiring additional event handlers or imperative navigation logic. This enables form-driven navigation patterns where a user’s input can dictate the next page, improving declarative control over navigation behavior. A new mechanism for controlling when client-side navigation triggers revalidation has been added. Previously, navigation could result in unnecessary revalidation of server-side rendering, even in cases where it was not required. This led to excessive network requests and performance overhead. Now, developers can explicitly define revalidation strategies, ensuring that only the relevant components are refreshed based on user interactions or navigation. This fine-grained control allows for more efficient client-side navigation while maintaining consistency. A global error component has been introduced to standardize error handling across applications. Instead of handling errors in multiple locations with redundant logic, applications can now define a centralized error component that gracefully captures and displays errors. This ensures a consistent error experience for users while also simplifying maintenance by reducing duplicated error handling logic. This feature also enables styling unexpected error caught during server-side rendering. Several issues related to module resolution when using `npx` have been addressed. Previously, certain dependencies would not resolve correctly when executed the react-server CLI via `npx`, causing unexpected failures when running commands that relied on specific `@lazarv/react-server` modules. These resolution issues have now been fixed, ensuring that executing commands via `npx` correctly locates and loads the necessary modules without manual intervention. A fix has been applied to server function calls to ensure that `redirect` responses behave correctly. Previously, certain redirect scenarios did not properly propagate the response to the client, resulting in broken navigation flows. This has now been corrected, allowing server functions to issue redirects that are correctly handled by the client. #110 Default CORS configuration has been adjusted to address inconsistencies in handling requests across different origins. The previous implementation had cases where preflight requests were either incorrectly blocked or missing required headers. The fixed configuration usage ensures that cross-origin requests function correctly, particularly for applications interacting with APIs and remote components from different domains. React Server Component network requests have been updated to support credential transmission. This change ensures that cookies are correctly included in all relevant RSC network requests. This improvement allows for more seamless authentication handling without requiring manual workarounds. Support for the `"use cache"` directive has been extended to additional use cases. Previously, this directive was limited in scope and did not fully cover all expected scenarios, particularly when used in certain asynchronous server function calls. These fixes ensure that `"use cache"` now applies more broadly and reliably across different execution contexts, allowing more efficient caching behavior and reducing redundant server computations. Several issues affecting `RemoteComponent` and remote rendering have been addressed. These fixes ensure that remotely loaded components behave consistently, resolving previous issues where rendering states were not properly handled. Remote rendering now correctly handles component hydration using both sync and async React Server Components, preventing unexpected behaviour. File-system based routing has been improved to correctly apply error boundaries at the appropriate levels, particularly for route outlets. Previously, some errors were not caught at the intended boundary, causing them to propagate unintentionally. With this update, errors encountered within a specific route segment are correctly handled by the nearest applicable error boundary, ensuring better application stability and predictable error recovery. The documentation has been updated to include details on the new APIs introduced in this release. This includes explanations of the enhanced error handling system, details on how to use the new `Form` navigation component, and guidelines for configuring client-side navigation revalidation. Additionally, examples have been added to clarify best practices for handling errors at different levels of an application. --- .vscode/settings.json | 4 +- docs/package.json | 4 +- ...n.middleware.mjs => (i18n).middleware.mjs} | 0 .../en/(pages)/router/client-navigation.mdx | 173 +- .../en/(pages)/router/error-handling.mdx | 30 +- examples/mantine/src/pages/layout.tsx | 4 +- examples/photos/src/app/(root).layout.tsx | 4 +- examples/pokemon/package.json | 26 + examples/pokemon/postcss.config.js | 6 + examples/pokemon/react-server.config.json | 3 + examples/pokemon/src/app/(404).[...slug].tsx | 16 + examples/pokemon/src/app/@modal/[id].tsx | 92 + examples/pokemon/src/app/@modal/error.tsx | 3 + examples/pokemon/src/app/@modal/loading.tsx | 39 + examples/pokemon/src/app/@view/[[id]].tsx | 132 ++ examples/pokemon/src/app/@view/error.tsx | 3 + examples/pokemon/src/app/error.tsx | 3 + examples/pokemon/src/app/global.css | 71 + examples/pokemon/src/app/layout.tsx | 58 + examples/pokemon/src/app/loading.tsx | 29 + examples/pokemon/src/app/page.tsx | 17 + .../pokemon/src/app/react-server.error.tsx | 31 + examples/pokemon/src/components/Button.tsx | 23 + .../pokemon/src/components/ClearSearch.tsx | 22 + .../pokemon/src/components/ErrorButton.tsx | 23 + .../pokemon/src/components/ErrorMessage.tsx | 28 + examples/pokemon/src/components/FormInput.tsx | 27 + examples/pokemon/src/components/Html.tsx | 12 + examples/pokemon/src/components/KeyLink.tsx | 57 + .../pokemon/src/components/Modal.module.css | 20 + examples/pokemon/src/components/Modal.tsx | 94 + examples/pokemon/src/components/Search.tsx | 34 + examples/pokemon/src/components/TimeAgo.tsx | 97 + examples/pokemon/src/lib/pokemon.ts | 153 ++ examples/pokemon/src/lib/utils.ts | 14 + examples/pokemon/tailwind.config.js | 11 + examples/pokemon/tsconfig.json | 18 + examples/pokemon/vite.config.mjs | 9 + .../remote/react-server.production.config.mjs | 4 +- examples/session-cookie/App.jsx | 24 + examples/session-cookie/actions/user.mjs | 9 + examples/session-cookie/components/login.jsx | 23 + examples/session-cookie/components/logout.jsx | 23 + .../session-cookie/components/newuser.jsx | 19 + examples/session-cookie/misc/cookies.mjs | 20 + examples/session-cookie/misc/session.mjs | 4 + examples/session-cookie/package.json | 17 + .../session-cookie/react-server.config.json | 5 + package.json | 2 +- .../react-server/client/ClientProvider.jsx | 373 +++- .../react-server/client/ErrorBoundary.jsx | 120 +- packages/react-server/client/Form.jsx | 78 + packages/react-server/client/Link.jsx | 65 +- .../client/ReactServerComponent.jsx | 184 +- packages/react-server/client/Refresh.jsx | 67 +- packages/react-server/client/context.mjs | 18 +- packages/react-server/client/entry.client.jsx | 236 +- packages/react-server/client/index.d.ts | 65 +- packages/react-server/client/index.jsx | 2 +- packages/react-server/client/location.mjs | 16 +- packages/react-server/client/navigation.d.ts | 82 +- packages/react-server/client/navigation.jsx | 3 +- packages/react-server/lib/build/client.mjs | 31 + packages/react-server/lib/build/server.mjs | 110 +- packages/react-server/lib/build/static.mjs | 6 +- packages/react-server/lib/dev/action.mjs | 1 - .../react-server/lib/dev/create-server.mjs | 64 +- packages/react-server/lib/dev/modules.mjs | 26 +- .../react-server/lib/dev/render-stream.mjs | 2 +- packages/react-server/lib/dev/ssr-handler.mjs | 73 +- packages/react-server/lib/handlers/error.mjs | 101 +- .../lib/plugins/file-router/entrypoint.jsx | 133 +- .../lib/plugins/file-router/plugin.mjs | 122 +- .../file-router/react-server-router.d.ts | 47 +- .../lib/plugins/optimize-deps.mjs | 3 +- .../lib/plugins/use-cache-inline.mjs | 86 +- .../react-server/lib/plugins/use-client.mjs | 3 +- .../react-server/lib/start/create-server.mjs | 12 +- packages/react-server/lib/start/manifest.mjs | 4 +- .../react-server/lib/start/ssr-handler.mjs | 72 +- packages/react-server/memory-cache/index.mjs | 27 +- .../react-server/server/ErrorBoundary.jsx | 10 +- packages/react-server/server/GlobalError.jsx | 77 + .../react-server/server/RemoteComponent.jsx | 15 +- .../server/client-reference-map.mjs | 2 +- packages/react-server/server/dom-flight.mjs | 8 +- .../react-server/server/error-boundary.d.ts | 9 +- .../react-server/server/error-handler.mjs | 31 + packages/react-server/server/error-styles.mjs | 47 + packages/react-server/server/redirects.mjs | 7 +- packages/react-server/server/render-dom.mjs | 53 +- packages/react-server/server/render-rsc.jsx | 153 +- packages/react-server/server/render.mjs | 7 +- packages/react-server/server/symbols.mjs | 3 + pnpm-lock.yaml | 1913 +++++++++-------- test/__test__/apps/mantine.spec.mjs | 6 +- test/__test__/apps/pokemon.spec.mjs | 14 + test/__test__/apps/session-cookie.spec.mjs | 54 + test/__test__/error-boundary.spec.mjs | 16 +- test/vitestGlobalSetup.mjs | 19 +- test/vitestSetup.mjs | 14 + 101 files changed, 4868 insertions(+), 1362 deletions(-) rename docs/src/pages/{i18n.middleware.mjs => (i18n).middleware.mjs} (100%) create mode 100644 examples/pokemon/package.json create mode 100644 examples/pokemon/postcss.config.js create mode 100644 examples/pokemon/react-server.config.json create mode 100644 examples/pokemon/src/app/(404).[...slug].tsx create mode 100644 examples/pokemon/src/app/@modal/[id].tsx create mode 100644 examples/pokemon/src/app/@modal/error.tsx create mode 100644 examples/pokemon/src/app/@modal/loading.tsx create mode 100644 examples/pokemon/src/app/@view/[[id]].tsx create mode 100644 examples/pokemon/src/app/@view/error.tsx create mode 100644 examples/pokemon/src/app/error.tsx create mode 100644 examples/pokemon/src/app/global.css create mode 100644 examples/pokemon/src/app/layout.tsx create mode 100644 examples/pokemon/src/app/loading.tsx create mode 100644 examples/pokemon/src/app/page.tsx create mode 100644 examples/pokemon/src/app/react-server.error.tsx create mode 100644 examples/pokemon/src/components/Button.tsx create mode 100644 examples/pokemon/src/components/ClearSearch.tsx create mode 100644 examples/pokemon/src/components/ErrorButton.tsx create mode 100644 examples/pokemon/src/components/ErrorMessage.tsx create mode 100644 examples/pokemon/src/components/FormInput.tsx create mode 100644 examples/pokemon/src/components/Html.tsx create mode 100644 examples/pokemon/src/components/KeyLink.tsx create mode 100644 examples/pokemon/src/components/Modal.module.css create mode 100644 examples/pokemon/src/components/Modal.tsx create mode 100644 examples/pokemon/src/components/Search.tsx create mode 100644 examples/pokemon/src/components/TimeAgo.tsx create mode 100644 examples/pokemon/src/lib/pokemon.ts create mode 100644 examples/pokemon/src/lib/utils.ts create mode 100644 examples/pokemon/tailwind.config.js create mode 100644 examples/pokemon/tsconfig.json create mode 100644 examples/pokemon/vite.config.mjs create mode 100644 examples/session-cookie/App.jsx create mode 100644 examples/session-cookie/actions/user.mjs create mode 100644 examples/session-cookie/components/login.jsx create mode 100644 examples/session-cookie/components/logout.jsx create mode 100644 examples/session-cookie/components/newuser.jsx create mode 100644 examples/session-cookie/misc/cookies.mjs create mode 100644 examples/session-cookie/misc/session.mjs create mode 100644 examples/session-cookie/package.json create mode 100644 examples/session-cookie/react-server.config.json create mode 100644 packages/react-server/client/Form.jsx create mode 100644 packages/react-server/server/GlobalError.jsx create mode 100644 packages/react-server/server/error-handler.mjs create mode 100644 packages/react-server/server/error-styles.mjs create mode 100644 test/__test__/apps/pokemon.spec.mjs create mode 100644 test/__test__/apps/session-cookie.spec.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index f36fb3c..44dcda4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,7 @@ "editor.codeActionsOnSave": { "source.organizeImports": "never" } - } + }, + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" } diff --git a/docs/package.json b/docs/package.json index 55b2009..8848f23 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,8 +13,8 @@ "@lazarv/react-server": "workspace:^", "@lazarv/react-server-adapter-vercel": "workspace:^", "@uidotdev/usehooks": "^2.4.1", - "@vercel/analytics": "^1.3.1", - "@vercel/speed-insights": "^1.0.12", + "@vercel/analytics": "^1.4.1", + "@vercel/speed-insights": "^1.1.0", "@vitejs/plugin-react-swc": "^3.7.0", "algoliasearch": "^4.24.0", "highlight.js": "^11.9.0", diff --git a/docs/src/pages/i18n.middleware.mjs b/docs/src/pages/(i18n).middleware.mjs similarity index 100% rename from docs/src/pages/i18n.middleware.mjs rename to docs/src/pages/(i18n).middleware.mjs diff --git a/docs/src/pages/en/(pages)/router/client-navigation.mdx b/docs/src/pages/en/(pages)/router/client-navigation.mdx index 8c932a6..7c8fa7a 100644 --- a/docs/src/pages/en/(pages)/router/client-navigation.mdx +++ b/docs/src/pages/en/(pages)/router/client-navigation.mdx @@ -165,6 +165,25 @@ export default function Home() { } ``` + +## Form + + +You can navigate to a new page by using the `Form` client component exported by the `@lazarv/react-server/navigation` module. This component will navigate to the current route on form submit using form data as the query parameters. + +```jsx +import { Form } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ + +
+ ); +} +``` + ## Outlet @@ -216,11 +235,11 @@ Using both `defer` and `url` props on the `ReactServerComponent` you can achieve The `useClient` hook returns an object with the following properties: -- `navigate(url: string, options: { rollback?: number })`: A function that navigates to a new page. The `rollback` option allows you to cache the current page for a specified amount of time. -- `replace(url: string, options: { rollback?: number })`: A function that replaces the current page with a new page. The `rollback` option allows you to cache the current page for a specified amount of time. -- `prefetch(url: string, options: { ttl?: number })`: A function that prefetches a page. The `ttl` option allows you to cache the page for a specified amount of time. -- `refresh()`: A function that refreshes the current page. - +- `navigate(url: string, options: { outlet?: string; push?: boolean; rollback?: number; signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that navigates to a new page or the specified outlet. The `rollback` option allows you to cache the current page for a specified amount of time. +- `replace(url: string, options: { outlet?: string; rollback?: number; signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that replaces the current page with a new page or the content of the specified outlet. The `rollback` option allows you to cache the current page for a specified amount of time. +- `prefetch(url: string, options: { outlet?: string; ttl?: number; signal?: AbortSignal })`: A function that prefetches a page or the content of the specified outlet. The `ttl` option allows you to cache the page for a specified amount of time. +- `refresh(outlet?: string, options: { signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that refreshes the current page or the content of the specified outlet. +- `abort(outlet?: string, reason?: unknown)`: A function that aborts navigation of the specified outlet. You can use these functions for programmatic navigation. ```jsx @@ -246,4 +265,146 @@ export default function Home() { ); } -``` \ No newline at end of file +``` + + +## useOutlet + + +The `useOutlet` hook returns a set of functions to interact with the current outlet. These functions are the same as the ones returned by the `useClient` hook, but you don't need to specify the `outlet` option. In the example below, the `navigate` function is scoped to the current outlet, not the entire page. But if the current outlet is the root outlet, the `navigate` function will navigate to the entire page. + +```jsx +"use client"; + +import { useOutlet } from "@lazarv/react-server/client"; + +export default function Home() { + const { navigate } = useOutlet(); + + return ( +
+ +
+ ); +} +``` + + +### Fallback + + +The `fallback` option on the `Link` and `Refresh` components allows you to specify a fallback component to render until the outlet starts to render the React Server Component. This can be useful when you want to render a loading indicator or a skeleton while the React Server Component is being rendered immediately, without waiting for the React Server Component request to reach the server. + +```jsx +import { Link } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ Loading...
}>About + + ); +} +``` + +You can also specify the `fallback` option when navigating programmatically with the `navigate` or `replace` functions. + +```jsx +import { useClient } from "@lazarv/react-server/client"; + +export default function Home() { + const { navigate } = useClient(); + + return ( +
+ +
+ ); +} +``` + + +### Component + + +The `Component` option on the `Link` and `Refresh` components allows you to specify a React component to render. This can be useful when you want to render a React component directly in the outlet instead of making a request to the server. + +```jsx +import { Link } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ About
}>About + + ); +} +``` + +You can also specify the `Component` option when navigating programmatically with the `navigate` or `replace` functions. + +```jsx +import { useClient } from "@lazarv/react-server/client"; + +export default function Home() { + const { navigate } = useClient(); + + return ( +
+ +
+ ); +} +``` + + +### Using revalidate + + +You can use the `revalidate` prop on the `Link`, `Refresh` and `Form` components to control client-side caching of the page or content of the specified outlet. The `revalidate` prop can accept a number which represents the number of milliseconds the page or outlet will be cached for the target URL. After the timeout expires, the page will be removed from the cache and the next time the user navigates to the page, the page will be rendered again by fetching the content from the server rendering the React Server Component. + +By default, the `revalidate` prop is not set, which means that the page or outlet will not be cached at all, and every navigation will fetch the content from the server. + +```jsx +import { Link } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ About +
+ ); +} +``` + +You can disable revalidation by passing `false` to the `revalidate` prop. By disabling revalidation, the page or outlet will be cached indefinitely. + +```jsx +import { Link } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ About +
+ ); +} +``` + +You can also fully customize the logic for revalidation by passing a function to the `revalidate` prop. The function will receive a context object including the `outlet`, the target `url` and the `timestamp` of the cached content. The function should return a boolean indicating whether the content should be revalidated. + +```jsx +"use client"; + +import { Link } from "@lazarv/react-server/navigation"; + +export default function Home() { + return ( +
+ { + return Math.random() > 0.5; + }}>About +
+ ); +} +``` diff --git a/docs/src/pages/en/(pages)/router/error-handling.mdx b/docs/src/pages/en/(pages)/router/error-handling.mdx index 28dac08..6094a82 100644 --- a/docs/src/pages/en/(pages)/router/error-handling.mdx +++ b/docs/src/pages/en/(pages)/router/error-handling.mdx @@ -38,4 +38,32 @@ export default function FallbackError({ error }) { } ``` -> **Warning:** you can define an error boundary, error fallback or loading component only for layouts, not for pages. \ No newline at end of file +> **Warning:** you can define an error boundary, error fallback or loading component only for layouts, not for pages. + + +## Global error component + + +By default, the global error component is the first `react-server.error.jsx` or `react-server.error.tsx` file found from the root of your app. This component will be used to render the error component when an error occurs during the rendering of a page and no error component is defined for the error. + +Your global error component will be used for all errors that are not handled by a more specific error component. The error component will receive the error as a prop. + +```jsx +// src/app/react-server.error.tsx +export default function GlobalError({ error }: { error: Error }) { + return
{error.message}
; +} +``` + +Optionally, you can specify the global error component in the `react-server.config.json` file. You only need to specify the path to the file when you want to use a file that is not named `react-server.error.jsx` or `react-server.error.tsx`, like `global-error.tsx` or similar, or when you want to use a file specifically for the global error component and not the first the framework can find with the default name. + +```jsx +// react-server.config.json +{ + "globalErrorComponent": "src/app/react-server.error.tsx" +} +``` + +Your global error component can be a React Server Component or a client component. When it's a client component, it will be rendered on the client side using a React error boundary, while if it's a React Server Component, it will be rendered on the server side only. + +> **Warning:** you can't reset a global error boundary! The page needs to be reloaded to reset the error boundary. Use the `Refresh` component to reload the page using the React Server Component payload. It's recommended to use the `noCache` prop on the `Refresh` component to avoid caching issues. diff --git a/examples/mantine/src/pages/layout.tsx b/examples/mantine/src/pages/layout.tsx index 27df395..0b6b416 100644 --- a/examples/mantine/src/pages/layout.tsx +++ b/examples/mantine/src/pages/layout.tsx @@ -15,11 +15,11 @@ export default function Layout({ children }: { children: React.ReactNode }) { const pathname = usePathname(); return ( - + - + diff --git a/examples/photos/src/app/(root).layout.tsx b/examples/photos/src/app/(root).layout.tsx index 3042961..eff103b 100644 --- a/examples/photos/src/app/(root).layout.tsx +++ b/examples/photos/src/app/(root).layout.tsx @@ -10,7 +10,7 @@ export default function Layout({ modal: React.ReactNode; }>) { return ( - + Photos @@ -20,7 +20,7 @@ export default function Layout({ /> - + {children} {modal} diff --git a/examples/pokemon/package.json b/examples/pokemon/package.json new file mode 100644 index 0000000..108cdc8 --- /dev/null +++ b/examples/pokemon/package.json @@ -0,0 +1,26 @@ +{ + "name": "@lazarv/react-server-example-pokemon", + "private": true, + "description": "React Server Pokemon example application", + "scripts": { + "dev": "react-server", + "build": "react-server build", + "start": "react-server start" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@lazarv/react-server": "workspace:^", + "clsx": "^2.1.1", + "tailwind-merge": "^2.6.0" + }, + "devDependencies": { + "@types/react": "^18.3.2", + "@types/react-dom": "^18.3.0", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.3", + "vite": "6.0.0-alpha.18" + } +} diff --git a/examples/pokemon/postcss.config.js b/examples/pokemon/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/examples/pokemon/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/examples/pokemon/react-server.config.json b/examples/pokemon/react-server.config.json new file mode 100644 index 0000000..d38fd6e --- /dev/null +++ b/examples/pokemon/react-server.config.json @@ -0,0 +1,3 @@ +{ + "root": "src/app" +} diff --git a/examples/pokemon/src/app/(404).[...slug].tsx b/examples/pokemon/src/app/(404).[...slug].tsx new file mode 100644 index 0000000..8efb625 --- /dev/null +++ b/examples/pokemon/src/app/(404).[...slug].tsx @@ -0,0 +1,16 @@ +import { status } from "@lazarv/react-server"; +import { Link } from "@lazarv/react-server/navigation"; + +export default function NotFound() { + status(404); + + return ( +
+

Not Found

+

The page you are looking for does not exist.

+ + Go back to the home page + +
+ ); +} diff --git a/examples/pokemon/src/app/@modal/[id].tsx b/examples/pokemon/src/app/@modal/[id].tsx new file mode 100644 index 0000000..a2b436e --- /dev/null +++ b/examples/pokemon/src/app/@modal/[id].tsx @@ -0,0 +1,92 @@ +import { getPokemonDetails } from "@/lib/pokemon"; + +export const ttl = 24 * 60 * 60 * 1000; + +export default async function PokemonDetails({ id }: { id: string }) { + const pokemon = await getPokemonDetails(id); + + if (!pokemon) { + return ( +
+

Not Found

+

The requested Pokémon was not found.

+
+ ); + } + + return ( +
+
+

{pokemon.name}

+

#{pokemon.id}

+
+
+
+

Species

+

+ { + pokemon.species.flavor_text_entries.find( + ({ language }) => language.name === "en" + )?.flavor_text + } +

+ {pokemon.species.form_descriptions.find( + ({ language }) => language.name === "en" + ) && ( + <> +

Forms

+

+ { + pokemon.species.form_descriptions.find( + ({ language }) => language.name === "en" + )?.description + } +

+ + )} +

Height

+

{pokemon.height}

+

Weight

+

{pokemon.weight}

+

Base Experience

+

{pokemon.base_experience}

+

Abilities

+ {pokemon.abilities.map((ability) => ( +
+
+ { + ability.names.find(({ language }) => language.name === "en") + ?.name + } +
+

+ { + ability.effect_entries.find( + ({ language }) => language.name === "en" + )?.effect + } +

+
+ ))} +

Types

+

+ {pokemon.types + .map( + (type) => + type.names.find(({ language }) => language.name === "en") + ?.name + ) + .join(", ")} +

+
+
+ {pokemon.name} +
+
+
+ ); +} diff --git a/examples/pokemon/src/app/@modal/error.tsx b/examples/pokemon/src/app/@modal/error.tsx new file mode 100644 index 0000000..c884a6f --- /dev/null +++ b/examples/pokemon/src/app/@modal/error.tsx @@ -0,0 +1,3 @@ +"use client"; + +export { default } from "@/components/ErrorMessage"; diff --git a/examples/pokemon/src/app/@modal/loading.tsx b/examples/pokemon/src/app/@modal/loading.tsx new file mode 100644 index 0000000..820bf87 --- /dev/null +++ b/examples/pokemon/src/app/@modal/loading.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { createPortal } from "react-dom"; + +import { ClientOnly } from "@lazarv/react-server/client"; + +export default function Loading() { + const fallback = ( +
+ Loading... +
+ ); + + if (typeof document === "undefined") { + return fallback; + } + + return ( + <> + {fallback} + + {createPortal( +
+ {[...Array(3)].map((_, i) => ( +
+ ))} +
, + document.body + )} + + + ); +} diff --git a/examples/pokemon/src/app/@view/[[id]].tsx b/examples/pokemon/src/app/@view/[[id]].tsx new file mode 100644 index 0000000..52f9f21 --- /dev/null +++ b/examples/pokemon/src/app/@view/[[id]].tsx @@ -0,0 +1,132 @@ +import ModalLoading from "@/app/@modal/loading"; +import ViewLoading from "@/app/loading"; +import Button from "@/components/Button"; +import KeyLink from "@/components/KeyLink"; +import { getPokemons } from "@/lib/pokemon"; +import { applySearchParams } from "@/lib/utils"; +import { useSearchParams } from "@lazarv/react-server"; +import { Link } from "@lazarv/react-server/navigation"; + +export const ttl = 24 * 60 * 60 * 1000; + +export default async function View() { + const { search, offset: offsetParam, limit: limitParam } = useSearchParams(); + const offset = Number(offsetParam) || 0; + const limit = Number(limitParam) || 10; + const currentPage = getPokemons((search as string) ?? "", offset, limit); + const prevPage = + offset > 0 + ? getPokemons( + (search as string) ?? "", + Math.max(0, offset - limit), + limit + ) + : Promise.resolve({ data: [], count: 0 }); + const nextPage = getPokemons( + (search as string) ?? "", + offset + 0 + limit, + limit + ); + const [{ data: prevData }, { data, count }, { data: nextData }] = + await Promise.all([prevPage, currentPage, nextPage]); + const prefetchData = [...prevData, ...data, ...nextData]; + + return ( + <> + {prefetchData.map((pokemon) => ( + + ))} +
+
+ {data?.map((pokemon, index) => ( + } + tabIndex={-1} + > +
+

+ {pokemon.name} +

+ {pokemon.sprites.front_default ? ( + {pokemon.name} + ) : ( +
+ )} +
+ #{pokemon.id} +
+
+ + ))} +
+
+
+ 0 + ? `?${applySearchParams({ + offset: Math.max(0, offset - limit), + limit, + })}` + : "#" + } + prefetch + revalidate={false} + eventKey="ArrowLeft" + target="view" + fallback={} + tabIndex={-1} + > + + + + {offset + 1} -{" "} + {offset + data?.length} of {count} + + } + tabIndex={-1} + > + + +
+ + ); +} diff --git a/examples/pokemon/src/app/@view/error.tsx b/examples/pokemon/src/app/@view/error.tsx new file mode 100644 index 0000000..c884a6f --- /dev/null +++ b/examples/pokemon/src/app/@view/error.tsx @@ -0,0 +1,3 @@ +"use client"; + +export { default } from "@/components/ErrorMessage"; diff --git a/examples/pokemon/src/app/error.tsx b/examples/pokemon/src/app/error.tsx new file mode 100644 index 0000000..c884a6f --- /dev/null +++ b/examples/pokemon/src/app/error.tsx @@ -0,0 +1,3 @@ +"use client"; + +export { default } from "@/components/ErrorMessage"; diff --git a/examples/pokemon/src/app/global.css b/examples/pokemon/src/app/global.css new file mode 100644 index 0000000..e1b9199 --- /dev/null +++ b/examples/pokemon/src/app/global.css @@ -0,0 +1,71 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +.pixelated { + image-rendering: pixelated; +} + +@keyframes dotFade { + 0%, + 100% { + opacity: 0; + transform: scale(0.8); + } + 50% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes slideFromRight { + from { + transform: translateX(100%); + } + to { + transform: translateX(0); + } +} + +@keyframes itemEnter { + 0% { + opacity: 0; + transform: scale(0.5); + } + 75% { + opacity: 0.75; + transform: scale(1.05); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +.fade-in { + animation: fadeIn 0.5s ease-in-out; +} + +.slide-from-right { + animation: slideFromRight 0.2s ease-in-out; +} + +.item-enter { + animation: itemEnter 0.2s ease-in-out forwards; +} + +@media (prefers-reduced-motion: reduce) { + .item-enter { + animation: none !important; + opacity: 1; + } +} diff --git a/examples/pokemon/src/app/layout.tsx b/examples/pokemon/src/app/layout.tsx new file mode 100644 index 0000000..6febbf0 --- /dev/null +++ b/examples/pokemon/src/app/layout.tsx @@ -0,0 +1,58 @@ +import "./global.css"; + +import Html from "@/components/Html"; +import Modal from "@/components/Modal"; +import TimeAgo from "@/components/TimeAgo"; +import { ReactServerComponent, Refresh } from "@lazarv/react-server/navigation"; +import { useMatch } from "@lazarv/react-server/router"; + +export default async function Layout({ + modal, + children, +}: { + modal: React.ReactNode; + children: React.ReactNode; +}) { + const hasRefresh = useMatch("/", { exact: true }); + + return ( + +
+
+

Pokémon Catalog

+ {hasRefresh && ( +
+ + + + + +
+
+ +
+
+
+ )} +
+
+ {children} + + {modal} + +
+
+ + ); +} diff --git a/examples/pokemon/src/app/loading.tsx b/examples/pokemon/src/app/loading.tsx new file mode 100644 index 0000000..514e999 --- /dev/null +++ b/examples/pokemon/src/app/loading.tsx @@ -0,0 +1,29 @@ +export default function Loading() { + return ( +
+
+ + + + +

Loading...

+
+
+ ); +} diff --git a/examples/pokemon/src/app/page.tsx b/examples/pokemon/src/app/page.tsx new file mode 100644 index 0000000..f7e40f1 --- /dev/null +++ b/examples/pokemon/src/app/page.tsx @@ -0,0 +1,17 @@ +import Search from "@/components/Search"; +import { ReactServerComponent } from "@lazarv/react-server/navigation"; + +import View from "./@view/[[id]]"; + +export const ttl = 24 * 60 * 60 * 1000; + +export default async function Page() { + const view = await View(); + + return ( + <> + + {view} + + ); +} diff --git a/examples/pokemon/src/app/react-server.error.tsx b/examples/pokemon/src/app/react-server.error.tsx new file mode 100644 index 0000000..a54652b --- /dev/null +++ b/examples/pokemon/src/app/react-server.error.tsx @@ -0,0 +1,31 @@ +"use client"; + +import ErrorButton from "@/components/ErrorButton"; +import Html from "@/components/Html"; +import { type ErrorBoundaryComponentProps } from "@lazarv/react-server/error-boundary"; +import { Refresh } from "@lazarv/react-server/navigation"; + +export default function GlobalError({ error }: ErrorBoundaryComponentProps) { + return ( + +
+
+

+ {error.digest && error.digest !== error.message + ? error.digest + : error.message || "Global Error"} +

+

An error occurred while loading the page.

+ {error.stack && ( +
+              {error?.stack}
+            
+ )} + + Retry + +
+
+ + ); +} diff --git a/examples/pokemon/src/components/Button.tsx b/examples/pokemon/src/components/Button.tsx new file mode 100644 index 0000000..58e8d8f --- /dev/null +++ b/examples/pokemon/src/components/Button.tsx @@ -0,0 +1,23 @@ +import clsx from "clsx"; +import { twMerge } from "tailwind-merge"; + +export default function Button({ + className, + children, + ...props +}: React.PropsWithChildren>) { + return ( + + ); +} diff --git a/examples/pokemon/src/components/ClearSearch.tsx b/examples/pokemon/src/components/ClearSearch.tsx new file mode 100644 index 0000000..f36d916 --- /dev/null +++ b/examples/pokemon/src/components/ClearSearch.tsx @@ -0,0 +1,22 @@ +"use client"; + +export function ClearSearch() { + return ( + + ); +} diff --git a/examples/pokemon/src/components/ErrorButton.tsx b/examples/pokemon/src/components/ErrorButton.tsx new file mode 100644 index 0000000..1b97acb --- /dev/null +++ b/examples/pokemon/src/components/ErrorButton.tsx @@ -0,0 +1,23 @@ +import clsx from "clsx"; +import { twMerge } from "tailwind-merge"; + +export default function ErrorButton({ + className, + children, + ...props +}: React.PropsWithChildren>) { + return ( + + ); +} diff --git a/examples/pokemon/src/components/ErrorMessage.tsx b/examples/pokemon/src/components/ErrorMessage.tsx new file mode 100644 index 0000000..679397f --- /dev/null +++ b/examples/pokemon/src/components/ErrorMessage.tsx @@ -0,0 +1,28 @@ +"use client"; + +import ErrorButton from "@/components/ErrorButton"; +import { type ErrorBoundaryComponentProps } from "@lazarv/react-server/error-boundary"; + +export default function Error({ + error, + resetErrorBoundary, +}: ErrorBoundaryComponentProps) { + return ( +
+
+

+ {error.digest && error.digest !== error.message + ? error.digest + : error.message || "Error"} +

+

An error occurred while loading the page.

+ {error.stack && ( +
+            {error.stack}
+          
+ )} + Retry +
+
+ ); +} diff --git a/examples/pokemon/src/components/FormInput.tsx b/examples/pokemon/src/components/FormInput.tsx new file mode 100644 index 0000000..9d6d65a --- /dev/null +++ b/examples/pokemon/src/components/FormInput.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +export default function FormInput( + props: React.InputHTMLAttributes +) { + const timeoutId = useRef(); + const formRef = useRef(null); + const ref = useRef(null); + + useEffect(() => { + formRef.current = ref?.current?.closest("form") ?? null; + }, [ref]); + + const handleChange = () => { + if (timeoutId.current) { + clearTimeout(timeoutId.current); + } + + timeoutId.current = setTimeout(() => { + formRef.current?.requestSubmit(); + }, 200); + }; + + return ; +} diff --git a/examples/pokemon/src/components/Html.tsx b/examples/pokemon/src/components/Html.tsx new file mode 100644 index 0000000..3bbd91d --- /dev/null +++ b/examples/pokemon/src/components/Html.tsx @@ -0,0 +1,12 @@ +export default function Html({ children }: { children: React.ReactNode }) { + return ( + + + + + Pokémon Catalog + + {children} + + ); +} diff --git a/examples/pokemon/src/components/KeyLink.tsx b/examples/pokemon/src/components/KeyLink.tsx new file mode 100644 index 0000000..11b719d --- /dev/null +++ b/examples/pokemon/src/components/KeyLink.tsx @@ -0,0 +1,57 @@ +"use client"; + +import { useEffect } from "react"; + +import { useClient } from "@lazarv/react-server/client"; +import { Link, type LinkProps } from "@lazarv/react-server/navigation"; + +export default function KeyLink({ + to, + eventKey, + target, + fallback, + revalidate, + children, + ...props +}: LinkProps<__react_server_routing__.RouteImpl> & { eventKey: string }) { + const { navigate } = useClient(); + + useEffect(() => { + const abortController = new AbortController(); + + document.addEventListener( + "keydown", + (event) => { + if ( + document.activeElement?.tagName !== "INPUT" && + event.key === eventKey && + to !== "#" && + (to === "/" || (to !== "/" && !location.href.includes(to))) + ) { + navigate(to, { + outlet: target, + push: true, + fallback, + revalidate, + }); + } + }, + { signal: abortController.signal } + ); + + return () => abortController.abort(); + }, [to]); + + return ( + + {children} + + ); +} diff --git a/examples/pokemon/src/components/Modal.module.css b/examples/pokemon/src/components/Modal.module.css new file mode 100644 index 0000000..f9a99ea --- /dev/null +++ b/examples/pokemon/src/components/Modal.module.css @@ -0,0 +1,20 @@ +.content { + @apply block fixed inset-x-8 sm:inset-x-10 md:inset-x-20 lg:inset-x-40 xl:inset-x-1/4 top-20 max-h-[calc(100vh-10rem)] bg-white rounded-lg shadow-lg overflow-auto z-30 transition-all duration-300; +} + +.content:not(:empty)::after { + @apply content-[''] block sticky bottom-0 w-full h-8 bg-gradient-to-t from-white; +} + +.content:empty, +.content.closing { + @apply opacity-0 translate-y-[100vh] pointer-events-none; +} + +.overlay { + @apply fixed inset-0 z-20 opacity-0 transition-all duration-300 pointer-events-none; +} + +.content:not(:empty):not(.closing) + .overlay { + @apply bg-black opacity-50 pointer-events-auto; +} diff --git a/examples/pokemon/src/components/Modal.tsx b/examples/pokemon/src/components/Modal.tsx new file mode 100644 index 0000000..713613f --- /dev/null +++ b/examples/pokemon/src/components/Modal.tsx @@ -0,0 +1,94 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +import { useClient } from "@lazarv/react-server/client"; + +import classes from "./Modal.module.css"; + +export default function Modal({ children }: { children: React.ReactNode }) { + const { navigate } = useClient(); + const contentRef = useRef(null); + const closableRef = useRef(false); + + useEffect(() => { + const content = contentRef.current; + if (!content) return; + + const observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + if (mutation.type === "childList") { + content.classList.remove(classes.closing); + } + } + }); + + observer.observe(content, { + childList: true, + subtree: true, + }); + + return () => observer.disconnect(); + }, []); + + useEffect(() => { + const abortController = new AbortController(); + + contentRef.current?.addEventListener( + "transitionend", + () => { + if (!contentRef.current?.classList.contains(classes.closing)) { + closableRef.current = true; + } + }, + { signal: abortController.signal } + ); + + return () => abortController.abort(); + }, [contentRef.current]); + + const closeModal = async () => { + if (!closableRef.current) return; + + await new Promise((resolve) => { + contentRef.current?.addEventListener("transitionend", resolve, { + once: true, + }); + contentRef.current?.classList.add(classes.closing); + closableRef.current = false; + }); + navigate("/", { + outlet: "modal", + Component: null, + }); + }; + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") closeModal(); + }; + + useEffect(() => { + const abortController = new AbortController(); + + document.addEventListener("keydown", handleKeyDown, { + signal: abortController.signal, + }); + + return () => abortController.abort(); + }, []); + + return ( + <> +
+ {children} +
+
handleKeyDown(e.nativeEvent)} + role="button" + tabIndex={-1} + /> + + ); +} diff --git a/examples/pokemon/src/components/Search.tsx b/examples/pokemon/src/components/Search.tsx new file mode 100644 index 0000000..5fca58f --- /dev/null +++ b/examples/pokemon/src/components/Search.tsx @@ -0,0 +1,34 @@ +import FormInput from "@/components/FormInput"; +import { useSearchParams } from "@lazarv/react-server"; +import { Form } from "@lazarv/react-server/navigation"; + +import { ClearSearch } from "./ClearSearch"; + +export default function Search() { + const { search } = useSearchParams(); + + return ( +
+ +
+ + +
+
+ ); +} diff --git a/examples/pokemon/src/components/TimeAgo.tsx b/examples/pokemon/src/components/TimeAgo.tsx new file mode 100644 index 0000000..73c5c15 --- /dev/null +++ b/examples/pokemon/src/components/TimeAgo.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { useEffect, useState } from "react"; + +import { ClientOnly } from "@lazarv/react-server/client"; + +const intervals = { + year: 31536000, + month: 2592000, + week: 604800, + day: 86400, + hour: 3600, + minute: 60, + second: 1, +}; + +function timeAgo(date: Date, locale = "en") { + const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" }); + + const now = Date.now(); + const diffInSeconds = Math.floor((date.getTime() - now) / 1000); + + for (const [unit, secondsInUnit] of Object.entries(intervals)) { + if (Math.abs(diffInSeconds) >= secondsInUnit || unit === "second") { + const value = Math.round((diffInSeconds + 1) / secondsInUnit); + return rtf.format(value, unit as Intl.RelativeTimeFormatUnit); + } + } + + return "just now"; +} + +async function timeAgoInterval( + date: Date, + { signal }: { signal: AbortSignal } +) { + const now = Date.now(); + const diffInSeconds = Math.floor((date.getTime() - now) / 1000); + + let interval = 1000; + for (const secondsInUnit of Object.values(intervals)) { + if (Math.abs(diffInSeconds) >= secondsInUnit) { + interval = secondsInUnit * 1000; + break; + } + } + + await new Promise((resolve) => { + const timeoutId = setTimeout(resolve, interval); + signal.addEventListener( + "abort", + () => { + clearTimeout(timeoutId); + resolve(null); + }, + { once: true } + ); + }); + + if (!signal.aborted) { + return timeAgo(date); + } +} + +function TimeAgoRealTime({ date }: { date: Date }) { + const [value, setValue] = useState(timeAgo(date)); + + useEffect(() => { + const abortController = new AbortController(); + + (async () => { + while (true) { + const result = await timeAgoInterval(date, { + signal: abortController.signal, + }); + + if (!result) { + break; + } + + setValue(result); + } + })(); + + return () => abortController.abort(); + }, [date]); + + return value; +} + +export default function TimeAgo({ date }: { date: Date }) { + return ( + + + + ); +} diff --git a/examples/pokemon/src/lib/pokemon.ts b/examples/pokemon/src/lib/pokemon.ts new file mode 100644 index 0000000..dcf9079 --- /dev/null +++ b/examples/pokemon/src/lib/pokemon.ts @@ -0,0 +1,153 @@ +declare const process: { + env: { + POKEMON_LIMIT?: string; + }; +}; + +export type Pokemon = { + id: number; + name: string; + is_default: boolean; + height: number; + weight: number; + base_experience: number; + sprites: { front_default: string }; + abilities: Ability[]; + types: Type[]; + species: Species; +}; + +export async function getAllPokemons(): Promise { + "use cache"; + let pokemons: Pokemon[] = []; + let next = `https://pokeapi.co/api/v2/pokemon?limit=${process.env.POKEMON_LIMIT || 1000}`; + while (next) { + const response = await fetch(next); + const data = await response.json(); + pokemons = pokemons.concat(data.results); + next = data.next; + if ( + process.env.POKEMON_LIMIT && + pokemons.length >= parseInt(process.env.POKEMON_LIMIT) + ) { + break; + } + } + return pokemons; +} + +export async function getPokemons( + search: string, + offset: number, + limit: number +): Promise<{ data: Pokemon[]; count: number }> { + "use cache"; + try { + const allPokemons = await getAllPokemons(); + const filteredPokemons = + search.trim().length > 0 + ? allPokemons.filter((pokemon) => + pokemon.name.toLowerCase().includes(search.trim().toLowerCase()) + ) + : allPokemons; + const fullPokemons = await Promise.all( + filteredPokemons.map((pokemon) => getPokemon(pokemon.name)) + ); + const defaultPokemons = fullPokemons.filter( + (pokemon) => pokemon?.is_default + ); + return { + data: defaultPokemons.slice(offset, offset + limit), + count: defaultPokemons.length, + }; + } catch { + return { data: [], count: 0 }; + } +} + +export async function getPokemon(name: string): Promise { + "use cache"; + const pokemonData = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`); + return pokemonData.json(); +} + +export type Ability = { + ability: { name: string }; +}; + +export type AbilityDetails = { + names: { name: string; language: { name: string } }[]; + effect_entries: { + effect: string; + short_effect: string; + language: { name: string }; + }[]; +}; + +export async function getAbility(name: string): Promise { + "use cache"; + const abilityData = await fetch(`https://pokeapi.co/api/v2/ability/${name}`); + return abilityData.json(); +} + +export type Type = { + type: { name: string }; +}; + +export type TypeDetails = { + names: { name: string; language: { name: string } }[]; +}; + +export async function getType(name: string): Promise { + "use cache"; + const typeData = await fetch(`https://pokeapi.co/api/v2/type/${name}`); + return typeData.json(); +} + +export type Species = { + name: string; +}; + +export type SpeciesDetails = { + names: { name: string; language: { name: string } }[]; + flavor_text_entries: { + flavor_text: string; + language: { name: string }; + }[]; + form_descriptions: { + description: string; + language: { name: string }; + }[]; +}; + +export async function getSpecies(name: string): Promise { + "use cache"; + const speciesData = await fetch( + `https://pokeapi.co/api/v2/pokemon-species/${name}` + ); + return speciesData.json(); +} + +export async function getPokemonDetails(name: string): Promise< + Omit & { + abilities: AbilityDetails[]; + types: TypeDetails[]; + species: SpeciesDetails; + } +> { + "use cache"; + const pokemon = await getPokemon(name); + + if (!pokemon) { + throw new Error(`Pokemon "${name}" not found`); + } + + const abilities = await Promise.all( + pokemon.abilities.map((ability) => getAbility(ability.ability.name)) + ); + const types = await Promise.all( + pokemon.types.map((type) => getType(type.type.name)) + ); + const species = await getSpecies(pokemon.species.name); + return { ...pokemon, abilities, types, species }; +} diff --git a/examples/pokemon/src/lib/utils.ts b/examples/pokemon/src/lib/utils.ts new file mode 100644 index 0000000..a3973d1 --- /dev/null +++ b/examples/pokemon/src/lib/utils.ts @@ -0,0 +1,14 @@ +import { useUrl } from "@lazarv/react-server"; + +export function applySearchParams(params: Record) { + const { searchParams } = useUrl(); + const newSearchParams = new URLSearchParams(searchParams); + for (const [key, value] of Object.entries(params)) { + if (Array.isArray(value)) { + value.forEach((v) => newSearchParams.append(key, v)); + } else { + newSearchParams.set(key, value as string); + } + } + return newSearchParams.toString(); +} diff --git a/examples/pokemon/tailwind.config.js b/examples/pokemon/tailwind.config.js new file mode 100644 index 0000000..e405cda --- /dev/null +++ b/examples/pokemon/tailwind.config.js @@ -0,0 +1,11 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/components/**/*.{js,ts,jsx,tsx}", + "./src/app/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/examples/pokemon/tsconfig.json b/examples/pokemon/tsconfig.json new file mode 100644 index 0000000..d817c54 --- /dev/null +++ b/examples/pokemon/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "jsx": "preserve", + "strict": true, + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "types": ["react/experimental", "react-dom/experimental"], + "module": "ESNext", + "moduleResolution": "Bundler", + "plugins": [{ "name": "typescript-plugin-css-modules" }], + "baseUrl": "./src", + "paths": { + "@/*": ["./*"] + } + }, + "include": ["**/*.ts", "**/*.tsx", ".react-server/**/*.ts"], + "exclude": ["**/*.js", "**/*.mjs"] +} diff --git a/examples/pokemon/vite.config.mjs b/examples/pokemon/vite.config.mjs new file mode 100644 index 0000000..be05a32 --- /dev/null +++ b/examples/pokemon/vite.config.mjs @@ -0,0 +1,9 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + resolve: { + alias: { + "@/": new URL("src/", import.meta.url).pathname, + }, + }, +}); diff --git a/examples/remote/react-server.production.config.mjs b/examples/remote/react-server.production.config.mjs index 60816e0..c1d4a77 100644 --- a/examples/remote/react-server.production.config.mjs +++ b/examples/remote/react-server.production.config.mjs @@ -10,8 +10,8 @@ export default { "https://esm.sh/react-dom@0.0.0-experimental-204a551e-20240926/client", "react-server-dom-webpack/client.browser": "https://esm.sh/react-server-dom-webpack@0.0.0-experimental-204a551e-20240926/client.browser", - "http://localhost:3003/client/node_modules/@lazarv/react-server/": - "/client/node_modules/@lazarv/react-server/", + "http://localhost:3003/client/__/__/packages/react-server/": + "/client/__/__/packages/react-server/", }, }, resolve: { diff --git a/examples/session-cookie/App.jsx b/examples/session-cookie/App.jsx new file mode 100644 index 0000000..50f4403 --- /dev/null +++ b/examples/session-cookie/App.jsx @@ -0,0 +1,24 @@ +import { getIronSession } from "iron-session"; + +import Login from "./components/login"; +import Logout from "./components/logout"; +import NewUser from "./components/newuser"; +import Cookies from "./misc/cookies"; +import { cookieName, password } from "./misc/session"; + +export default async function App() { + const session = await getIronSession(new Cookies(), { cookieName, password }); + + return ( +
+ {session.username ? ( + + ) : ( + <> + + + + )} +
+ ); +} diff --git a/examples/session-cookie/actions/user.mjs b/examples/session-cookie/actions/user.mjs new file mode 100644 index 0000000..bfd78ad --- /dev/null +++ b/examples/session-cookie/actions/user.mjs @@ -0,0 +1,9 @@ +"use server"; + +function actionNewUser(prevState) { + return { + userCode: prevState.userCode === null ? 100000 : prevState.userCode + 1, + }; +} + +export { actionNewUser }; diff --git a/examples/session-cookie/components/login.jsx b/examples/session-cookie/components/login.jsx new file mode 100644 index 0000000..99ff03d --- /dev/null +++ b/examples/session-cookie/components/login.jsx @@ -0,0 +1,23 @@ +import { redirect } from "@lazarv/react-server"; +import { getIronSession } from "iron-session"; +import { cookieName, password } from "../misc/session"; +import Cookies from "../misc/cookies"; + +export default function Login() { + return ( +
{ + "use server"; + const session = await getIronSession(new Cookies(), { + cookieName, + password, + }); + session.username = "test"; + await session.save(); + redirect("/"); + }} + > + +
+ ); +} diff --git a/examples/session-cookie/components/logout.jsx b/examples/session-cookie/components/logout.jsx new file mode 100644 index 0000000..4fad497 --- /dev/null +++ b/examples/session-cookie/components/logout.jsx @@ -0,0 +1,23 @@ +import { redirect } from "@lazarv/react-server"; +import { getIronSession } from "iron-session"; +import { cookieName, password } from "../misc/session"; +import Cookies from "../misc/cookies"; + +export default function Logout() { + return ( +
{ + "use server"; + const session = await getIronSession(new Cookies(), { + cookieName, + password, + }); + delete session.username; + session.destroy(); + redirect("/"); + }} + > + +
+ ); +} diff --git a/examples/session-cookie/components/newuser.jsx b/examples/session-cookie/components/newuser.jsx new file mode 100644 index 0000000..8b73df2 --- /dev/null +++ b/examples/session-cookie/components/newuser.jsx @@ -0,0 +1,19 @@ +"use client"; + +import { useActionState } from "react"; + +import { actionNewUser } from "../actions/user.mjs"; + +export default function NewUser() { + const [state, dispatch] = useActionState(actionNewUser, { + userCode: null, + }); + + return ( +
+ +
+ {state.userCode ? "User code: " + state.userCode : ""} +
+ ); +} diff --git a/examples/session-cookie/misc/cookies.mjs b/examples/session-cookie/misc/cookies.mjs new file mode 100644 index 0000000..1b27f3e --- /dev/null +++ b/examples/session-cookie/misc/cookies.mjs @@ -0,0 +1,20 @@ +import { cookie, setCookie } from "@lazarv/react-server"; + +export default class Cookies { + constructor() { + this.cookieObject = cookie(); + } + + get(name) { + return { value: this.cookieObject[name] }; + } + + set(name, value, options) { + this.cookieObject[name] = value; + setCookie(name, value, options); + } + + toString() { + return `Cookies object : ${JSON.stringify(this.cookieObject)}`; + } +} diff --git a/examples/session-cookie/misc/session.mjs b/examples/session-cookie/misc/session.mjs new file mode 100644 index 0000000..1507f5c --- /dev/null +++ b/examples/session-cookie/misc/session.mjs @@ -0,0 +1,4 @@ +import { randomBytes } from "node:crypto"; + +export const cookieName = "loginSession"; +export const password = randomBytes(32).toString("hex"); diff --git a/examples/session-cookie/package.json b/examples/session-cookie/package.json new file mode 100644 index 0000000..56d1261 --- /dev/null +++ b/examples/session-cookie/package.json @@ -0,0 +1,17 @@ +{ + "name": "@lazarv/react-server-example-session-cookie", + "private": true, + "description": "React Server Session Cookie example application", + "scripts": { + "dev": "react-server ./App.jsx", + "build": "react-server build ./App.jsx", + "start": "react-server start" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@lazarv/react-server": "workspace:^", + "iron-session": "^8.0.4" + } +} diff --git a/examples/session-cookie/react-server.config.json b/examples/session-cookie/react-server.config.json new file mode 100644 index 0000000..b8611ce --- /dev/null +++ b/examples/session-cookie/react-server.config.json @@ -0,0 +1,5 @@ +{ + "resolve": { + "external": ["iron-session"] + } +} diff --git a/package.json b/package.json index 1e41ab6..5627ccd 100644 --- a/package.json +++ b/package.json @@ -90,5 +90,5 @@ "supertest>superagent": "9.0.2" } }, - "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" + "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0" } diff --git a/packages/react-server/client/ClientProvider.jsx b/packages/react-server/client/ClientProvider.jsx index 19c0201..a7e0e18 100644 --- a/packages/react-server/client/ClientProvider.jsx +++ b/packages/react-server/client/ClientProvider.jsx @@ -1,23 +1,29 @@ import { - createFromFetch, createFromReadableStream, encodeReply, } from "react-server-dom-webpack/client.browser"; -import { ClientContext, PAGE_ROOT as _PAGE_ROOT_ } from "./context.mjs"; +import { + ClientContext as _ClientContext, + PAGE_ROOT as _PAGE_ROOT_, +} from "./context.mjs"; export const PAGE_ROOT = _PAGE_ROOT_; +export const ClientContext = _ClientContext; const activeChunk = new Map(); const cache = new Map(); const listeners = new Map(); const outlets = new Map(); +const outletAbortControllers = new Map(); const prefetching = new Map(); const flightCache = new Map(); + const registerOutlet = (outlet, url) => { outlets.set(outlet, url); return () => outlets.delete(outlet); }; + const subscribe = (url, listener) => { if (!listeners.has(url)) { listeners.set(url, new Set()); @@ -26,12 +32,33 @@ const subscribe = (url, listener) => { urlListeners.add(listener); return () => urlListeners.delete(listener); }; + const emit = (url, to = url, options = {}, callback = () => {}) => { if (!listeners.has(url)) return callback(); const urlListeners = listeners.get(url); for (const listener of urlListeners) listener(to, options, callback); }; -const prefetchOutlet = (to, { outlet = PAGE_ROOT, ttl = Infinity }) => { + +const isStale = (revalidate, context) => { + if ( + typeof revalidate !== "undefined" && + revalidate !== null && + revalidate !== true + ) { + if (typeof revalidate === "function") { + return revalidate(context); + } else if (typeof revalidate === "number" && context.timestamp) { + return Date.now() - context.timestamp > revalidate; + } + return revalidate; + } + return true; +}; + +const prefetchOutlet = ( + to, + { outlet = PAGE_ROOT, revalidate, ttl = Infinity } +) => { if (prefetching.get(outlet) !== to) { cache.delete(outlet); cache.delete(to); @@ -39,9 +66,24 @@ const prefetchOutlet = (to, { outlet = PAGE_ROOT, ttl = Infinity }) => { const key = `${outlet}:${to}`; if (flightCache.has(key)) { cache.set(outlet, flightCache.get(key)); - } else { - getFlightResponse(to, { outlet }); + } else if ( + !flightCache.has(key) || + (flightCache.has(key) && + isStale(revalidate, { + outlet, + url: to, + timestamp: flightCache.get(`${key}:timestamp`), + })) + ) { + getFlightResponse(to, { + revalidate, + outlet, + onError: () => flightCache.delete(key), + prefetch: true, + fromCache: true, + }); flightCache.set(key, cache.get(outlet)); + flightCache.set(`${key}:timestamp`, Date.now()); if (typeof ttl === "number" && ttl < Infinity) { setTimeout(() => { if (flightCache.has(key)) { @@ -52,6 +94,7 @@ const prefetchOutlet = (to, { outlet = PAGE_ROOT, ttl = Infinity }) => { } } }; + const prefetch = (to, options = {}) => { if (outlets.size > 1) { const activeOutlets = new Set(outlets.keys()); @@ -64,16 +107,18 @@ const prefetch = (to, options = {}) => { } return prefetchOutlet(to, options); }; -const refresh = async (outlet = PAGE_ROOT) => { + +const refresh = async (outlet = PAGE_ROOT, options = {}) => { return new Promise((resolve, reject) => { - const url = outlets.get(outlet) || PAGE_ROOT; + const url = + outlet === PAGE_ROOT ? PAGE_ROOT : outlets.get(outlet) || PAGE_ROOT; if (prefetching.get(outlet) === url) { prefetching.delete(outlet); } else { cache.delete(url); cache.delete(outlet); } - emit(outlet, url, {}, (err) => { + emit(outlet, url, options, (err) => { if (err) reject(err); else { activeChunk.set(outlet, cache.get(outlet)); @@ -82,8 +127,12 @@ const refresh = async (outlet = PAGE_ROOT) => { }); }); }; + let prevLocation = new URL(location); -const navigateOutlet = (to, { outlet = PAGE_ROOT, push, rollback = 0 }) => { +const navigateOutlet = ( + to, + { outlet = PAGE_ROOT, push, rollback = 0, revalidate, noCache, ...options } +) => { return new Promise((resolve, reject) => { if (typeof rollback === "number" && rollback > 0) { const key = `${outlet}:${outlets.get(outlet) || location.href}`; @@ -116,7 +165,15 @@ const navigateOutlet = (to, { outlet = PAGE_ROOT, push, rollback = 0 }) => { const key = `${outlet}:${to}`; if (flightCache.has(key)) { cache.set(outlet, flightCache.get(key)); - flightCache.delete(key); + if ( + isStale(revalidate, { + outlet, + url: to, + timestamp: flightCache.get(`${key}:timestamp`), + }) + ) { + flightCache.delete(key); + } const timeoutKey = `${key}:timeout`; if (flightCache.has(timeoutKey)) { clearTimeout(flightCache.get(timeoutKey)); @@ -126,21 +183,37 @@ const navigateOutlet = (to, { outlet = PAGE_ROOT, push, rollback = 0 }) => { cache.delete(to); cache.delete(outlet); } - emit(outlet, to, {}, (err) => { - if (err) reject(err); - else { - activeChunk.set(outlet, cache.get(outlet)); - resolve(); + emit( + outlet, + to, + { + ...options, + noCache, + fromCache: true, + }, + (err) => { + if (err) reject(err); + else { + activeChunk.set(outlet, cache.get(outlet)); + + if (!isStale(revalidate, { outlet, url: to })) { + flightCache.set(`${outlet}:${to}`, cache.get(outlet)); + flightCache.set(`${outlet}:${to}:timestamp`, Date.now()); + } + + resolve(); + } } - }); + ); }); }; + const navigate = (to, options = {}) => { const isRoot = options.outlet === PAGE_ROOT; if (!isRoot && outlets.size > 1) { const activeOutlets = new Set(outlets.keys()); activeOutlets.delete(PAGE_ROOT); - if (!options.external) { + if (options.push || options.replace) { if (options.push !== false) { history.pushState(Object.fromEntries(outlets.entries()), "", to); } else { @@ -148,6 +221,9 @@ const navigate = (to, options = {}) => { } prevLocation = new URL(location); } + if (options.outlet) { + return navigateOutlet(to, { ...options, outlet: options.outlet }); + } return Promise.all( Array.from(activeOutlets).map((outlet) => navigateOutlet(to, { ...options, outlet: options.outlet || outlet }) @@ -156,9 +232,29 @@ const navigate = (to, options = {}) => { } return navigateOutlet(to, options); }; + const replace = (to, options) => { return navigate(to, { ...options, push: false }); }; + +const invalidate = (outlet, options = {}) => { + return new Promise((resolve, reject) => { + const url = options.url ?? (outlets.get(outlet) || PAGE_ROOT); + cache.delete(url); + cache.delete(outlet); + if (options.noEmit) { + return resolve(); + } + emit(outlet, url, { ...options, outlet, noCache: true }, (err) => { + if (err) reject(err); + else { + activeChunk.set(outlet, cache.get(outlet)); + resolve(); + } + }); + }); +}; + window.addEventListener("popstate", () => { const newLocation = new URL(location); if ( @@ -181,7 +277,7 @@ window.addEventListener("popstate", () => { flightCache.delete(timeoutKey); } outlets.set(PAGE_ROOT, location.href); - emit(PAGE_ROOT, location.href, {}, (err) => { + emit(PAGE_ROOT, location.href, { fromCache: true }, (err) => { if (!err) { activeChunk.set(PAGE_ROOT, cache.get(PAGE_ROOT)); } @@ -206,7 +302,7 @@ window.addEventListener("popstate", () => { cache.delete(location.href); } outlets.set(outlet, location.href); - emit(outlet, location.href, {}, (err) => { + emit(outlet, location.href, { fromCache: true }, (err) => { if (!err) { activeChunk.set(outlet, cache.get(outlet)); } @@ -214,7 +310,8 @@ window.addEventListener("popstate", () => { } } }); -export const streamOptions = (outlet, remote) => ({ + +export const streamOptions = (outlet, remote, defer) => ({ async callServer(id, args) { return new Promise(async (resolve, reject) => { try { @@ -229,6 +326,7 @@ export const streamOptions = (outlet, remote) => ({ body: formData, outlet: target, remote, + defer, callServer: id || true, onFetch: (res) => { const callServer = @@ -239,6 +337,14 @@ export const streamOptions = (outlet, remote) => ({ if (err) reject(err); else { if (!callServer) { + const url = res.headers.get("React-Server-Render"); + const outlet = res.headers.get("React-Server-Outlet"); + + if (url && outlet) { + cache.set(outlet, await result); + emit(outlet, url, {}); + } + return resolve(); } const rsc = await result; @@ -262,13 +368,9 @@ export const streamOptions = (outlet, remote) => ({ onError: (err) => { reject(err); }, - headers: - formData instanceof FormData && - Array.from(formData.keys()).find((key) => key.includes("ACTION_ID")) - ? {} - : { - "React-Server-Action": encodeURIComponent(id), - }, + headers: { + "React-Server-Action": encodeURIComponent(id), + }, }); } catch (e) { reject(e); @@ -276,24 +378,69 @@ export const streamOptions = (outlet, remote) => ({ }); }, }); + +const abort = (outlet = PAGE_ROOT, reason, prefetch) => { + if ( + outletAbortControllers.has(outlet) || + (prefetch !== false && outletAbortControllers.has(`prefetch:${outlet}`)) + ) { + const abortControllers = outletAbortControllers.get(outlet); + const prefetchAbortControllers = outletAbortControllers.get( + `prefetch:${outlet}` + ); + for (const abortController of [ + ...(abortControllers || []), + ...(prefetch !== false ? prefetchAbortControllers || [] : []), + ]) { + if (!abortController?.signal.aborted) { + if (import.meta.env.DEV) { + if (abortControllers && abortControllers.has(abortController)) { + console.warn( + `Aborting: React Server Component request at outlet "${outlet}"` + ); + } + } + abortController.abort(reason); + } + } + outletAbortControllers.delete(outlet); + outletAbortControllers.delete(`prefetch:${outlet}`); + + if (prefetch !== false) { + prefetching.delete(outlet); + } + } +}; + function getFlightResponse(url, options = {}) { - if (!cache.has(options.outlet || url)) { + let abortController = options.signal; + if (!cache.has(options.outlet || url) || options.noCache) { if ( !options.defer && self[`__flightStream__${options.outlet || PAGE_ROOT}__`] && !self[`__flightHydration__${options.outlet || PAGE_ROOT}__`] ) { + const stream = + self[`__flightStream__${options.outlet || PAGE_ROOT}__`].readable; + const [from, backup] = stream.tee(); + self[`__flightStream__${options.outlet || PAGE_ROOT}__`] = { + readable: backup, + }; cache.set( options.outlet || url, createFromReadableStream( - self[`__flightStream__${options.outlet || PAGE_ROOT}__`].readable, + from, streamOptions(options.outlet || url, options.remote) ) ); + self[`__flightHydration__${options.outlet || PAGE_ROOT}__`] = true; activeChunk.set(options.outlet || url, cache.get(options.outlet || url)); } else if (!options.fromScript) { - const src = new URL(url === PAGE_ROOT ? location.href : url, location); + const src = new URL( + url === PAGE_ROOT ? location.href : options.url ?? url, + location + ); const outlet = options.outlet && options.outlet !== PAGE_ROOT ? `@${options.outlet}.` @@ -302,37 +449,140 @@ function getFlightResponse(url, options = {}) { /\/+/g, "/" ); - cache.set( - options.outlet || url, - createFromFetch( - fetch(src.toString(), { - ...options.request, - method: options.method, - body: options.body, - headers: { - ...options.request?.headers, - accept: "text/x-component", - "React-Server-Outlet": encodeURIComponent( - options.outlet || PAGE_ROOT - ), - ...options.headers, - }, - }).then( - (res) => { - options.onFetch?.(res); - return res; - }, - (err) => { - options.onError?.(err); - throw err; + const srcString = src.toString(); + + if (!options.callServer) { + abort( + options.outlet || url, + new DOMException("navigation", "AbortError"), + !options.prefetch + ); + + if (!abortController) { + abortController = new AbortController(); + } + + if (options.onAbort) { + abortController.signal.addEventListener("abort", options.onAbort); + } + + if ( + options.prefetch && + isStale(options.revalidate, { + outlet: options.outlet || PAGE_ROOT, + url, + timestamp: flightCache.get( + `${options.outlet || PAGE_ROOT}:${url}:timestamp` + ), + }) + ) { + abortController.signal.addEventListener("abort", () => { + flightCache.delete(`${options.outlet || PAGE_ROOT}:${url}`); + }); + } + + const key = `${options.prefetch ? "prefetch:" : ""}${options.outlet || url}`; + if (!outletAbortControllers.has(key)) { + outletAbortControllers.set(key, new Set()); + } + + outletAbortControllers.get(key).add(abortController); + } + + const component = createFromReadableStream( + new ReadableStream({ + type: "bytes", + async start(controller) { + let response; + try { + response = await fetch(srcString, { + ...options.request, + method: options.method, + body: options.body, + headers: { + ...options.request?.headers, + accept: "text/x-component", + ...(options.noCache && { "Cache-Control": "no-cache" }), + ...(options.prefetch && { "React-Server-Prefetch": "true" }), + ...options.headers, + }, + credentials: "include", + signal: abortController?.signal, + }); + const { body } = response; + + window.dispatchEvent( + new CustomEvent( + `__react_server_flight_error_${options.outlet}__`, + { + detail: { error: null, options, url }, + } + ) + ); + + options.onFetch?.(response); + + if (abortController?.signal.aborted) { + controller.error(abortController.signal.reason); + return; + } + + for await (const chunk of body) { + controller.enqueue(chunk); + } + controller.close(); + + if (outletAbortControllers.has(options.outlet || url)) { + const abortControllers = outletAbortControllers.get( + options.outlet || url + ); + if (abortControllers.has(abortController)) { + abortControllers.delete(abortController); + } + } + } catch (e) { + if (e instanceof DOMException && e.name === "AbortError") { + cache.delete(options.outlet || url); + flightCache.delete(`${options.outlet || PAGE_ROOT}:${url}`); + return; + } + + options.onError?.(e); + return new Promise(async (resolve) => { + e.digest = e.message; + e.environmentName = "react-server"; + window.dispatchEvent( + new CustomEvent( + `__react_server_flight_error_${options.outlet}__`, + { + detail: { error: e, options, url }, + } + ) + ); + + const encoder = new TextEncoder(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + controller.enqueue(encoder.encode(`0:["$L1"]\n1:null\n`)); + controller.close(); + resolve(); + }); } - ), - streamOptions(options.outlet || url, options.remote) - ) + }, + }), + streamOptions(options.outlet || url, options.remote, options.defer) ); + cache.set(options.outlet || url, component); } } + if ( + typeof options.onReady === "function" && + !abortController?.signal.aborted + ) { + return options.onReady(cache.get(options.outlet || url)); + } + return cache.get(options.outlet || url); } @@ -346,7 +596,18 @@ export default function ClientProvider({ children }) { navigate, replace, subscribe, + invalidate, + abort, getFlightResponse, + state: { + activeChunk, + cache, + flightCache, + listeners, + outlets, + outletAbortControllers, + prefetching, + }, }} > {children} diff --git a/packages/react-server/client/ErrorBoundary.jsx b/packages/react-server/client/ErrorBoundary.jsx index b1d4802..5aee422 100644 --- a/packages/react-server/client/ErrorBoundary.jsx +++ b/packages/react-server/client/ErrorBoundary.jsx @@ -11,7 +11,12 @@ import { useState, } from "react"; -import { FlightContext, useClient } from "./context.mjs"; +import { + FlightContext, + FlightComponentContext, + useClient, + PAGE_ROOT, +} from "./context.mjs"; const ErrorBoundaryContext = createContext(null); @@ -62,16 +67,20 @@ export class ErrorBoundary extends Component { return { didCatch: true, error }; } - resetErrorBoundary(...args) { + async resetErrorBoundary(...args) { const { error } = this.state; if (error !== null) { - this.props.onReset?.({ + await this.props.onReset?.({ args, reason: "imperative-api", + error, + resetErrorBoundary: this.resetErrorBoundary, }); - this.setState(initialState); + if (typeof error?.digest !== "string") { + this.setState(initialState); + } } } @@ -93,13 +102,23 @@ export class ErrorBoundary extends Component { prevState.error !== null && hasArrayChanged(prevProps.resetKeys, resetKeys) ) { - this.props.onReset?.({ - next: resetKeys, - prev: prevProps.resetKeys, - reason: "keys", - }); + if (typeof this.props.onReset === "function") { + const resetPromise = this.props.onReset({ + next: resetKeys, + prev: prevProps.resetKeys, + reason: "keys", + }); - this.setState(initialState); + if (typeof resetPromise?.then === "function") { + resetPromise.then(() => { + this.setState(initialState); + }); + } else { + this.setState(initialState); + } + } else { + this.setState(initialState); + } } } @@ -108,6 +127,13 @@ export class ErrorBoundary extends Component { this.props; const { didCatch, error } = this.state; + if ( + error?.message === "Redirect" && + error?.digest.startsWith("Location=") + ) { + error.redirectTo = error.digest.slice(9); + } + let childToRender = children; if (didCatch) { @@ -116,6 +142,10 @@ export class ErrorBoundary extends Component { resetErrorBoundary: this.resetErrorBoundary, }; + if (!import.meta.env.DEV) { + delete error.stack; + } + if (typeof fallbackRender === "function") { childToRender = fallbackRender(props); } else if (FallbackComponent) { @@ -153,39 +183,77 @@ function hasArrayChanged(a = [], b = []) { ); } -function ResetErrorBoundary() { - const { url, outlet } = useContext(FlightContext); - const { resetBoundary } = useErrorBoundary(); - const { subscribe } = useClient(); +function FallbackRenderComponent({ + FallbackComponent, + fallbackRender, + ...props +}) { + const { outlet } = useContext(FlightContext); + const client = useClient(); + const { navigate } = client; + const { error } = props; + const { redirectTo } = error; useEffect(() => { - return subscribe(outlet || url, () => resetBoundary()); - }, []); + if (redirectTo) { + navigate(redirectTo, { outlet, external: outlet !== PAGE_ROOT }); + } + }, [redirectTo, navigate, outlet]); + if (redirectTo) { + return null; + } + + return ( + <> + {FallbackComponent && typeof FallbackComponent === "function" ? ( + + ) : ( + FallbackComponent + )} + {fallbackRender?.(props)} + + ); +} + +function ThrowError({ error }) { + if (error) { + throw error; + } return null; } -export default function ReactServerErrorBoundary({ +export default function ReactServerOutletErrorBoundary({ component: FallbackComponent, render: fallbackRender, + onReset, + global, children, ...props }) { + const { outlet } = useContext(FlightContext); + const { resourceKey, error } = useContext(FlightComponentContext); + const { invalidate } = useClient(); + return ( { + if (typeof details.error?.digest === "string") { + await invalidate(outlet); + } + onReset?.(details); + }} fallbackRender={(props) => ( - <> - - {FallbackComponent && typeof FallbackComponent === "function" ? ( - - ) : ( - FallbackComponent - )} - {fallbackRender?.(props)} - + )} > + {children} ); diff --git a/packages/react-server/client/Form.jsx b/packages/react-server/client/Form.jsx new file mode 100644 index 0000000..92bce4b --- /dev/null +++ b/packages/react-server/client/Form.jsx @@ -0,0 +1,78 @@ +"use client"; + +import { startTransition, useCallback, useContext, useRef } from "react"; + +import { FlightContext, useClient } from "./context.mjs"; + +export default function Form({ + target, + root, + local, + transition, + push, + replace, + rollback = false, + noCache, + revalidate, + onNavigate, + onError, + onSubmit, + children, + ...props +}) { + const { navigate } = useClient(); + const { outlet } = useContext(FlightContext); + const ref = useRef(null); + + const tryNavigate = useCallback(async () => { + try { + const url = new URL(ref.current.action, window.location.origin); + const formData = new FormData(ref.current); + for (const [key, value] of formData.entries()) { + url.searchParams.set(key, value); + } + const to = url.toString(); + await navigate(to, { + outlet: target || (local ? outlet : root ? "PAGE_ROOT" : undefined), + push: (replace ? false : push) ?? (target && target === outlet), + replace, + rollback, + noCache, + revalidate, + }); + onNavigate?.(); + } catch (e) { + onError?.(e); + } + }, [ + ref, + target, + outlet, + root, + local, + push, + replace, + rollback, + noCache, + revalidate, + ]); + + const handleNavigate = useCallback( + async (e) => { + e.preventDefault(); + onSubmit?.(e); + if (transition !== false) { + startTransition(tryNavigate); + } else { + tryNavigate(); + } + }, + [transition, onSubmit, tryNavigate] + ); + + return ( +
+ {children} +
+ ); +} diff --git a/packages/react-server/client/Link.jsx b/packages/react-server/client/Link.jsx index 43b3805..a86e9b5 100644 --- a/packages/react-server/client/Link.jsx +++ b/packages/react-server/client/Link.jsx @@ -14,9 +14,17 @@ export default function Link({ replace, prefetch: prefetchEnabled, ttl = Infinity, + revalidate, rollback = false, + noCache, + fallback, + Component, onNavigate, onError, + onClick, + onFocus, + onMouseOver, + onTouchStart, children, ...props }) { @@ -27,9 +35,16 @@ export default function Link({ try { await navigate(to, { outlet: target || (local ? outlet : root ? "PAGE_ROOT" : undefined), - external: target && target !== outlet, - push: replace ? false : push, + push: + (replace ? false : push) ?? + ((target && target === outlet) || + (!target && outlet === "PAGE_ROOT")), + replace, rollback, + revalidate, + noCache, + fallback, + Component, }); onNavigate?.(); } catch (e) { @@ -41,37 +56,49 @@ export default function Link({ local, outlet, root, - replace, push, + replace, rollback, + noCache, + revalidate, + fallback, + Component, onNavigate, onError, ]); - const handleNavigate = async (e) => { - e.preventDefault(); - if (transition !== false) { - startTransition(tryNavigate); - } else { - tryNavigate(); - } - }; + const handleNavigate = useCallback( + async (e) => { + e.preventDefault(); + onClick?.(e); + if (transition !== false && !fallback) { + startTransition(tryNavigate); + } else { + tryNavigate(); + } + }, + [transition, fallback, onClick, tryNavigate] + ); - const handlePrefetch = () => + const handlePrefetch = (handler) => () => { + handler?.(); prefetchEnabled === true && - prefetch(to, { - outlet: target || (local ? outlet : root ? "PAGE_ROOT" : undefined), - ttl, - }); + prefetch(to, { + outlet: target || (local ? outlet : root ? "PAGE_ROOT" : undefined), + ttl, + noCache, + revalidate, + }); + }; return ( {children} diff --git a/packages/react-server/client/ReactServerComponent.jsx b/packages/react-server/client/ReactServerComponent.jsx index 1bb1297..8411db0 100644 --- a/packages/react-server/client/ReactServerComponent.jsx +++ b/packages/react-server/client/ReactServerComponent.jsx @@ -1,10 +1,16 @@ "use client"; -import { startTransition, useContext, useEffect, useState } from "react"; +import { + startTransition, + useContext, + useEffect, + useRef, + useState, +} from "react"; import { - ClientContext, FlightContext, + FlightComponentContext, PAGE_ROOT, useClient, } from "./context.mjs"; @@ -12,9 +18,12 @@ import { function FlightComponent({ remote = false, defer = false, request, children }) { const { url, outlet } = useContext(FlightContext); const client = useClient(); - const { registerOutlet, subscribe, getFlightResponse } = client; - const [Component, setComponent] = useState( - children || + const { registerOutlet, subscribe, getFlightResponse, abort } = client; + const [{ resourceKey, error, Component }, setComponent] = useState({ + resourceKey: 0, + error: null, + Component: + children || (outlet === PAGE_ROOT || remote ? getFlightResponse?.(url, { outlet, @@ -22,30 +31,80 @@ function FlightComponent({ remote = false, defer = false, request, children }) { defer, request, }) - : null) - ); - const [error, setError] = useState(null); + : null), + }); + const errorRef = useRef(null); + const componentPromiseRef = useRef(null); + const prevComponent = useRef(Component); useEffect(() => { let mounted = true; const unregisterOutlet = registerOutlet(outlet, url); - const unsubscribe = subscribe(outlet || url, (to, options, callback) => { - const nextComponent = getFlightResponse(to, { - outlet, - remote, - request, - }); - if (!mounted) return; - if (options.callServer) { - callback(null, nextComponent); - } else { - startTransition(() => { - setError(null); - setComponent(nextComponent); - callback(null, nextComponent); + const unsubscribe = subscribe( + outlet || url, + async (to, options, callback) => { + if (typeof options.Component !== "undefined") { + const exception = new DOMException("render", "AbortError"); + + abort(outlet, exception); + componentPromiseRef.current?.reject(exception); + + setComponent((prev) => ({ + ...prev, + resourceKey: prev.resourceKey + 1, + error: errorRef.current, + Component: options.Component, + })); + + callback(null, options.Component); + return; + } + + let componentResolve, componentReject; + const componentPromise = new Promise((resolve, reject) => { + componentResolve = resolve; + componentReject = reject; + componentPromiseRef.current = { resolve, reject }; + }); + const nextComponent = getFlightResponse(to, { + ...options, + outlet, + remote, + request, + onReady: options.callServer ? undefined : componentResolve, + onAbort: options.callServer ? undefined : componentReject, }); + if (options.callServer) { + callback(null, nextComponent); + } else if (mounted) { + if (options.fallback) { + startTransition(() => { + setComponent((prev) => ({ + ...prev, + resourceKey: prev.resourceKey + 1, + error: errorRef.current, + Component: options.fallback, + })); + }); + } + try { + const nextComponent = await componentPromise; + componentPromiseRef.current = null; + startTransition(() => { + setComponent((prev) => ({ + ...prev, + resourceKey: prev.resourceKey + 1, + error: errorRef.current, + Component: nextComponent, + })); + callback(null, nextComponent); + }); + } catch { + componentPromiseRef.current = null; + } + } } - }); + ); return () => { mounted = false; unregisterOutlet(); @@ -55,29 +114,70 @@ function FlightComponent({ remote = false, defer = false, request, children }) { useEffect(() => { if (children || (outlet !== PAGE_ROOT && Component)) { - setComponent(children); + setComponent((prev) => ({ + ...prev, + resourceKey: prev.resourceKey + 1, + error: errorRef.current, + Component: children, + })); } }, [children]); useEffect(() => { if (remote || defer) { - const nextComponent = getFlightResponse(url, { + getFlightResponse(url, { outlet, remote, defer, request, fromScript: defer ? false : true, + onReady: (nextComponent) => { + if (nextComponent) { + startTransition(() => + setComponent((prev) => ({ + ...prev, + resourceKey: prev.resourceKey + 1, + error: errorRef.current, + Component: nextComponent, + })) + ); + } + }, }); - if (nextComponent) { - startTransition(() => setComponent(nextComponent)); - } } }, [url, outlet, remote, defer, request, getFlightResponse]); + useEffect(() => { + const abortController = new AbortController(); + + window.addEventListener( + `__react_server_flight_error_${outlet}__`, + (event) => { + errorRef.current = event.detail.error; + }, + { signal: abortController.signal } + ); + + return () => abortController.abort(); + }, [outlet]); + + if (error) { + if (outlet === PAGE_ROOT) { + return ( + + {prevComponent.current} + + ); + } + throw error; + } + + prevComponent.current = Component; + return ( - + {Component} - + ); } @@ -89,8 +189,30 @@ export default function ReactServerComponent({ request, children, }) { + const { navigate, abort } = useClient(); + return ( - + {children} diff --git a/packages/react-server/client/Refresh.jsx b/packages/react-server/client/Refresh.jsx index e71eddb..6f93d84 100644 --- a/packages/react-server/client/Refresh.jsx +++ b/packages/react-server/client/Refresh.jsx @@ -12,8 +12,16 @@ export default function Refresh({ transition, prefetch: prefetchEnabled, ttl = Infinity, + revalidate, + noCache, + fallback, + Component, onRefresh, onError, + onClick, + onFocus, + onMouseOver, + onTouchStart, children, ...props }) { @@ -25,38 +33,61 @@ export default function Refresh({ await refresh( target || url || - (local ? _outlet || _url : root ? "PAGE_ROOT" : undefined) + (local ? _outlet || _url : root ? "PAGE_ROOT" : undefined), + { noCache, fallback, Component, revalidate } ); onRefresh?.(); } catch (e) { onError?.(e); } - }, [refresh, target, local, root, url, _outlet, _url, onRefresh, onError]); + }, [ + refresh, + target, + local, + root, + url, + _outlet, + _url, + revalidate, + noCache, + fallback, + Component, + onRefresh, + onError, + ]); - const handleRefresh = async (e) => { - e.preventDefault(); - if (transition !== false) { - startTransition(tryRefresh); - } else { - tryRefresh(); - } - }; + const handleRefresh = useCallback( + async (e) => { + e.preventDefault(); + onClick?.(e); + if (transition !== false && !fallback) { + startTransition(tryRefresh); + } else { + tryRefresh(); + } + }, + [transition, fallback, onClick, tryRefresh] + ); - const handlePrefetch = () => + const handlePrefetch = (handler) => () => { + handler?.(); prefetchEnabled === true && - prefetch(url || _url, { - outlet: target || (local ? _outlet : root ? "PAGE_ROOT" : undefined), - ttl, - }); + prefetch(url || _url, { + outlet: target || (local ? _outlet : root ? "PAGE_ROOT" : undefined), + ttl, + noCache, + revalidate, + }); + }; return ( {children} diff --git a/packages/react-server/client/context.mjs b/packages/react-server/client/context.mjs index 38d13d7..7778586 100644 --- a/packages/react-server/client/context.mjs +++ b/packages/react-server/client/context.mjs @@ -4,8 +4,24 @@ import { createContext, useContext } from "react"; export const PAGE_ROOT = "PAGE_ROOT"; export const ClientContext = createContext({}); -export const FlightContext = createContext({ url: "/", outlet: null }); +export const FlightContext = createContext({ + url: "/", + outlet: null, + refresh: () => {}, + prefetch: () => {}, + navigate: () => {}, + replace: () => {}, + abort: () => {}, +}); +export const FlightComponentContext = createContext({ + resourceKey: 0, + error: null, +}); export function useClient() { return useContext(ClientContext); } + +export function useOutlet() { + return useContext(FlightContext); +} diff --git a/packages/react-server/client/entry.client.jsx b/packages/react-server/client/entry.client.jsx index 0b5d413..0859e8f 100644 --- a/packages/react-server/client/entry.client.jsx +++ b/packages/react-server/client/entry.client.jsx @@ -1,21 +1,175 @@ -import { startTransition, StrictMode } from "react"; +import { startTransition, StrictMode, Component } from "react"; import { hydrateRoot } from "react-dom/client"; -import ClientProvider, { PAGE_ROOT, streamOptions } from "./ClientProvider.jsx"; +import ClientProvider, { + PAGE_ROOT, + ClientContext, + streamOptions, +} from "./ClientProvider.jsx"; import ReactServerComponent from "./ReactServerComponent.jsx"; self.__react_server_callServer__ = streamOptions(PAGE_ROOT).callServer; +const initialState = { didCatch: false, error: null }; + +function findRef(ref, value, visited = new Set()) { + if (ref === value) { + return true; + } + if (visited.has(value)) { + return false; + } + visited.add(value); + if (Array.isArray(value)) { + return value.some((v) => findRef(ref, v, visited)); + } + if (typeof value === "object" && value !== null) { + return Object.values(value).some((v) => findRef(ref, v, visited)); + } + return false; +} + +class ErrorBoundary extends Component { + static contextType = ClientContext; + + constructor(props) { + super(props); + this.state = { ...initialState }; + } + + static getDerivedStateFromError(error) { + return { didCatch: true, error, info: null }; + } + + componentDidCatch(error, info) { + for (const [key, value] of this.context.state.cache.entries()) { + if (findRef(error, value)) { + this.setState({ + didCatch: true, + error, + info, + outlet: key, + url: this.context.state.outlets.get(key) || PAGE_ROOT, + }); + break; + } + } + } + + resetErrorBoundary = async () => { + const { error, outlet, url } = this.state; + if (typeof error?.digest === "string") { + if (outlet !== PAGE_ROOT) { + self[`__flightHydration__${PAGE_ROOT}__`] = false; + } + this.context.invalidate(outlet, { noEmit: true }); + this.context.getFlightResponse(outlet, { + outlet, + remote: outlet !== PAGE_ROOT && self[`__flightStream__${outlet}__`], + url, + onFetch: () => { + this.setState(initialState); + }, + }); + } else { + this.setState(initialState); + } + }; + + render() { + const { didCatch, error } = this.state; + + if (didCatch) { + return ( + + + {document.title} + + + + + +

${e?.digest || e?.message}

+
${(e?.digest ? e?.message : e?.stack) || "An unexpected error occurred while rendering the page. The specific message is omitted in production builds to avoid leaking sensitive details."}
+ + + + +`; + + headers.set("Content-Type", "text/html; charset=utf-8"); + return new Response(html, { + status: httpStatus.status, + headers, + }); + } + headers.set("Content-Type", "text/plain; charset=utf-8"); - return new Response(e?.stack ?? null, { + return new Response(e?.digest || e?.message, { ...httpStatus, headers, }); @@ -159,6 +208,7 @@ export default async function ssrHandler(root, options = {}) { [RENDER_STREAM]: renderStream, [PRELUDE_HTML]: getPrerender(PRELUDE_HTML), [POSTPONE_STATE]: getPrerender(POSTPONE_STATE), + [ERROR_BOUNDARY]: ErrorBoundary, }, async () => { const cacheModule = forChild(httpContext.url)?.cache?.module; @@ -180,12 +230,20 @@ export default async function ssrHandler(root, options = {}) { context$(RENDER_CONTEXT, renderContext); context$(RENDER, render); + if (GlobalErrorComponent) { + useErrorComponent(GlobalErrorComponent); + } + try { const middlewares = await root_init$?.(); if (middlewares) { const response = await middlewares(httpContext); if (response) { - return resolve(response); + return resolve( + typeof response === "function" + ? await response(httpContext) + : response + ); } } } catch { diff --git a/packages/react-server/memory-cache/index.mjs b/packages/react-server/memory-cache/index.mjs index 8df288c..1f195c2 100644 --- a/packages/react-server/memory-cache/index.mjs +++ b/packages/react-server/memory-cache/index.mjs @@ -8,6 +8,12 @@ import { MEMORY_CACHE_CONTEXT, } from "../server/symbols.mjs"; +function matchKeys(keys, entryKeys) { + return keys.every((key) => + Boolean(entryKeys.find((entryKey) => equals(entryKey, key))) + ); +} + export class MemoryCache { constructor() { this.cache = new Map(); @@ -29,7 +35,7 @@ export class MemoryCache { const cacheKeys = this.cache.keys(); for (const entryKeys of cacheKeys) { - if (keys.every((key, keyIndex) => equals(entryKeys[keyIndex], key))) { + if (matchKeys(keys, entryKeys)) { return this.cache.get(entryKeys); } } @@ -41,7 +47,7 @@ export class MemoryCache { if (await this.hasExpiry(keys)) { const cacheKeys = this.cache.keys(); for (const entryKeys of cacheKeys) { - if (keys.every((key, keyIndex) => equals(entryKeys[keyIndex], key))) { + if (matchKeys(keys, entryKeys)) { this.cache.set(entryKeys, value); return; } @@ -53,7 +59,7 @@ export class MemoryCache { async has(keys) { const cacheKeys = this.cache.keys(); for (const entryKeys of cacheKeys) { - if (keys.every((key, keyIndex) => equals(entryKeys[keyIndex], key))) { + if (matchKeys(keys, entryKeys)) { return true; } } @@ -61,10 +67,21 @@ export class MemoryCache { return false; } + async getExpiry(keys) { + const expiryKeys = this.expiry.keys(); + for (const entryKeys of expiryKeys) { + if (matchKeys(keys, entryKeys)) { + return this.expiry.get(entryKeys); + } + } + + return null; + } + async setExpiry(keys, expiry) { const expiryKeys = this.expiry.keys(); for (const entryKeys of expiryKeys) { - if (keys.every((key, keyIndex) => equals(entryKeys[keyIndex], key))) { + if (matchKeys(keys, entryKeys)) { this.expiry.set(entryKeys, expiry); return; } @@ -92,7 +109,7 @@ export class MemoryCache { async delete(keys) { const cacheKeys = this.cache.keys(); for (const entryKeys of cacheKeys) { - if (keys.every((key, keyIndex) => equals(entryKeys[keyIndex], key))) { + if (matchKeys(keys, entryKeys)) { this.cache.delete(entryKeys); } } diff --git a/packages/react-server/server/ErrorBoundary.jsx b/packages/react-server/server/ErrorBoundary.jsx index a9ccb4e..46df6cb 100644 --- a/packages/react-server/server/ErrorBoundary.jsx +++ b/packages/react-server/server/ErrorBoundary.jsx @@ -8,8 +8,12 @@ export default async function ReactServerErrorBoundary({ ...props }) { return ( - - {children} - + + {fallback ? ( + {children} + ) : ( + children + )} + ); } diff --git a/packages/react-server/server/GlobalError.jsx b/packages/react-server/server/GlobalError.jsx new file mode 100644 index 0000000..929f99e --- /dev/null +++ b/packages/react-server/server/GlobalError.jsx @@ -0,0 +1,77 @@ +import { useRender, useUrl } from "@lazarv/react-server"; +import { style, remoteStyle } from "./error-styles.mjs"; + +export default async function GlobalError({ error }) { + const url = useUrl(); + const { isRemote } = useRender(); + + if (import.meta.env.DEV) { + const [{ getContext }, { SERVER_CONTEXT }] = await Promise.all([ + import("@lazarv/react-server/server/context.mjs"), + import("@lazarv/react-server/server/symbols.mjs"), + ]); + const viteDevServer = getContext(SERVER_CONTEXT); + if (viteDevServer) { + try { + viteDevServer.environments.client.moduleGraph.invalidateAll(); + viteDevServer.environments.ssr.moduleGraph.invalidateAll(); + viteDevServer.environments.rsc.moduleGraph.invalidateAll(); + } catch { + // ignore + } + } + } + + if (isRemote) { + return ( +
+ +

+ {error.digest && error.digest !== error.message + ? error.digest + : error.message || "Global Error"} +

+
+          {import.meta.env.DEV
+            ? error.stack
+            : "An error occurred. Please try again later."}
+        
+
+ ); + } + + return ( + + + Global Error + + + + + +

+ {error.digest && error.digest !== error.message + ? error.digest + : error.message || "Global Error"} +

+
+          {import.meta.env.DEV
+            ? error.stack
+            : "An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error."}
+        
+ + + + {import.meta.env.DEV && ( + <> + + + + + )} + + + ); +} diff --git a/packages/react-server/server/RemoteComponent.jsx b/packages/react-server/server/RemoteComponent.jsx index f05ce79..6786ab6 100644 --- a/packages/react-server/server/RemoteComponent.jsx +++ b/packages/react-server/server/RemoteComponent.jsx @@ -7,7 +7,13 @@ import { getContext } from "./context.mjs"; import { useUrl } from "./request.mjs"; import { LOGGER_CONTEXT } from "./symbols.mjs"; -async function RemoteComponentLoader({ url, ttl, request = {}, onError }) { +async function RemoteComponentLoader({ + url, + ttl, + request = {}, + defer, + onError, +}) { const Component = await useCache( [url], async () => { @@ -23,7 +29,11 @@ async function RemoteComponentLoader({ url, ttl, request = {}, onError }) { headers: { Origin: url.origin, ...request.headers, - Accept: "text/html", + ...(defer + ? { + "React-Server-Defer": "true", + } + : {}), }, }).catch((e) => { (onError ?? getContext(LOGGER_CONTEXT)?.error)?.(e); @@ -90,6 +100,7 @@ export default async function RemoteComponent({ url={remoteUrl} ttl={ttl} request={request} + defer={defer} onError={onError} /> diff --git a/packages/react-server/server/client-reference-map.mjs b/packages/react-server/server/client-reference-map.mjs index a874bb2..66094ee 100644 --- a/packages/react-server/server/client-reference-map.mjs +++ b/packages/react-server/server/client-reference-map.mjs @@ -15,7 +15,7 @@ export const clientReferenceMap = ({ remote, origin }) => const manifest = getContext(MANIFEST); if (!manifest) { def = { - id: remote ? `${origin}/${id}` : id, + id, chunks: [], name, async: true, diff --git a/packages/react-server/server/dom-flight.mjs b/packages/react-server/server/dom-flight.mjs index 3b80483..ca6d03a 100644 --- a/packages/react-server/server/dom-flight.mjs +++ b/packages/react-server/server/dom-flight.mjs @@ -11,6 +11,9 @@ export default function visit(node, context) { case "#comment": return null; default: { + if (node.nodeName === "template" && context.defer) { + return null; + } const childNodes = node.childNodes?.map((node) => visit(node, context)) ?? []; const children = childNodes.length > 1 ? childNodes : childNodes[0]; @@ -52,7 +55,10 @@ export default function visit(node, context) { return props; }, {}) ?? {}; if (typeof children !== "undefined") { - props.children = children; + props.children = + node.nodeName === "script" && children.startsWith("$") + ? `$${children}` + : children; } return ["$", node.nodeName, null, props, "", "", 1]; } diff --git a/packages/react-server/server/error-boundary.d.ts b/packages/react-server/server/error-boundary.d.ts index be48501..ff9da3a 100644 --- a/packages/react-server/server/error-boundary.d.ts +++ b/packages/react-server/server/error-boundary.d.ts @@ -51,10 +51,17 @@ export type ErrorBoundaryProps = | ErrorBoundaryPropsWithComponent | ErrorBoundaryPropsWithRender; +export type ErrorBoundaryComponentProps = React.PropsWithChildren<{ + error: Error & { digest?: string }; + resetErrorBoundary: () => void; +}>; + export type ReactServerErrorBoundaryProps = React.PropsWithChildren< Omit & { fallback?: React.ReactNode; - component?: React.ComponentType<{ error?: Error }> | React.ReactNode; + component?: + | React.ComponentType + | React.ReactNode; } >; diff --git a/packages/react-server/server/error-handler.mjs b/packages/react-server/server/error-handler.mjs new file mode 100644 index 0000000..e50d17a --- /dev/null +++ b/packages/react-server/server/error-handler.mjs @@ -0,0 +1,31 @@ +import { getEnv } from "../lib/sys.mjs"; +import { context$, getContext } from "./context.mjs"; +import { useRender } from "./render.mjs"; +import { ERROR_COMPONENT, ERROR_CONTEXT } from "./symbols.mjs"; + +export function useErrorComponent(Component) { + const { render } = useRender(); + const errorHandler = getContext(ERROR_CONTEXT); + + context$(ERROR_CONTEXT, async (error) => { + context$(ERROR_CONTEXT, errorHandler); + return render( + Component, + { + error: { + ...Reflect.ownKeys(error).reduce((acc, key) => { + acc[key] = error[key]; + return acc; + }, {}), + environmentName: "Server", + digest: error.digest || error.message, + stack: getEnv("NODE_ENV") !== "production" ? error.stack : undefined, + }, + }, + { + skipFunction: true, + } + ); + }); + context$(ERROR_COMPONENT, Component); +} diff --git a/packages/react-server/server/error-styles.mjs b/packages/react-server/server/error-styles.mjs new file mode 100644 index 0000000..f752ec3 --- /dev/null +++ b/packages/react-server/server/error-styles.mjs @@ -0,0 +1,47 @@ +export const remoteStyle = `.react-server-global-error * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + .react-server-global-error { + font-family: system-ui, -apple-system, sans-serif; + line-height: 1.5; + padding: 1rem; + background: #fff; + } + + .react-server-global-error h1 { + font-size: 2rem; + font-weight: 600; + margin-bottom: 1rem; + color: #e11d48; + } + + .react-server-global-error pre { + margin: 1rem 0; + padding: 1rem; + background: #f1f5f9; + color: #374151; + border-radius: 0.5rem; + font-size: 0.875rem; + width: 100%; + overflow: auto; + white-space: pre-wrap; + word-wrap: break-word; + }`; + +export const style = `${remoteStyle} + + .react-server-global-error button { + padding: 0.5rem 1rem; + background: #0ea5e9; + color: white; + border: none; + border-radius: 0.25rem; + cursor: pointer; + } + + .react-server-global-error button:hover { + background: #0284c7; + }`; diff --git a/packages/react-server/server/redirects.mjs b/packages/react-server/server/redirects.mjs index 6003444..abc333f 100644 --- a/packages/react-server/server/redirects.mjs +++ b/packages/react-server/server/redirects.mjs @@ -9,6 +9,7 @@ export class RedirectError extends Error { super("Redirect"); this.url = url; this.status = status; + this.digest = `${status} ${url}`; } } @@ -16,6 +17,7 @@ export function redirect(url, status = 302) { const store = getContext(REDIRECT_CONTEXT); if (store) { const request = getContext(HTTP_CONTEXT).request; + store.location = url; store.response = request.method !== "GET" ? new Response( @@ -38,8 +40,3 @@ export function redirect(url, status = 302) { throw new RedirectError(url, status); } - -export function redirect$(handler) { - const store = getContext(REDIRECT_CONTEXT); - store.redirectHandlers.push(handler); -} diff --git a/packages/react-server/server/render-dom.mjs b/packages/react-server/server/render-dom.mjs index 6089b2f..d857bfc 100644 --- a/packages/react-server/server/render-dom.mjs +++ b/packages/react-server/server/render-dom.mjs @@ -27,6 +27,7 @@ export const createRenderer = ({ remote, origin, importMap, + defer, }) => { if (!flight) { throw new Error("No flight stream provided."); @@ -250,15 +251,15 @@ export const createRenderer = ({ // TODO: bootstrapScripts should be buffers instead of strings, fix script parts should be pre-encoded buffers then yield copy of those buffers const script = encoder.encode( - `${ + `${ importMap ? `` : "" - }${ + }${ hmr ? "" : bootstrapModules @@ -332,6 +333,8 @@ export const createRenderer = ({ }; const remoteWorker = async function* () { + let line = 1; + let tokenize = true; while (!(forwardDone && htmlDone)) { for await (const value of forwardWorker()) { if (hydrated) { @@ -345,9 +348,12 @@ export const createRenderer = ({ const parser = Parser.getFragmentParser(); for await (const value of htmlWorker()) { - const html = decoder.decode(value); - parser.tokenizer.write(html); + if (tokenize) { + const html = decoder.decode(value); + parser.tokenizer.write(html); + } } + tokenize = false; if (linkQueue.size > 0) { const links = Array.from(linkQueue); @@ -362,22 +368,21 @@ export const createRenderer = ({ } } - parser.tokenizer.write( - hydrated || (!hasClientComponent && !hasServerAction) - ? "" - : `${bootstrapScripts - .map( - (textContent) => `` - ) - .join("")}`, - true - ); - hydrated = true; + if (!defer && (hasClientComponent || hasServerAction)) { + while (bootstrapScripts.length > 0) { + const textContent = bootstrapScripts.shift(); + parser.tokenizer.write( + `` + ); + } + } const fragment = parser.getFragment(); if (fragment.childNodes.length > 0) { - const tree = dom2flight(fragment, { origin }); - yield encoder.encode(`0:${JSON.stringify(tree)}\n`); + const tree = dom2flight(fragment, { origin, defer }); + yield encoder.encode( + `${line++}:${JSON.stringify(tree)}\n` + ); } if (!started) { @@ -391,6 +396,13 @@ export const createRenderer = ({ }); } } + + yield encoder.encode( + `0:[${new Array(line - 1) + .fill(0) + .map((_, i) => `"$${i + 1}"`) + .join(",")}]\n` + ); }; const render = async () => { @@ -408,6 +420,7 @@ export const createRenderer = ({ done: true, error: e.message, stack: e.stack, + digest: e.digest, }); } }; @@ -419,6 +432,7 @@ export const createRenderer = ({ done: true, error: error.message, stack: error.stack, + digest: error.digest, }); } }, @@ -431,6 +445,7 @@ export const createRenderer = ({ done: true, error: error.message, stack: error.stack, + digest: error.digest, }); } }); diff --git a/packages/react-server/server/render-rsc.jsx b/packages/react-server/server/render-rsc.jsx index fe7c318..ef8281a 100644 --- a/packages/react-server/server/render-rsc.jsx +++ b/packages/react-server/server/render-rsc.jsx @@ -14,13 +14,15 @@ import { getContext, } from "@lazarv/react-server/server/context.mjs"; import { init$ as revalidate$ } from "@lazarv/react-server/server/revalidate.mjs"; -import { useOutlet } from "@lazarv/react-server/server/request.mjs"; +import { useOutlet, rewrite } from "@lazarv/react-server/server/request.mjs"; import { ACTION_CONTEXT, CACHE_CONTEXT, CACHE_MISS, CONFIG_CONTEXT, CONFIG_ROOT, + ERROR_BOUNDARY, + ERROR_COMPONENT, ERROR_CONTEXT, FLIGHT_CACHE, FORM_DATA_PARSER, @@ -59,7 +61,7 @@ const serverReferenceMap = new Proxy( } ); -export async function render(Component) { +export async function render(Component, props = {}, options = {}) { const logger = getContext(LOGGER_CONTEXT); const renderStream = getContext(RENDER_STREAM); const config = getContext(CONFIG_CONTEXT)?.[CONFIG_ROOT]; @@ -86,7 +88,9 @@ export async function render(Component) { ); if ( "POST,PUT,PATCH,DELETE".includes(context.request.method) && - ((serverActionHeader && serverActionHeader !== "null") || isFormData) + ((serverActionHeader && serverActionHeader !== "null") || + isFormData) && + !options.skipFunction ) { let action = async function () { throw new Error("Server action not found"); @@ -164,6 +168,12 @@ export async function render(Component) { ); } + if (typeof action !== "function") { + const e = new Error("Server Function Not Found"); + e.digest = e.message; + throw e; + } + const { data, actionId, error } = await action(); if (!isFormData) { @@ -194,7 +204,7 @@ export async function render(Component) { } const redirect = getContext(REDIRECT_CONTEXT); - if (redirect?.response) { + if (renderContext.flags.isHTML && redirect?.response) { return resolve(redirect.response); } @@ -231,7 +241,9 @@ export async function render(Component) { } } - const precedence = remote ? undefined : "default"; + const precedence = + // when rendering a remote component or the outlet name starts with http or https (escaped remote component outlet name), don't set the precedence + remote || /^https?___/.test(outlet) ? undefined : "default"; const configBaseHref = config.base ? (link) => `/${config.base}/${link?.id || link}`.replace(/\/+/g, "/") : (link) => link?.id || link; @@ -261,7 +273,7 @@ export async function render(Component) { const ComponentWithStyles = ( <> - + ); @@ -274,6 +286,16 @@ export async function render(Component) { }; } + const redirect = getContext(REDIRECT_CONTEXT); + if (redirect?.response) { + callServerHeaders = { + ...callServerHeaders, + "React-Server-Render": redirect.location, + "React-Server-Outlet": "PAGE_ROOT", + }; + rewrite(redirect.location); + } + let app = ComponentWithStyles; if (callServer) { callServerHeaders = { @@ -290,6 +312,31 @@ export async function render(Component) { ); } + if ( + !remote && + !callServer && + (!outlet || (outlet && outlet === "PAGE_ROOT")) + ) { + const ErrorComponent = getContext(ERROR_COMPONENT); + if (ErrorComponent) { + if ( + ErrorComponent.$$typeof === Symbol.for("react.client.reference") + ) { + const ErrorBoundary = getContext(ERROR_BOUNDARY); + if (ErrorBoundary) { + app = ( + <> + + + + + + ); + } + } + } + } + const lastModified = new Date().toUTCString(); if (renderContext.flags.isRSC && !renderContext.flags.isRemote) { if (!noCache && !callServer) { @@ -310,6 +357,7 @@ export async function render(Component) { } } + let hasError = false; const stream = new ReadableStream({ type: "bytes", async start(controller) { @@ -332,7 +380,17 @@ export async function render(Component) { const flight = server.renderToReadableStream( app, - clientReferenceMap({ remote, origin }) + clientReferenceMap({ remote, origin }), + { + onError(e) { + hasError = true; + const redirect = getContext(REDIRECT_CONTEXT); + if (redirect?.response) { + return `Location=${redirect.response.headers.get("location")}`; + } + return e?.message; + }, + } ); const reader = flight.getReader(); @@ -360,12 +418,6 @@ export async function render(Component) { const { value, done: _done } = res; done = _done; if (value) { - const redirect = getContext(REDIRECT_CONTEXT); - if (redirect?.response) { - controller.close(); - return resolve(redirect.response); - } - payload.push(copyBytesFrom(value)); } } @@ -399,20 +451,22 @@ export async function render(Component) { controller.close(); - getContext(CACHE_CONTEXT)?.set( - [ - context.url, - "text/x-component", - outlet, - FLIGHT_CACHE, - lastModified, - ], - { - ...httpStatus, - buffer: concat(payload), - headers, - } - ); + if (!hasError) { + getContext(CACHE_CONTEXT)?.set( + [ + context.url, + "text/x-component", + outlet, + FLIGHT_CACHE, + lastModified, + ], + { + ...httpStatus, + buffer: concat(payload), + headers, + } + ); + } }, }); } else if (renderContext.flags.isHTML || renderContext.flags.isRemote) { @@ -455,11 +509,13 @@ export async function render(Component) { }) ); + let hasError = false; const flight = server.renderToReadableStream( app, clientReferenceMap({ remote, origin }), { onError(e) { + hasError = true; const redirect = getContext(REDIRECT_CONTEXT); if (redirect?.response) { return resolve(redirect.response); @@ -505,6 +561,7 @@ export async function render(Component) { };`.replace(/\n/g, ""), ], outlet, + defer: context.request.headers.get("react-server-defer") === "true", start: async () => { isStarted = true; ContextStorage.run(contextStore, async () => { @@ -522,23 +579,25 @@ export async function render(Component) { const [responseStream, cacheStream] = stream.tee(); const payload = []; (async () => { - for await (const chunk of cacheStream) { - payload.push(copyBytesFrom(chunk)); - } - await getContext(CACHE_CONTEXT)?.set( - [ - context.url, - "text/html", - outlet, - HTML_CACHE, - lastModified, - ], - { - ...httpStatus, - buffer: concat(payload), - headers, + if (!hasError) { + for await (const chunk of cacheStream) { + payload.push(copyBytesFrom(chunk)); } - ); + await getContext(CACHE_CONTEXT)?.set( + [ + context.url, + "text/html", + outlet, + HTML_CACHE, + lastModified, + ], + { + ...httpStatus, + buffer: concat(payload), + headers, + } + ); + } })(); const response = new Response(responseStream, { @@ -551,8 +610,16 @@ export async function render(Component) { }, onError(e, digest) { logger.error(e, digest); + if (digest) { + e.digest = digest; + } + hasError = true; if (!isStarted) { ContextStorage.run(contextStore, async () => { + context$(HTTP_STATUS, { + status: 500, + statusText: "Internal Server Error", + }); getContext(ERROR_CONTEXT)?.(e)?.then(resolve, reject); }); } diff --git a/packages/react-server/server/render.mjs b/packages/react-server/server/render.mjs index 7b59a45..e787965 100644 --- a/packages/react-server/server/render.mjs +++ b/packages/react-server/server/render.mjs @@ -1,11 +1,14 @@ import { immediate } from "../lib/sys.mjs"; import { context$, getContext } from "./context.mjs"; -import { RENDER, RENDER_WAIT } from "./symbols.mjs"; +import { RENDER, RENDER_CONTEXT, RENDER_WAIT } from "./symbols.mjs"; const RENDER_LOCK = Symbol("RENDER_LOCK"); export function useRender() { const render = getContext(RENDER); + const context = getContext(RENDER_CONTEXT); + const isRemote = context?.flags.isRemote; + const isFunction = context?.flags.isFunction; const lock = (fn) => { context$(RENDER_LOCK, (getContext(RENDER_LOCK) ?? 0) + 1); @@ -37,5 +40,5 @@ export function useRender() { }); }; - return { render, lock }; + return { render, lock, isRemote, isFunction }; } diff --git a/packages/react-server/server/symbols.mjs b/packages/react-server/server/symbols.mjs index 3d3d235..9ccecab 100644 --- a/packages/react-server/server/symbols.mjs +++ b/packages/react-server/server/symbols.mjs @@ -10,6 +10,8 @@ export const HTTP_OUTLET = Symbol.for("HTTP_OUTLET"); export const HTTP_RESPONSE = Symbol.for("HTTP_RESPONSE"); export const REDIRECT_CONTEXT = Symbol.for("REDIRECT_CONTEXT"); export const MODULE_LOADER = Symbol.for("MODULE_LOADER"); +export const ERROR_BOUNDARY = Symbol.for("ERROR_BOUNDARY"); +export const ERROR_COMPONENT = Symbol.for("ERROR_COMPONENT"); export const ERROR_CONTEXT = Symbol.for("ERROR_CONTEXT"); export const MEMORY_CACHE_CONTEXT = Symbol.for("MEMORY_CACHE_CONTEXT"); export const CACHE_CONTEXT = Symbol.for("CACHE_CONTEXT"); @@ -28,6 +30,7 @@ export const RELOAD = Symbol.for("RELOAD"); export const RENDER = Symbol.for("RENDER"); export const RENDER_STREAM = Symbol.for("RENDER_STREAM"); export const RENDER_CONTEXT = Symbol.for("RENDER_CONTEXT"); +export const RENDER_HANDLER = Symbol.for("RENDER_HANDLER"); export const RENDER_WAIT = Symbol.for("RENDER_WAIT"); export const WORKER_THREAD = Symbol.for("WORKER_THREAD"); export const PRELUDE_HTML = Symbol.for("PRELUDE_HTML"); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8a2cc9..30dcf3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,7 +76,7 @@ importers: version: 6.10.1(eslint@9.13.0(jiti@1.21.6)) eslint-plugin-prettier: specifier: ^5.2.1 - version: 5.2.1(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(prettier@3.3.2) + version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(prettier@3.3.2) eslint-plugin-react: specifier: ^7.37.2 version: 7.37.2(eslint@9.13.0(jiti@1.21.6)) @@ -109,7 +109,7 @@ importers: dependencies: '@docsearch/react': specifier: '3' - version: 3.6.0(@algolia/client-search@5.10.2)(@types/react@18.3.3)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(search-insights@2.14.0) + version: 3.6.0(@algolia/client-search@5.10.2)(@types/react@18.3.3)(search-insights@2.14.0) '@lazarv/react-server': specifier: workspace:^ version: link:../packages/react-server @@ -118,16 +118,16 @@ importers: version: link:../packages/react-server-adapter-vercel '@uidotdev/usehooks': specifier: ^2.4.1 - version: 2.4.1(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731) + version: 2.4.1 '@vercel/analytics': - specifier: ^1.3.1 - version: 1.3.1(next@14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6))(react@19.0.0-rc-a7d1240c-20240731) + specifier: ^1.4.1 + version: 1.4.1 '@vercel/speed-insights': - specifier: ^1.0.12 - version: 1.0.12(next@14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6))(react@19.0.0-rc-a7d1240c-20240731) + specifier: ^1.1.0 + version: 1.1.0 '@vitejs/plugin-react-swc': specifier: ^3.7.0 - version: 3.7.0(@swc/helpers@0.5.5)(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1)) + version: 3.7.0(@swc/helpers@0.5.5)(vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0)) algoliasearch: specifier: ^4.24.0 version: 4.24.0 @@ -136,7 +136,7 @@ importers: version: 11.9.0 lucide-react: specifier: ^0.408.0 - version: 0.408.0(react@19.0.0-rc-a7d1240c-20240731) + version: 0.408.0 rehype-highlight: specifier: ^7.0.0 version: 7.0.0 @@ -148,7 +148,7 @@ importers: version: 4.0.0 vite-plugin-svgr: specifier: ^4.2.0 - version: 4.2.0(rollup@4.24.0)(typescript@5.6.3)(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1)) + version: 4.2.0(rollup@4.24.0)(typescript@5.7.2)(vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0)) devDependencies: '@types/react': specifier: ^18.3.2 @@ -164,7 +164,7 @@ importers: version: 1.77.6 tailwindcss: specifier: ^3.4.3 - version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) examples/chakra-ui: dependencies: @@ -343,13 +343,13 @@ importers: version: link:../../packages/react-server '@nestjs/common': specifier: ^10.0.0 - version: 10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1) + version: 10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': specifier: ^10.0.0 - version: 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.9)(reflect-metadata@0.2.2)(rxjs@7.8.1) + version: 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/platform-express': specifier: ^10.0.0 - version: 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9) + version: 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15) reflect-metadata: specifier: ^0.2.0 version: 0.2.2 @@ -359,25 +359,25 @@ importers: devDependencies: '@nestjs/cli': specifier: ^10.0.0 - version: 10.3.2(@swc/core@1.6.6(@swc/helpers@0.5.5)) + version: 10.4.9(@swc/core@1.6.6(@swc/helpers@0.5.5)) '@nestjs/schematics': specifier: ^10.0.0 - version: 10.1.1(chokidar@3.6.0)(typescript@5.5.2) + version: 10.2.3(chokidar@3.6.0)(typescript@5.6.3) '@nestjs/testing': specifier: ^10.0.0 - version: 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9)(@nestjs/platform-express@10.3.9) + version: 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15)(@nestjs/platform-express@10.4.15) '@types/express': specifier: ^4.17.17 version: 4.17.21 '@types/jest': specifier: ^29.5.2 - version: 29.5.12 + version: 29.5.14 '@types/node': specifier: ^20.3.1 - version: 20.14.9 + version: 20.17.11 '@types/react': specifier: ^18.3.2 - version: 18.3.3 + version: 18.3.5 '@types/react-dom': specifier: ^18.3.0 version: 18.3.0 @@ -386,22 +386,22 @@ importers: version: 6.0.2 '@typescript-eslint/eslint-plugin': specifier: ^6.0.0 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/parser': specifier: ^6.0.0 - version: 6.21.0(eslint@8.57.0)(typescript@5.5.2) + version: 6.21.0(eslint@8.57.1)(typescript@5.6.3) eslint: specifier: ^8.42.0 - version: 8.57.0 + version: 8.57.1 eslint-config-prettier: specifier: ^9.0.0 - version: 9.1.0(eslint@8.57.0) + version: 9.1.0(eslint@8.57.1) eslint-plugin-prettier: specifier: ^5.0.0 - version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) + version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.2) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + version: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) prettier: specifier: ^3.0.0 version: 3.3.2 @@ -413,19 +413,19 @@ importers: version: 6.3.4 ts-jest: specifier: ^29.1.0 - version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)))(typescript@5.5.2) + version: 29.2.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)))(typescript@5.6.3) ts-loader: specifier: ^9.4.3 - version: 9.5.1(typescript@5.5.2)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) + version: 9.5.1(typescript@5.6.3)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) ts-node: specifier: ^10.9.1 - version: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2) + version: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3) tsconfig-paths: specifier: ^4.2.0 version: 4.2.0 typescript: specifier: ^5.1.3 - version: 5.5.2 + version: 5.6.3 examples/photos: dependencies: @@ -453,7 +453,38 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.4.3 - version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) + + examples/pokemon: + dependencies: + '@lazarv/react-server': + specifier: workspace:^ + version: link:../../packages/react-server + clsx: + specifier: ^2.1.1 + version: 2.1.1 + tailwind-merge: + specifier: ^2.6.0 + version: 2.6.0 + devDependencies: + '@types/react': + specifier: ^18.3.2 + version: 18.3.5 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.0 + autoprefixer: + specifier: ^10.4.19 + version: 10.4.19(postcss@8.4.45) + postcss: + specifier: ^8.4.38 + version: 8.4.45 + tailwindcss: + specifier: ^3.4.3 + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) + vite: + specifier: 6.0.0-alpha.18 + version: 6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) examples/react-query: dependencies: @@ -492,6 +523,15 @@ importers: specifier: ^4.1.5 version: 4.1.5 + examples/session-cookie: + dependencies: + '@lazarv/react-server': + specifier: workspace:^ + version: link:../../packages/react-server + iron-session: + specifier: ^8.0.4 + version: 8.0.4 + examples/spa: dependencies: '@lazarv/react-server': @@ -506,7 +546,7 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.4.3 - version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) examples/tanstack-router: dependencies: @@ -522,7 +562,7 @@ importers: version: 1.43.3(@tanstack/react-router@1.43.3(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731))(csstype@3.1.3)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731) '@tanstack/router-plugin': specifier: ^1.39.13 - version: 1.43.1(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1)) + version: 1.43.1(vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0)) '@types/react': specifier: ^18.3.2 version: 18.3.3 @@ -537,7 +577,7 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.4.3 - version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) examples/todo: dependencies: @@ -568,7 +608,7 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.4.3 - version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + version: 3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) packages/react-server: dependencies: @@ -613,7 +653,7 @@ importers: version: 18.3.0 '@vitejs/plugin-react': specifier: ^4.3.0 - version: 4.3.1(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1)) + version: 4.3.1(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0)) acorn: specifier: ^8.10.0 version: 8.12.0 @@ -685,7 +725,7 @@ importers: version: 2.0.2 react-server-dom-webpack: specifier: 0.0.0-experimental-204a551e-20240926 - version: 0.0.0-experimental-204a551e-20240926(react-dom@0.0.0-experimental-204a551e-20240926(react@0.0.0-experimental-204a551e-20240926))(react@0.0.0-experimental-204a551e-20240926)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)) + version: 0.0.0-experimental-204a551e-20240926(react-dom@0.0.0-experimental-204a551e-20240926(react@0.0.0-experimental-204a551e-20240926))(react@0.0.0-experimental-204a551e-20240926)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)) remark-frontmatter: specifier: ^5.0.0 version: 5.0.0 @@ -706,7 +746,7 @@ importers: version: 1.1.12 vite: specifier: 6.0.0-alpha.18 - version: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + version: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) devDependencies: '@types/node': specifier: ^20.10.0 @@ -759,7 +799,7 @@ importers: version: 4.13.0 vite: specifier: 6.0.0-alpha.18 - version: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + version: 6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) devDependencies: '@vitest/ui': specifier: ^2.1.3 @@ -772,7 +812,7 @@ importers: version: 1.46.1 vitest: specifier: ^2.1.3 - version: 2.1.3(@types/node@20.14.9)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + version: 2.1.3(@types/node@22.9.0)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) packages: @@ -904,8 +944,8 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular-devkit/core@17.1.2': - resolution: {integrity: sha512-ku+/W/HMCBacSWFppenr9y6Lx8mDuTuQvn1IkTyBLiJOpWnzgVbx9kHDeaDchGa1PwLlJUBBrv27t3qgJOIDPw==} + '@angular-devkit/core@17.3.11': + resolution: {integrity: sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==} engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^3.5.2 @@ -913,13 +953,13 @@ packages: chokidar: optional: true - '@angular-devkit/schematics-cli@17.1.2': - resolution: {integrity: sha512-bvXykYzSST05qFdlgIzUguNOb3z0hCa8HaTwtqdmQo9aFPf+P+/AC56I64t1iTchMjQtf3JrBQhYM25gUdcGbg==} + '@angular-devkit/schematics-cli@17.3.11': + resolution: {integrity: sha512-kcOMqp+PHAKkqRad7Zd7PbpqJ0LqLaNZdY1+k66lLWmkEBozgq8v4ASn/puPWf9Bo0HpCiK+EzLf0VHE8Z/y6Q==} engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/schematics@17.1.2': - resolution: {integrity: sha512-8S9RuM8olFN/gwN+mjbuF1CwHX61f0i59EGXz9tXLnKRUTjsRR+8vVMTAmX0dvVAT5fJTG/T69X+HX7FeumdqA==} + '@angular-devkit/schematics@17.3.11': + resolution: {integrity: sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==} engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@babel/code-frame@7.24.7': @@ -1064,12 +1104,24 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-import-assertions@7.25.9': resolution: {integrity: sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-import-meta@7.10.4': resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: @@ -1122,6 +1174,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-top-level-await@7.14.5': resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} @@ -2137,8 +2195,8 @@ packages: resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@eslint/js@9.13.0': @@ -2213,8 +2271,8 @@ packages: resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} engines: {node: '>=18.18.0'} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead @@ -2370,6 +2428,10 @@ packages: resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -2381,9 +2443,6 @@ 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==} @@ -2623,12 +2682,12 @@ packages: '@types/react': optional: true - '@nestjs/cli@10.3.2': - resolution: {integrity: sha512-aWmD1GLluWrbuC4a1Iz/XBk5p74Uj6nIVZj6Ov03JbTfgtWqGFLtXuMetvzMiHxfrHehx/myt2iKAPRhKdZvTg==} + '@nestjs/cli@10.4.9': + resolution: {integrity: sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==} engines: {node: '>= 16.14'} hasBin: true peerDependencies: - '@swc/cli': ^0.1.62 || ^0.3.0 + '@swc/cli': ^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 '@swc/core': ^1.3.62 peerDependenciesMeta: '@swc/cli': @@ -2636,8 +2695,8 @@ packages: '@swc/core': optional: true - '@nestjs/common@10.3.9': - resolution: {integrity: sha512-JAQONPagMa+sy/fcIqh/Hn3rkYQ9pQM51vXCFNOM5ujefxUVqn3gwFRMN8Y1+MxdUHipV+8daEj2jEm0IqJzOA==} + '@nestjs/common@10.4.15': + resolution: {integrity: sha512-vaLg1ZgwhG29BuLDxPA9OAcIlgqzp9/N8iG0wGapyUNTf4IY4O6zAHgN6QalwLhFxq7nOI021vdRojR1oF3bqg==} peerDependencies: class-transformer: '*' class-validator: '*' @@ -2649,8 +2708,8 @@ packages: class-validator: optional: true - '@nestjs/core@10.3.9': - resolution: {integrity: sha512-NzZUfWAmaf8sqhhwoRA+CuqxQe+P4Rz8PZp5U7CdCbjyeB9ZVGcBkihcJC9wMdtiOWHRndB2J8zRfs5w06jK3w==} + '@nestjs/core@10.4.15': + resolution: {integrity: sha512-UBejmdiYwaH6fTsz2QFBlC1cJHM+3UDeLZN+CiP9I1fRv2KlBZsmozGLbV5eS1JAVWJB4T5N5yQ0gjN8ZvcS2w==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/microservices': ^10.0.0 @@ -2666,19 +2725,19 @@ packages: '@nestjs/websockets': optional: true - '@nestjs/platform-express@10.3.9': - resolution: {integrity: sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==} + '@nestjs/platform-express@10.4.15': + resolution: {integrity: sha512-63ZZPkXHjoDyO7ahGOVcybZCRa7/Scp6mObQKjcX/fTEq1YJeU75ELvMsuQgc8U2opMGOBD7GVuc4DV0oeDHoA==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 - '@nestjs/schematics@10.1.1': - resolution: {integrity: sha512-o4lfCnEeIkfJhGBbLZxTuVWcGuqDCFwg5OrvpgRUBM7vI/vONvKKiB5riVNpO+JqXoH0I42NNeDb0m4V5RREig==} + '@nestjs/schematics@10.2.3': + resolution: {integrity: sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==} peerDependencies: typescript: '>=4.8.2' - '@nestjs/testing@10.3.9': - resolution: {integrity: sha512-z24SdpZIRtYyM5s2vnu7rbBosXJY/KcAP7oJlwgFa/h/z/wg8gzyoKy5lhibH//OZNO+pYKajV5wczxuy5WeAg==} + '@nestjs/testing@10.4.15': + resolution: {integrity: sha512-eGlWESkACMKti+iZk1hs6FUY/UqObmMaa8HAN9JLnaYkoLf1Jeh+EuHlGnfqo/Rq77oznNLIyaA3PFjrFDlNUg==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 @@ -2690,63 +2749,6 @@ packages: '@nestjs/platform-express': optional: true - '@next/env@14.2.8': - resolution: {integrity: sha512-L44a+ynqkolyNBnYfF8VoCiSrjSZWgEHYKkKLGcs/a80qh7AkfVUD/MduVPgdsWZ31tgROR+yJRA0PZjSVBXWQ==} - - '@next/swc-darwin-arm64@14.2.8': - resolution: {integrity: sha512-1VrQlG8OzdyvvGZhGJFnaNE2P10Jjy/2FopnqbY0nSa/gr8If3iINxvOEW3cmVeoAYkmW0RsBazQecA2dBFOSw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@14.2.8': - resolution: {integrity: sha512-87t3I86rNRSOJB1gXIUzaQWWSWrkWPDyZGsR0Z7JAPtLeX3uUOW2fHxl7dNWD2BZvbvftctTQjgtfpp7nMtmWg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@14.2.8': - resolution: {integrity: sha512-ta2sfVzbOpTbgBrF9HM5m+U58dv6QPuwU4n5EX4LLyCJGKc433Z0D9h9gay/HSOjLEXJ2fJYrMP5JYYbHdxhtw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@14.2.8': - resolution: {integrity: sha512-+IoLTPK6Z5uIgDhgeWnQF5/o5GBN7+zyUNrs4Bes1W3g9++YELb8y0unFybS8s87ntAKMDl6jeQ+mD7oNwp/Ng==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@14.2.8': - resolution: {integrity: sha512-pO+hVXC+mvzUOQJJRG4RX4wJsRJ5BkURSf6dD6EjUXAX4Ml9es1WsEfkaZ4lcpmFzFvY47IkDaffks/GdCn9ag==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@14.2.8': - resolution: {integrity: sha512-bCat9izctychCtf3uL1nqHq31N5e1VxvdyNcBQflkudPMLbxVnlrw45Vi87K+lt1CwrtVayHqzo4ie0Szcpwzg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@14.2.8': - resolution: {integrity: sha512-gbxfUaSPV7EyUobpavida2Hwi62GhSJaSg7iBjmBWoxkxlmETOD7U4tWt763cGIsyE6jM7IoNavq0BXqwdW2QA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-ia32-msvc@14.2.8': - resolution: {integrity: sha512-PUXzEzjTTlUh3b5VAn1nlpwvujTnuCMMwbiCnaTazoVlN1nA3kWjlmp42IfURA2N/nyrlVEw7pURa/o4Qxj1cw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@next/swc-win32-x64-msvc@14.2.8': - resolution: {integrity: sha512-EnPKv0ttq02E9/1KZ/8Dn7kuutv6hy1CKc0HlNcvzOQcm4/SQtvfws5gY0zrG9tuupd3HfC2L/zcTrnBhpjTuQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} @@ -3461,8 +3463,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.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -3473,8 +3475,8 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/express-serve-static-core@4.19.5': - resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -3497,8 +3499,8 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - '@types/jest@29.5.12': - resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3527,6 +3529,12 @@ packages: '@types/node@20.14.9': resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + '@types/node@20.17.11': + resolution: {integrity: sha512-Ept5glCK35R8yeyIeYlRIZtX6SLRyqMhOFTgj5SOkMpLTdw3SEHI9fHx60xaUZ+V1aJxQJODE+7/j5ocZydYTg==} + + '@types/node@22.9.0': + resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} + '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -3539,8 +3547,8 @@ packages: '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - '@types/qs@6.9.15': - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + '@types/qs@6.9.17': + resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -3569,8 +3577,8 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - '@types/superagent@8.1.7': - resolution: {integrity: sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==} + '@types/superagent@8.1.9': + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} '@types/supertest@6.0.2': resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==} @@ -3587,8 +3595,8 @@ packages: '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.32': - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} '@typescript-eslint/eslint-plugin@6.21.0': resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} @@ -3715,29 +3723,44 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vercel/analytics@1.3.1': - resolution: {integrity: sha512-xhSlYgAuJ6Q4WQGkzYTLmXwhYl39sWjoMA3nHxfkvG+WdBT25c563a7QhwwKivEOZtPJXifYHR1m2ihoisbWyA==} + '@vercel/analytics@1.4.1': + resolution: {integrity: sha512-ekpL4ReX2TH3LnrRZTUKjHHNpNy9S1I7QmS+g/RQXoSUQ8ienzosuX7T9djZ/s8zPhBx1mpHP/Rw5875N+zQIQ==} peerDependencies: + '@remix-run/react': ^2 + '@sveltejs/kit': ^1 || ^2 next: '>= 13' react: 0.0.0-experimental-204a551e-20240926 + svelte: '>= 4' + vue: ^3 + vue-router: ^4 peerDependenciesMeta: + '@remix-run/react': + optional: true + '@sveltejs/kit': + optional: true next: optional: true react: optional: true + svelte: + optional: true + vue: + optional: true + vue-router: + optional: true '@vercel/nft@0.27.2': resolution: {integrity: sha512-7LeioS1yE5hwPpQfD3DdH04tuugKjo5KrJk3yK5kAI3Lh76iSsK/ezoFQfzuT08X3ZASQOd1y9ePjLNI9+TxTQ==} engines: {node: '>=16'} hasBin: true - '@vercel/speed-insights@1.0.12': - resolution: {integrity: sha512-ZGQ+a7bcfWJD2VYEp2R1LHvRAMyyaFBYytZXsfnbOMkeOvzGNVxUL7aVUvisIrTZjXTSsxG45DKX7yiw6nq2Jw==} + '@vercel/speed-insights@1.1.0': + resolution: {integrity: sha512-rAXxuhhO4mlRGC9noa5F7HLMtGg8YF1zAN6Pjd1Ny4pII4cerhtwSG4vympbCl+pWkH7nBS9kVXRD4FAn54dlg==} peerDependencies: '@sveltejs/kit': ^1 || ^2 next: '>= 13' react: 0.0.0-experimental-204a551e-20240926 - svelte: ^4 + svelte: '>= 4' vue: ^3 vue-router: ^4 peerDependenciesMeta: @@ -3803,50 +3826,50 @@ packages: '@vitest/utils@2.1.3': resolution: {integrity: sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==} - '@webassemblyjs/ast@1.12.1': - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - '@webassemblyjs/floating-point-hex-parser@1.11.6': - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - '@webassemblyjs/helper-api-error@1.11.6': - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - '@webassemblyjs/helper-buffer@1.12.1': - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - '@webassemblyjs/helper-numbers@1.11.6': - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - '@webassemblyjs/helper-wasm-bytecode@1.11.6': - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - '@webassemblyjs/helper-wasm-section@1.12.1': - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - '@webassemblyjs/ieee754@1.11.6': - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - '@webassemblyjs/leb128@1.11.6': - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - '@webassemblyjs/utf8@1.11.6': - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - '@webassemblyjs/wasm-edit@1.12.1': - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - '@webassemblyjs/wasm-gen@1.12.1': - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - '@webassemblyjs/wasm-opt@1.12.1': - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - '@webassemblyjs/wasm-parser@1.12.1': - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - '@webassemblyjs/wast-printer@1.12.1': - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -3878,11 +3901,6 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} - 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: @@ -3897,8 +3915,8 @@ packages: resolution: {integrity: sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==} engines: {node: '>=0.4.0'} - acorn-walk@8.3.3: - resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} acorn@8.12.0: @@ -3906,6 +3924,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -3923,12 +3946,20 @@ packages: peerDependencies: ajv: ^6.9.1 + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + algoliasearch@4.24.0: resolution: {integrity: sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==} @@ -4068,6 +4099,9 @@ packages: async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -4115,8 +4149,8 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} - 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 @@ -4159,6 +4193,10 @@ packages: resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + bplist-parser@0.2.0: resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} engines: {node: '>= 5.10.0'} @@ -4178,6 +4216,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.24.3: + resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bs-logger@0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} engines: {node: '>= 6'} @@ -4233,8 +4276,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001638: - resolution: {integrity: sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==} + caniuse-lite@1.0.30001690: + resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -4297,8 +4340,8 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - cjs-module-lexer@1.3.1: - resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} @@ -4320,8 +4363,8 @@ packages: resolution: {integrity: sha512-5p/5f8xOjTiyEpdc5KNulSLl5dOOgPQa/m4Rj6fF5UZubWIAvpVIJlnROBbJw+PZHKHlRlYv3KSfGYlecD7qrQ==} engines: {node: '>=18.20'} - cli-table3@0.6.3: - resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} cli-truncate@4.0.0: @@ -4336,9 +4379,6 @@ packages: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -4402,8 +4442,8 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - comment-json@4.2.3: - resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + comment-json@4.2.5: + resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==} engines: {node: '>= 6'} compare-func@2.0.0: @@ -4474,6 +4514,14 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + cookiejar@2.1.4: resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} @@ -4628,15 +4676,6 @@ packages: supports-color: optional: true - 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'} @@ -4804,9 +4843,17 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + electron-to-chromium@1.4.815: resolution: {integrity: sha512-OvpTT2ItpOXJL7IGcYakRjHCt8L5GrrN/wHCQsRB4PQa1X9fe+X9oen245mIId7s14xvArCGSTIq644yPUKKLg==} + electron-to-chromium@1.5.76: + resolution: {integrity: sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==} + embla-carousel-react@8.2.1: resolution: {integrity: sha512-YKtARk101mp00Zb6UAFkkvK+5XRo92LAtO9xLFeDnQ/XU9DqFhKnRy1CedRRj0/RSk6MTFDx3MqOQue3gJj9DA==} peerDependencies: @@ -4837,11 +4884,15 @@ packages: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - enhanced-resolve@5.17.0: - resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} + enhanced-resolve@5.18.0: + resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==} engines: {node: '>=10.13.0'} entities@4.5.0: @@ -4879,8 +4930,8 @@ packages: resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} engines: {node: '>= 0.4'} - es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} @@ -4911,6 +4962,10 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -4947,20 +5002,6 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - eslint-plugin-prettier@5.2.1: resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -5010,8 +5051,8 @@ packages: resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true @@ -5129,6 +5170,10 @@ packages: resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} engines: {node: '>= 0.10.0'} + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -5163,6 +5208,9 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fast-uri@3.0.4: + resolution: {integrity: sha512-G3iTQw1DizJQ5eEqj1CbFCWhq+pzum7qepkxU7rS1FGZDqjYKcrguo9XDRbV7EgPnn8CgaPigTq+NEjyioeYZQ==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -5187,10 +5235,6 @@ packages: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} - figures@5.0.0: - resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} - engines: {node: '>=14'} - file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -5202,6 +5246,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==} + filesize@10.1.2: resolution: {integrity: sha512-Dx770ai81ohflojxhU+oG+Z2QGvKdYxgEr9OSA8UVrqhwNHjfH9A8f5NKfg83fEH8ZFA5N5llJo5T3PIoZ4CRA==} engines: {node: '>= 10.4.0'} @@ -5218,6 +5265,10 @@ packages: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} @@ -5262,16 +5313,16 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - formidable@3.5.1: - resolution: {integrity: sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==} + formidable@3.5.2: + resolution: {integrity: sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==} forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} @@ -5393,24 +5444,19 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - glob@10.4.2: resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} engines: {node: '>=16 || 14 >=14.18'} hasBin: true + 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@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} - global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} @@ -5508,8 +5554,8 @@ packages: hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - hexoid@1.0.0: - resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} + hexoid@2.0.0: + resolution: {integrity: sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==} engines: {node: '>=8'} highlight.js@11.9.0: @@ -5581,8 +5627,8 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} - 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 @@ -5617,9 +5663,9 @@ packages: resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} engines: {node: '>=12.0.0'} - inquirer@9.2.12: - resolution: {integrity: sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==} - engines: {node: '>=14.18.0'} + inquirer@9.2.15: + resolution: {integrity: sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==} + engines: {node: '>=18'} internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} @@ -5629,10 +5675,6 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} @@ -5640,6 +5682,12 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + iron-session@8.0.4: + resolution: {integrity: sha512-9ivNnaKOd08osD0lJ3i6If23GFS2LsxyMU8Gf/uBUEgm8/8CC1hrrCHFDpMo3IFbpBgwoo/eairRsaD3c5itxA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + is-alphabetical@2.0.1: resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} @@ -5811,10 +5859,6 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -5854,8 +5898,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: @@ -5878,14 +5922,15 @@ packages: resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} engines: {node: '>= 0.4'} - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - jackspeak@3.4.0: resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} engines: {node: '>=14'} + 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==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6071,12 +6116,12 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - 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@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -6246,8 +6291,8 @@ packages: magic-string@0.30.12: resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} - magic-string@0.30.5: - resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + magic-string@0.30.8: + resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} engines: {node: '>=12'} make-dir@2.1.0: @@ -6355,6 +6400,9 @@ packages: merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -6520,9 +6568,9 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} @@ -6539,10 +6587,6 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} - minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} @@ -6627,24 +6671,6 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - next@14.2.8: - resolution: {integrity: sha512-EyEyJZ89r8C5FPlS/401AiF3O8jeMtHIE+bLom9MwcdWJJFBgRl+MR/2VgO0v5bI6tQORNY0a0DR5sjpFNrjbg==} - engines: {node: '>=18.17.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - sass: - optional: true - nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} @@ -6683,6 +6709,9 @@ packages: node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + nopt@5.0.0: resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} engines: {node: '>=6'} @@ -6891,11 +6920,14 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - path-to-regexp@3.2.0: - resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} + path-to-regexp@3.3.0: + resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} path-type@3.0.0: resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} @@ -6918,13 +6950,16 @@ packages: picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@3.0.1: - resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} - engines: {node: '>=10'} + picomatch@4.0.1: + resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} + engines: {node: '>=12'} picomatch@4.0.2: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} @@ -7079,10 +7114,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.4.39: resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} @@ -7216,8 +7247,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'} query-registry@3.0.1: @@ -7431,10 +7462,6 @@ packages: react: ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} @@ -7506,8 +7533,8 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} engines: {node: '>=10'} resolve@1.22.8: @@ -7538,11 +7565,6 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@4.4.1: - resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} - engines: {node: '>=14'} - hasBin: true - rollup@4.13.0: resolution: {integrity: sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7616,6 +7638,10 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} + schema-utils@4.3.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} + search-insights@2.14.0: resolution: {integrity: sha512-OLN6MsPMCghDOqlCtsIsYgtsC0pnwVTyT9Mu6A3ewOj1DxvzZF6COrn2g86E/c05xbktB0XN04m/t1Z+n+fTGw==} @@ -7627,11 +7653,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 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'} @@ -7641,6 +7662,10 @@ packages: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -7648,8 +7673,9 @@ packages: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} - server-only@0.0.1: - resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} @@ -7684,11 +7710,6 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -7906,19 +7927,6 @@ packages: style-to-object@1.0.6: resolution: {integrity: sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==} - styled-jsx@5.1.1: - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} @@ -7968,10 +7976,6 @@ packages: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} - engines: {node: ^14.18.0 || >=16.0.0} - synckit@0.9.2: resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -7979,6 +7983,9 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tailwind-merge@2.6.0: + resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} + tailwindcss@3.4.4: resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} engines: {node: '>=14.0.0'} @@ -7999,8 +8006,8 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - terser-webpack-plugin@5.3.10: - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + terser-webpack-plugin@5.3.11: + resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -8015,8 +8022,8 @@ packages: uglify-js: optional: true - terser@5.31.1: - resolution: {integrity: sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==} + terser@5.37.0: + resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==} engines: {node: '>=10'} hasBin: true @@ -8130,8 +8137,8 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-jest@29.1.5: - resolution: {integrity: sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==} + ts-jest@29.2.5: + resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -8175,8 +8182,8 @@ packages: '@swc/wasm': optional: true - tsconfig-paths-webpack-plugin@4.1.0: - resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} + tsconfig-paths-webpack-plugin@4.2.0: + resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} engines: {node: '>=10.13.0'} tsconfig-paths@4.2.0: @@ -8186,12 +8193,12 @@ packages: tslib@2.4.0: resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -8243,11 +8250,6 @@ packages: peerDependencies: typescript: '>=4.0.0' - typescript@5.3.3: - resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.5.2: resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} engines: {node: '>=14.17'} @@ -8258,6 +8260,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} @@ -8271,9 +8278,15 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici@6.19.8: resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} engines: {node: '>=18.17'} @@ -8334,6 +8347,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -8520,8 +8539,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'} wcwidth@1.0.1: @@ -8541,8 +8560,8 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - webpack@5.90.1: - resolution: {integrity: sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==} + webpack@5.97.1: + resolution: {integrity: sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -8867,33 +8886,33 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@angular-devkit/core@17.1.2(chokidar@3.6.0)': + '@angular-devkit/core@17.3.11(chokidar@3.6.0)': dependencies: ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) - jsonc-parser: 3.2.0 - picomatch: 3.0.1 + jsonc-parser: 3.2.1 + picomatch: 4.0.1 rxjs: 7.8.1 source-map: 0.7.4 optionalDependencies: chokidar: 3.6.0 - '@angular-devkit/schematics-cli@17.1.2(chokidar@3.6.0)': + '@angular-devkit/schematics-cli@17.3.11(chokidar@3.6.0)': dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) + '@angular-devkit/core': 17.3.11(chokidar@3.6.0) + '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0) ansi-colors: 4.1.3 - inquirer: 9.2.12 + inquirer: 9.2.15 symbol-observable: 4.0.0 yargs-parser: 21.1.1 transitivePeerDependencies: - chokidar - '@angular-devkit/schematics@17.1.2(chokidar@3.6.0)': + '@angular-devkit/schematics@17.3.11(chokidar@3.6.0)': dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - jsonc-parser: 3.2.0 - magic-string: 0.30.5 + '@angular-devkit/core': 17.3.11(chokidar@3.6.0) + jsonc-parser: 3.2.1 + magic-string: 0.30.8 ora: 5.4.1 rxjs: 7.8.1 transitivePeerDependencies: @@ -9072,11 +9091,21 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-import-assertions@7.25.9(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 @@ -9127,6 +9156,11 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 @@ -9973,7 +10007,7 @@ snapshots: '@commitlint/config-validator@19.0.3': dependencies: '@commitlint/types': 19.0.3 - ajv: 8.12.0 + ajv: 8.17.1 '@commitlint/ensure@19.0.3': dependencies: @@ -10069,7 +10103,7 @@ snapshots: '@docsearch/css@3.6.0': {} - '@docsearch/react@3.6.0(@algolia/client-search@5.10.2)(@types/react@18.3.3)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(search-insights@2.14.0)': + '@docsearch/react@3.6.0(@algolia/client-search@5.10.2)(@types/react@18.3.3)(search-insights@2.14.0)': dependencies: '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@5.10.2)(algoliasearch@4.24.0)(search-insights@2.14.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@5.10.2)(algoliasearch@4.24.0) @@ -10077,8 +10111,6 @@ snapshots: algoliasearch: 4.24.0 optionalDependencies: '@types/react': 18.3.3 - react: 19.0.0-rc-a7d1240c-20240731 - react-dom: 19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731) search-insights: 2.14.0 transitivePeerDependencies: - '@algolia/client-search' @@ -10304,9 +10336,9 @@ snapshots: '@esbuild/win32-x64@0.21.3': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: - eslint: 8.57.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0(jiti@1.21.6))': @@ -10319,7 +10351,7 @@ snapshots: '@eslint/config-array@0.18.0': dependencies: '@eslint/object-schema': 2.1.4 - debug: 4.3.6 + debug: 4.4.0 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -10354,7 +10386,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@8.57.1': {} '@eslint/js@9.13.0': {} @@ -10436,7 +10468,7 @@ snapshots: '@humanfs/core': 0.19.0 '@humanwhocodes/retry': 0.3.1 - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.4.0 @@ -10589,27 +10621,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.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(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.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.14.9 + '@types/node': 20.17.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.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + jest-config: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -10634,7 +10666,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -10652,7 +10684,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.9 + '@types/node': 20.17.11 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -10674,14 +10706,14 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.9 + '@types/node': 20.17.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 @@ -10744,8 +10776,8 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.9 - '@types/yargs': 17.0.32 + '@types/node': 20.17.11 + '@types/yargs': 17.0.33 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.5': @@ -10754,17 +10786,21 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} '@jridgewell/source-map@0.3.6': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} - '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': @@ -11027,29 +11063,26 @@ snapshots: optionalDependencies: '@types/react': 18.3.5 - '@nestjs/cli@10.3.2(@swc/core@1.6.6(@swc/helpers@0.5.5))': + '@nestjs/cli@10.4.9(@swc/core@1.6.6(@swc/helpers@0.5.5))': dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics-cli': 17.1.2(chokidar@3.6.0) - '@nestjs/schematics': 10.1.1(chokidar@3.6.0)(typescript@5.3.3) + '@angular-devkit/core': 17.3.11(chokidar@3.6.0) + '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0) + '@angular-devkit/schematics-cli': 17.3.11(chokidar@3.6.0) + '@nestjs/schematics': 10.2.3(chokidar@3.6.0)(typescript@5.7.2) chalk: 4.1.2 chokidar: 3.6.0 - cli-table3: 0.6.3 + cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) - glob: 10.3.10 + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) + glob: 10.4.5 inquirer: 8.2.6 node-emoji: 1.11.0 ora: 5.4.1 - rimraf: 4.4.1 - shelljs: 0.8.5 - source-map-support: 0.5.21 tree-kill: 1.2.2 tsconfig-paths: 4.2.0 - tsconfig-paths-webpack-plugin: 4.1.0 - typescript: 5.3.3 - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) + tsconfig-paths-webpack-plugin: 4.2.0 + typescript: 5.7.2 + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) webpack-node-externals: 3.0.0 optionalDependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) @@ -11058,101 +11091,71 @@ snapshots: - uglify-js - webpack-cli - '@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1)': + '@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1)': dependencies: iterare: 1.2.1 reflect-metadata: 0.2.2 rxjs: 7.8.1 - tslib: 2.6.2 + tslib: 2.8.1 uid: 2.0.2 - '@nestjs/core@10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.9)(reflect-metadata@0.2.2)(rxjs@7.8.1)': + '@nestjs/core@10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1)': dependencies: - '@nestjs/common': 10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 iterare: 1.2.1 - path-to-regexp: 3.2.0 + path-to-regexp: 3.3.0 reflect-metadata: 0.2.2 rxjs: 7.8.1 - tslib: 2.6.2 + tslib: 2.8.1 uid: 2.0.2 optionalDependencies: - '@nestjs/platform-express': 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9) + '@nestjs/platform-express': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15) transitivePeerDependencies: - encoding - '@nestjs/platform-express@10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9)': + '@nestjs/platform-express@10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15)': dependencies: - '@nestjs/common': 10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.9)(reflect-metadata@0.2.2)(rxjs@7.8.1) - body-parser: 1.20.2 + '@nestjs/common': 10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1) + body-parser: 1.20.3 cors: 2.8.5 - express: 4.19.2 + express: 4.21.2 multer: 1.4.4-lts.1 - tslib: 2.6.2 + tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@nestjs/schematics@10.1.1(chokidar@3.6.0)(typescript@5.3.3)': + '@nestjs/schematics@10.2.3(chokidar@3.6.0)(typescript@5.6.3)': dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - comment-json: 4.2.3 - jsonc-parser: 3.2.1 + '@angular-devkit/core': 17.3.11(chokidar@3.6.0) + '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0) + comment-json: 4.2.5 + jsonc-parser: 3.3.1 pluralize: 8.0.0 - typescript: 5.3.3 + typescript: 5.6.3 transitivePeerDependencies: - chokidar - '@nestjs/schematics@10.1.1(chokidar@3.6.0)(typescript@5.5.2)': + '@nestjs/schematics@10.2.3(chokidar@3.6.0)(typescript@5.7.2)': dependencies: - '@angular-devkit/core': 17.1.2(chokidar@3.6.0) - '@angular-devkit/schematics': 17.1.2(chokidar@3.6.0) - comment-json: 4.2.3 - jsonc-parser: 3.2.1 + '@angular-devkit/core': 17.3.11(chokidar@3.6.0) + '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0) + comment-json: 4.2.5 + jsonc-parser: 3.3.1 pluralize: 8.0.0 - typescript: 5.5.2 + typescript: 5.7.2 transitivePeerDependencies: - chokidar - '@nestjs/testing@10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9)(@nestjs/platform-express@10.3.9)': + '@nestjs/testing@10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15)(@nestjs/platform-express@10.4.15)': dependencies: - '@nestjs/common': 10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.9)(reflect-metadata@0.2.2)(rxjs@7.8.1) - tslib: 2.6.2 + '@nestjs/common': 10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1) + tslib: 2.8.1 optionalDependencies: - '@nestjs/platform-express': 10.3.9(@nestjs/common@10.3.9(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.9) - - '@next/env@14.2.8': - optional: true - - '@next/swc-darwin-arm64@14.2.8': - optional: true - - '@next/swc-darwin-x64@14.2.8': - optional: true - - '@next/swc-linux-arm64-gnu@14.2.8': - optional: true - - '@next/swc-linux-arm64-musl@14.2.8': - optional: true - - '@next/swc-linux-x64-gnu@14.2.8': - optional: true - - '@next/swc-linux-x64-musl@14.2.8': - optional: true - - '@next/swc-win32-arm64-msvc@14.2.8': - optional: true - - '@next/swc-win32-ia32-msvc@14.2.8': - optional: true - - '@next/swc-win32-x64-msvc@14.2.8': - optional: true + '@nestjs/platform-express': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15) '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: @@ -11424,12 +11427,12 @@ snapshots: '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.7) '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.7) - '@svgr/core@8.1.0(typescript@5.6.3)': + '@svgr/core@8.1.0(typescript@5.7.2)': dependencies: '@babel/core': 7.24.7 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.6.3) + cosmiconfig: 8.3.6(typescript@5.7.2) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -11440,11 +11443,11 @@ snapshots: '@babel/types': 7.24.7 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.6.3))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.7.2))': dependencies: '@babel/core': 7.24.7 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) - '@svgr/core': 8.1.0(typescript@5.6.3) + '@svgr/core': 8.1.0(typescript@5.7.2) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: @@ -11502,7 +11505,7 @@ snapshots: '@swc/helpers@0.5.5': dependencies: '@swc/counter': 0.1.3 - tslib: 2.6.3 + tslib: 2.8.1 optional: true '@swc/types@0.1.9': @@ -11556,7 +11559,7 @@ snapshots: prettier: 3.3.2 zod: 3.23.8 - '@tanstack/router-plugin@1.43.1(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1))': + '@tanstack/router-plugin@1.43.1(vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0))': dependencies: '@babel/core': 7.24.7 '@babel/generator': 7.24.7 @@ -11575,7 +11578,7 @@ snapshots: unplugin: 1.10.2 zod: 3.23.8 optionalDependencies: - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1) + vite: 5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0) transitivePeerDependencies: - supports-color @@ -11789,20 +11792,20 @@ snapshots: '@types/better-sqlite3@7.6.10': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/connect@3.4.38': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/cookie@0.5.4': {} @@ -11838,10 +11841,10 @@ snapshots: '@types/eslint-scope@3.7.7': dependencies: - '@types/eslint': 8.56.10 + '@types/eslint': 9.6.1 '@types/estree': 1.0.6 - '@types/eslint@8.56.10': + '@types/eslint@9.6.1': dependencies: '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 @@ -11854,23 +11857,23 @@ snapshots: '@types/estree@1.0.6': {} - '@types/express-serve-static-core@4.19.5': + '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 20.14.9 - '@types/qs': 6.9.15 + '@types/node': 20.17.11 + '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.5 - '@types/qs': 6.9.15 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.17 '@types/serve-static': 1.15.7 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/hast@3.0.4': dependencies: @@ -11888,7 +11891,7 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 - '@types/jest@29.5.12': + '@types/jest@29.5.14': dependencies: expect: 29.7.0 pretty-format: 29.7.0 @@ -11917,6 +11920,15 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@20.17.11': + dependencies: + undici-types: 6.19.8 + + '@types/node@22.9.0': + dependencies: + undici-types: 6.19.8 + optional: true + '@types/parse-json@4.0.2': {} '@types/postcss-modules-local-by-default@4.0.2': @@ -11929,7 +11941,7 @@ snapshots: '@types/prop-types@15.7.12': {} - '@types/qs@6.9.15': {} + '@types/qs@6.9.17': {} '@types/range-parser@1.2.7': {} @@ -11939,7 +11951,7 @@ snapshots: '@types/react-transition-group@4.4.11': dependencies: - '@types/react': 18.3.3 + '@types/react': 18.3.5 '@types/react@18.3.3': dependencies: @@ -11956,26 +11968,27 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.14.9 + '@types/node': 20.17.11 '@types/send': 0.17.4 '@types/stack-utils@2.0.3': {} - '@types/superagent@8.1.7': + '@types/superagent@8.1.9': dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 20.14.9 + '@types/node': 20.17.11 + form-data: 4.0.1 '@types/supertest@6.0.2': dependencies: '@types/methods': 1.1.4 - '@types/superagent': 8.1.7 + '@types/superagent': 8.1.9 '@types/unist@2.0.10': {} @@ -11985,27 +11998,27 @@ snapshots: '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.32': + '@types/yargs@17.0.33': dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 + debug: 4.4.0 + eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.2) + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -12027,16 +12040,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.2) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.5 - eslint: 8.57.0 + debug: 4.4.0 + eslint: 8.57.1 optionalDependencies: - typescript: 5.5.2 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -12063,15 +12076,15 @@ snapshots: '@typescript-eslint/types': 8.11.0 '@typescript-eslint/visitor-keys': 8.11.0 - '@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) debug: 4.4.0 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + eslint: 8.57.1 + ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -12079,7 +12092,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3) '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@5.6.3) - debug: 4.3.6 + debug: 4.4.0 ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: typescript: 5.6.3 @@ -12091,7 +12104,7 @@ snapshots: '@typescript-eslint/types@8.11.0': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.2)': + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 @@ -12100,9 +12113,9 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.3 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -12110,7 +12123,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.11.0 '@typescript-eslint/visitor-keys': 8.11.0 - debug: 4.3.6 + debug: 4.4.0 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 @@ -12121,15 +12134,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.2) - eslint: 8.57.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) + eslint: 8.57.1 semver: 7.6.3 transitivePeerDependencies: - supports-color @@ -12156,19 +12169,11 @@ snapshots: '@typescript-eslint/types': 8.11.0 eslint-visitor-keys: 3.4.3 - '@uidotdev/usehooks@2.4.1(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)': - dependencies: - react: 19.0.0-rc-a7d1240c-20240731 - react-dom: 19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731) + '@uidotdev/usehooks@2.4.1': {} '@ungap/structured-clone@1.2.0': {} - '@vercel/analytics@1.3.1(next@14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6))(react@19.0.0-rc-a7d1240c-20240731)': - dependencies: - server-only: 0.0.1 - optionalDependencies: - next: 14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6) - react: 19.0.0-rc-a7d1240c-20240731 + '@vercel/analytics@1.4.1': {} '@vercel/nft@0.27.2': dependencies: @@ -12188,26 +12193,23 @@ snapshots: - encoding - supports-color - '@vercel/speed-insights@1.0.12(next@14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6))(react@19.0.0-rc-a7d1240c-20240731)': - optionalDependencies: - next: 14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6) - react: 19.0.0-rc-a7d1240c-20240731 + '@vercel/speed-insights@1.1.0': {} - '@vitejs/plugin-react-swc@3.7.0(@swc/helpers@0.5.5)(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1))': + '@vitejs/plugin-react-swc@3.7.0(@swc/helpers@0.5.5)(vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0))': dependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) - vite: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1) + vite: 6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.3.1(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1))': + '@vitejs/plugin-react@4.3.1(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0))': dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.7) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + vite: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) transitivePeerDependencies: - supports-color @@ -12218,13 +12220,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1))': + '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0))': dependencies: '@vitest/spy': 2.1.3 estree-walker: 3.0.3 magic-string: 0.30.12 optionalDependencies: - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + vite: 5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) '@vitest/pretty-format@2.1.3': dependencies: @@ -12258,7 +12260,7 @@ snapshots: sirv: 2.0.4 tinyglobby: 0.2.10 tinyrainbow: 1.2.0 - vitest: 2.1.3(@types/node@20.14.9)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + vitest: 2.1.3(@types/node@22.9.0)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) '@vitest/utils@2.1.3': dependencies: @@ -12266,80 +12268,80 @@ snapshots: loupe: 3.1.2 tinyrainbow: 1.2.0 - '@webassemblyjs/ast@1.12.1': + '@webassemblyjs/ast@1.14.1': dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/floating-point-hex-parser@1.11.6': {} + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - '@webassemblyjs/helper-api-error@1.11.6': {} + '@webassemblyjs/helper-api-error@1.13.2': {} - '@webassemblyjs/helper-buffer@1.12.1': {} + '@webassemblyjs/helper-buffer@1.14.1': {} - '@webassemblyjs/helper-numbers@1.11.6': + '@webassemblyjs/helper-numbers@1.13.2': dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 '@xtuc/long': 4.2.2 - '@webassemblyjs/helper-wasm-bytecode@1.11.6': {} + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} - '@webassemblyjs/helper-wasm-section@1.12.1': + '@webassemblyjs/helper-wasm-section@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/ieee754@1.11.6': + '@webassemblyjs/ieee754@1.13.2': dependencies: '@xtuc/ieee754': 1.2.0 - '@webassemblyjs/leb128@1.11.6': + '@webassemblyjs/leb128@1.13.2': dependencies: '@xtuc/long': 4.2.2 - '@webassemblyjs/utf8@1.11.6': {} + '@webassemblyjs/utf8@1.13.2': {} - '@webassemblyjs/wasm-edit@1.12.1': + '@webassemblyjs/wasm-edit@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 - '@webassemblyjs/wasm-gen@1.12.1': + '@webassemblyjs/wasm-gen@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@webassemblyjs/wasm-opt@1.12.1': + '@webassemblyjs/wasm-opt@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wasm-parser@1.12.1': + '@webassemblyjs/wasm-parser@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@webassemblyjs/wast-printer@1.12.1': + '@webassemblyjs/wast-printer@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 '@xtuc/ieee754@1.2.0': {} @@ -12370,10 +12372,6 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-import-assertions@1.9.0(acorn@8.12.0): - dependencies: - acorn: 8.12.0 - acorn-import-attributes@1.9.5(acorn@8.12.0): dependencies: acorn: 8.12.0 @@ -12382,16 +12380,22 @@ snapshots: dependencies: acorn: 8.12.0 + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + acorn-loose@8.4.0: dependencies: acorn: 8.12.0 - acorn-walk@8.3.3: + acorn-walk@8.3.4: dependencies: - acorn: 8.12.0 + acorn: 8.14.0 acorn@8.12.0: {} + acorn@8.14.0: {} + agent-base@6.0.2: dependencies: debug: 4.4.0 @@ -12402,10 +12406,19 @@ snapshots: optionalDependencies: ajv: 8.12.0 + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + 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.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -12420,6 +12433,13 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + algoliasearch@4.24.0: dependencies: '@algolia/cache-browser-local-storage': 4.24.0 @@ -12508,7 +12528,7 @@ snapshots: aria-hidden@1.2.4: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 aria-query@5.3.2: {} @@ -12586,6 +12606,8 @@ snapshots: async-sema@3.1.1: {} + async@3.2.6: {} + asynckit@0.4.0: {} atomic-sleep@1.0.0: {} @@ -12593,13 +12615,23 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.39): dependencies: browserslist: 4.23.1 - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 postcss: 8.4.39 postcss-value-parser: 4.2.0 + autoprefixer@10.4.19(postcss@8.4.45): + dependencies: + browserslist: 4.23.1 + caniuse-lite: 1.0.30001690 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.1 + postcss: 8.4.45 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -12642,8 +12674,8 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 + '@babel/template': 7.25.9 + '@babel/types': 7.25.9 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 @@ -12653,12 +12685,14 @@ snapshots: cosmiconfig: 7.1.0 resolve: 1.22.8 - babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.7): + babel-preset-current-node-syntax@1.1.0(@babel/core@7.24.7): dependencies: '@babel/core': 7.24.7 '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.7) '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.7) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.24.7) '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7) '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) @@ -12667,13 +12701,14 @@ snapshots: '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.7) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.7) babel-preset-jest@29.6.3(@babel/core@7.24.7): dependencies: '@babel/core': 7.24.7 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.7) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.24.7) bail@2.0.2: {} @@ -12719,6 +12754,23 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + bplist-parser@0.2.0: dependencies: big-integer: 1.6.52 @@ -12738,11 +12790,18 @@ snapshots: browserslist@4.23.1: dependencies: - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 electron-to-chromium: 1.4.815 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) + browserslist@4.24.3: + dependencies: + caniuse-lite: 1.0.30001690 + electron-to-chromium: 1.5.76 + node-releases: 2.0.19 + update-browserslist-db: 1.1.1(browserslist@4.24.3) + bs-logger@0.2.6: dependencies: fast-json-stable-stringify: 2.1.0 @@ -12793,7 +12852,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001638: {} + caniuse-lite@1.0.30001690: {} ccount@2.0.1: {} @@ -12852,7 +12911,7 @@ snapshots: ci-info@3.9.0: {} - cjs-module-lexer@1.3.1: {} + cjs-module-lexer@1.4.1: {} cli-cursor@3.1.0: dependencies: @@ -12870,7 +12929,7 @@ snapshots: cli-spinners@3.0.0: {} - cli-table3@0.6.3: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -12885,9 +12944,6 @@ snapshots: cli-width@4.1.0: {} - client-only@0.0.1: - optional: true - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -12934,7 +12990,7 @@ snapshots: commander@4.1.1: {} - comment-json@4.2.3: + comment-json@4.2.5: dependencies: array-timsort: 1.0.3 core-util-is: 1.0.3 @@ -13009,6 +13065,10 @@ snapshots: cookie@0.6.0: {} + cookie@0.7.1: {} + + cookie@0.7.2: {} + cookiejar@2.1.4: {} copy-anything@2.0.6: @@ -13041,23 +13101,14 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.3.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.3.3 - - cosmiconfig@8.3.6(typescript@5.6.3): + cosmiconfig@8.3.6(typescript@5.7.2): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.6.3 + typescript: 5.7.2 cosmiconfig@9.0.0(typescript@5.6.3): dependencies: @@ -13068,13 +13119,13 @@ snapshots: optionalDependencies: typescript: 5.6.3 - create-jest@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)): + create-jest@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.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.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + jest-config: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -13179,10 +13230,6 @@ snapshots: dependencies: ms: 2.0.0 - debug@4.3.5: - dependencies: - ms: 2.1.2 - debug@4.3.6: dependencies: ms: 2.1.2 @@ -13304,7 +13351,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 dot-prop@5.3.0: dependencies: @@ -13316,8 +13363,14 @@ snapshots: ee-first@1.1.1: {} + ejs@3.1.10: + dependencies: + jake: 10.9.2 + electron-to-chromium@1.4.815: {} + electron-to-chromium@1.5.76: {} + embla-carousel-react@8.2.1: dependencies: embla-carousel: 8.2.1 @@ -13339,11 +13392,13 @@ snapshots: encodeurl@1.0.2: {} + encodeurl@2.0.0: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 - enhanced-resolve@5.17.0: + enhanced-resolve@5.18.0: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 @@ -13435,7 +13490,7 @@ snapshots: iterator.prototype: 1.1.3 safe-array-concat: 1.1.2 - es-module-lexer@1.5.4: {} + es-module-lexer@1.6.0: {} es-object-atoms@1.0.0: dependencies: @@ -13511,6 +13566,8 @@ snapshots: escalade@3.1.2: {} + escalade@3.2.0: {} + escape-html@1.0.3: {} escape-string-regexp@1.0.5: {} @@ -13529,9 +13586,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@9.1.0(eslint@8.57.0): + eslint-config-prettier@9.1.0(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@1.21.6)): dependencies: @@ -13557,24 +13614,24 @@ snapshots: safe-regex-test: 1.0.3 string.prototype.includes: 2.0.1 - eslint-plugin-prettier@5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2): + eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.2): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 prettier: 3.3.2 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.2 optionalDependencies: - '@types/eslint': 8.56.10 - eslint-config-prettier: 9.1.0(eslint@8.57.0) + '@types/eslint': 9.6.1 + eslint-config-prettier: 9.1.0(eslint@8.57.1) - eslint-plugin-prettier@5.2.1(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(prettier@3.3.2): + eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(prettier@3.3.2): dependencies: eslint: 9.13.0(jiti@1.21.6) prettier: 3.3.2 prettier-linter-helpers: 1.0.0 synckit: 0.9.2 optionalDependencies: - '@types/eslint': 8.56.10 + '@types/eslint': 9.6.1 eslint-config-prettier: 9.1.0(eslint@9.13.0(jiti@1.21.6)) eslint-plugin-react@7.37.2(eslint@9.13.0(jiti@1.21.6)): @@ -13624,20 +13681,20 @@ snapshots: eslint-visitor-keys@4.1.0: {} - eslint@8.57.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@eslint-community/regexpp': 4.11.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5 + debug: 4.4.0 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -13717,8 +13774,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.12.0 - acorn-jsx: 5.3.2(acorn@8.12.0) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -13865,6 +13922,42 @@ snapshots: transitivePeerDependencies: - supports-color + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend@3.0.2: {} external-editor@3.1.0: @@ -13895,6 +13988,8 @@ snapshots: fast-safe-stringify@2.1.1: {} + fast-uri@3.0.4: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -13917,11 +14012,6 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - figures@5.0.0: - dependencies: - escape-string-regexp: 5.0.0 - is-unicode-supported: 1.3.0 - file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -13932,6 +14022,10 @@ snapshots: file-uri-to-path@1.0.0: {} + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + filesize@10.1.2: {} fill-range@7.1.1: @@ -13952,6 +14046,18 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + find-root@1.1.0: {} find-up@4.1.0: @@ -13985,7 +14091,7 @@ snapshots: focus-lock@1.3.5: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 for-each@0.3.3: dependencies: @@ -13996,12 +14102,12 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): + fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.25.9 chalk: 4.1.2 chokidar: 3.6.0 - cosmiconfig: 8.3.6(typescript@5.3.3) + cosmiconfig: 8.3.6(typescript@5.7.2) deepmerge: 4.3.1 fs-extra: 10.1.0 memfs: 3.5.3 @@ -14010,10 +14116,10 @@ snapshots: schema-utils: 3.3.0 semver: 7.6.3 tapable: 2.2.1 - typescript: 5.3.3 - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) + typescript: 5.7.2 + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) - form-data@4.0.0: + form-data@4.0.1: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -14021,10 +14127,10 @@ snapshots: format@0.2.2: {} - formidable@3.5.1: + formidable@3.5.2: dependencies: dezalgo: 1.0.4 - hexoid: 1.0.0 + hexoid: 2.0.0 once: 1.4.0 forwarded@0.2.0: {} @@ -14133,15 +14239,16 @@ snapshots: glob-to-regexp@0.4.1: {} - glob@10.3.10: + glob@10.4.2: dependencies: foreground-child: 3.2.1 - jackspeak: 2.3.6 + jackspeak: 3.4.0 minimatch: 9.0.5 minipass: 7.1.2 + package-json-from-dist: 1.0.0 path-scurry: 1.11.1 - glob@10.4.2: + glob@10.4.5: dependencies: foreground-child: 3.2.1 jackspeak: 3.4.0 @@ -14159,13 +14266,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - glob@9.3.5: - dependencies: - fs.realpath: 1.0.0 - minimatch: 8.0.4 - minipass: 4.2.8 - path-scurry: 1.11.1 - global-directory@4.0.1: dependencies: ini: 4.1.1 @@ -14301,7 +14401,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hexoid@1.0.0: {} + hexoid@2.0.0: {} highlight.js@11.9.0: {} @@ -14363,7 +14463,7 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-local@3.1.0: + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 @@ -14405,7 +14505,7 @@ snapshots: through: 2.3.8 wrap-ansi: 6.2.0 - inquirer@9.2.12: + inquirer@9.2.15: dependencies: '@ljharb/through': 2.3.13 ansi-escapes: 4.3.2 @@ -14413,7 +14513,7 @@ snapshots: cli-cursor: 3.1.0 cli-width: 4.1.0 external-editor: 3.1.0 - figures: 5.0.0 + figures: 3.2.0 lodash: 4.17.21 mute-stream: 1.0.0 ora: 5.4.1 @@ -14431,14 +14531,20 @@ snapshots: internmap@2.0.3: {} - interpret@1.4.0: {} - invariant@2.2.4: dependencies: loose-envify: 1.4.0 ipaddr.js@1.9.1: {} + iron-session@8.0.4: + dependencies: + cookie: 0.7.2 + iron-webcrypto: 1.2.1 + uncrypto: 0.1.3 + + iron-webcrypto@1.2.1: {} + is-alphabetical@2.0.1: {} is-alphanumerical@2.0.1: @@ -14575,8 +14681,6 @@ snapshots: is-unicode-supported@0.1.0: {} - is-unicode-supported@1.3.0: {} - is-weakmap@2.0.2: {} is-weakref@1.0.2: @@ -14607,17 +14711,17 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.24.7 - '@babel/parser': 7.24.7 + '@babel/parser': 7.25.9 '@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.7 - '@babel/parser': 7.24.7 + '@babel/parser': 7.25.9 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.3 @@ -14653,17 +14757,18 @@ snapshots: reflect.getprototypeof: 1.0.6 set-function-name: 2.0.2 - jackspeak@2.3.6: + jackspeak@3.4.0: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jackspeak@3.4.0: + jake@10.9.2: dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 jest-changed-files@29.7.0: dependencies: @@ -14677,7 +14782,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3(babel-plugin-macros@3.1.0) @@ -14697,16 +14802,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)): + jest-cli@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.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.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + create-jest: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -14716,7 +14821,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)): + jest-config@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)): dependencies: '@babel/core': 7.24.7 '@jest/test-sequencer': 29.7.0 @@ -14741,8 +14846,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.9 - ts-node: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2) + '@types/node': 20.17.11 + ts-node: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -14771,7 +14876,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -14781,7 +14886,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.9 + '@types/node': 20.17.11 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -14807,7 +14912,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.25.9 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -14820,7 +14925,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -14845,7 +14950,7 @@ snapshots: jest-util: 29.7.0 jest-validate: 29.7.0 resolve: 1.22.8 - resolve.exports: 2.0.2 + resolve.exports: 2.0.3 slash: 3.0.0 jest-runner@29.7.0: @@ -14855,7 +14960,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -14883,9 +14988,9 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 chalk: 4.1.2 - cjs-module-lexer: 1.3.1 + cjs-module-lexer: 1.4.1 collect-v8-coverage: 1.0.2 glob: 7.2.3 graceful-fs: 4.2.11 @@ -14904,14 +15009,14 @@ snapshots: jest-snapshot@29.7.0: dependencies: '@babel/core': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) + '@babel/generator': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.24.7) '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.7) - '@babel/types': 7.24.7 + '@babel/types': 7.25.9 '@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.7) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.24.7) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -14929,7 +15034,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -14948,7 +15053,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.17.11 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -14957,23 +15062,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.9 + '@types/node': 20.17.11 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)): + jest@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -15013,10 +15118,10 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.0: {} - jsonc-parser@3.2.1: {} + jsonc-parser@3.3.1: {} + jsonfile@6.1.0: dependencies: universalify: 2.0.1 @@ -15050,7 +15155,7 @@ snapshots: dependencies: copy-anything: 2.0.6 parse-node-version: 1.0.1 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: errno: 0.1.8 graceful-fs: 4.2.11 @@ -15177,7 +15282,7 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 lowlight@3.1.0: dependencies: @@ -15191,19 +15296,17 @@ snapshots: dependencies: yallist: 3.1.1 - lucide-react@0.408.0(react@19.0.0-rc-a7d1240c-20240731): - dependencies: - react: 19.0.0-rc-a7d1240c-20240731 + lucide-react@0.408.0: {} magic-string@0.30.10: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 magic-string@0.30.12: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.5: + magic-string@0.30.8: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -15433,6 +15536,8 @@ snapshots: merge-descriptors@1.0.1: {} + merge-descriptors@1.0.3: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -15739,7 +15844,7 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@8.0.4: + minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 @@ -15757,8 +15862,6 @@ snapshots: dependencies: yallist: 4.0.0 - minipass@4.2.8: {} - minipass@5.0.0: {} minipass@7.1.2: {} @@ -15831,39 +15934,12 @@ snapshots: neo-async@2.6.2: {} - next@14.2.8(@babel/core@7.24.7)(react-dom@19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731))(react@19.0.0-rc-a7d1240c-20240731)(sass@1.77.6): - dependencies: - '@next/env': 14.2.8 - '@swc/helpers': 0.5.5 - busboy: 1.6.0 - caniuse-lite: 1.0.30001638 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 19.0.0-rc-a7d1240c-20240731 - react-dom: 19.0.0-rc-3208e73e-20240730(react@19.0.0-rc-a7d1240c-20240731) - styled-jsx: 5.1.1(@babel/core@7.24.7)(react@19.0.0-rc-a7d1240c-20240731) - optionalDependencies: - '@next/swc-darwin-arm64': 14.2.8 - '@next/swc-darwin-x64': 14.2.8 - '@next/swc-linux-arm64-gnu': 14.2.8 - '@next/swc-linux-arm64-musl': 14.2.8 - '@next/swc-linux-x64-gnu': 14.2.8 - '@next/swc-linux-x64-musl': 14.2.8 - '@next/swc-win32-arm64-msvc': 14.2.8 - '@next/swc-win32-ia32-msvc': 14.2.8 - '@next/swc-win32-x64-msvc': 14.2.8 - sass: 1.77.6 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - optional: true - nice-try@1.0.5: {} no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.3 + tslib: 2.8.1 node-abi@3.65.0: dependencies: @@ -15887,6 +15963,8 @@ snapshots: node-releases@2.0.14: {} + node-releases@2.0.19: {} + nopt@5.0.0: dependencies: abbrev: 1.1.1 @@ -16113,9 +16191,11 @@ snapshots: lru-cache: 10.3.0 minipass: 7.1.2 + path-to-regexp@0.1.12: {} + path-to-regexp@0.1.7: {} - path-to-regexp@3.2.0: {} + path-to-regexp@3.3.0: {} path-type@3.0.0: dependencies: @@ -16135,9 +16215,11 @@ snapshots: picocolors@1.0.1: {} + picocolors@1.1.1: {} + picomatch@2.3.1: {} - picomatch@3.0.1: {} + picomatch@4.0.1: {} picomatch@4.0.2: {} @@ -16231,13 +16313,13 @@ snapshots: postcss: 8.4.45 ts-node: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3) - postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)): + postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)): dependencies: lilconfig: 3.1.2 yaml: 2.4.5 optionalDependencies: postcss: 8.4.39 - ts-node: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3) + ts-node: 10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2) postcss-mixins@9.0.4(postcss@8.4.45): dependencies: @@ -16290,13 +16372,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.31: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - optional: true - postcss@8.4.39: dependencies: nanoid: 3.3.7 @@ -16482,7 +16557,7 @@ snapshots: dependencies: side-channel: 1.0.6 - qs@6.12.1: + qs@6.13.0: dependencies: side-channel: 1.0.6 @@ -16583,7 +16658,7 @@ snapshots: dependencies: react: 19.0.0-rc-a7d1240c-20240731 react-style-singleton: 2.2.1(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731) - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.5 @@ -16592,7 +16667,7 @@ snapshots: react: 19.0.0-rc-a7d1240c-20240731 react-remove-scroll-bar: 2.3.6(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731) react-style-singleton: 2.2.1(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731) - tslib: 2.6.3 + tslib: 2.8.1 use-callback-ref: 1.3.2(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731) use-sidecar: 1.1.2(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731) optionalDependencies: @@ -16610,13 +16685,13 @@ snapshots: '@remix-run/router': 1.17.0 react: 19.0.0-rc-a7d1240c-20240731 - react-server-dom-webpack@0.0.0-experimental-204a551e-20240926(react-dom@0.0.0-experimental-204a551e-20240926(react@0.0.0-experimental-204a551e-20240926))(react@0.0.0-experimental-204a551e-20240926)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)): + react-server-dom-webpack@0.0.0-experimental-204a551e-20240926(react-dom@0.0.0-experimental-204a551e-20240926(react@0.0.0-experimental-204a551e-20240926))(react@0.0.0-experimental-204a551e-20240926)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)): dependencies: acorn-loose: 8.4.0 neo-async: 2.6.2 react: 0.0.0-experimental-204a551e-20240926 react-dom: 0.0.0-experimental-204a551e-20240926(react@0.0.0-experimental-204a551e-20240926) - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12) + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12) webpack-sources: 3.2.3 react-smooth@4.0.1(react-dom@19.0.0-rc-3208e73e-20240730): @@ -16631,7 +16706,7 @@ snapshots: get-nonce: 1.0.1 invariant: 2.2.4 react: 19.0.0-rc-a7d1240c-20240731 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.5 @@ -16717,10 +16792,6 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 - rechoir@0.6.2: - dependencies: - resolve: 1.22.8 - reflect-metadata@0.2.2: {} reflect.getprototypeof@1.0.6: @@ -16839,7 +16910,7 @@ snapshots: resolve-from@5.0.0: {} - resolve.exports@2.0.2: {} + resolve.exports@2.0.3: {} resolve@1.22.8: dependencies: @@ -16871,10 +16942,6 @@ snapshots: dependencies: glob: 7.2.3 - rimraf@4.4.1: - dependencies: - glob: 9.3.5 - rollup@4.13.0: dependencies: '@types/estree': 1.0.5 @@ -16932,7 +16999,7 @@ snapshots: rxjs@7.8.1: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 safe-array-concat@1.1.2: dependencies: @@ -16976,14 +17043,19 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) + schema-utils@4.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + search-insights@2.14.0: {} semver@5.7.2: {} semver@6.3.1: {} - semver@7.6.2: {} - semver@7.6.3: {} send@0.18.0: @@ -17004,6 +17076,24 @@ snapshots: transitivePeerDependencies: - supports-color + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -17017,7 +17107,14 @@ snapshots: transitivePeerDependencies: - supports-color - server-only@0.0.1: {} + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color set-blocking@2.0.0: {} @@ -17053,12 +17150,6 @@ snapshots: shell-quote@1.8.1: {} - shelljs@0.8.5: - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - side-channel@1.0.6: dependencies: call-bind: 1.0.7 @@ -17105,7 +17196,7 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 sonic-boom@3.8.1: dependencies: @@ -17291,20 +17382,12 @@ snapshots: dependencies: inline-style-parser: 0.2.3 - styled-jsx@5.1.1(@babel/core@7.24.7)(react@19.0.0-rc-a7d1240c-20240731): - dependencies: - client-only: 0.0.1 - react: 19.0.0-rc-a7d1240c-20240731 - optionalDependencies: - '@babel/core': 7.24.7 - optional: true - stylis@4.2.0: {} stylus@0.62.0: dependencies: '@adobe/css-tools': 4.3.3 - debug: 4.3.6 + debug: 4.4.0 glob: 7.2.3 sax: 1.3.0 source-map: 0.7.4 @@ -17336,11 +17419,11 @@ snapshots: cookiejar: 2.1.4 debug: 4.4.0 fast-safe-stringify: 2.1.1 - form-data: 4.0.0 - formidable: 3.5.1 + form-data: 4.0.1 + formidable: 3.5.2 methods: 1.1.2 mime: 2.6.0 - qs: 6.12.1 + qs: 6.11.0 transitivePeerDependencies: - supports-color @@ -17369,19 +17452,16 @@ snapshots: symbol-observable@4.0.0: {} - synckit@0.8.8: - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.3 - synckit@0.9.2: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.3 + tslib: 2.8.1 tabbable@6.2.0: {} - tailwindcss@3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)): + tailwind-merge@2.6.0: {} + + tailwindcss@3.4.4(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -17400,7 +17480,7 @@ snapshots: postcss: 8.4.39 postcss-import: 15.1.0(postcss@8.4.39) postcss-js: 4.0.1(postcss@8.4.39) - postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3)) + postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2)) postcss-nested: 6.0.1(postcss@8.4.39) postcss-selector-parser: 6.1.0 resolve: 1.22.8 @@ -17434,33 +17514,33 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - terser-webpack-plugin@5.3.10(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)): + terser-webpack-plugin@5.3.11(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 - schema-utils: 3.3.0 + schema-utils: 4.3.0 serialize-javascript: 6.0.2 - terser: 5.31.1 - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12) + terser: 5.37.0 + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12) optionalDependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) esbuild: 0.19.12 - terser-webpack-plugin@5.3.10(@swc/core@1.6.6(@swc/helpers@0.5.5))(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): + terser-webpack-plugin@5.3.11(@swc/core@1.6.6(@swc/helpers@0.5.5))(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 - schema-utils: 3.3.0 + schema-utils: 4.3.0 serialize-javascript: 6.0.2 - terser: 5.31.1 - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) + terser: 5.37.0 + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) optionalDependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) - terser@5.31.1: + terser@5.37.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.12.0 + acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -17541,27 +17621,24 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.3.0(typescript@5.5.2): - dependencies: - typescript: 5.5.2 - ts-api-utils@1.3.0(typescript@5.6.3): dependencies: typescript: 5.6.3 ts-interface-checker@0.1.13: {} - ts-jest@29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)))(typescript@5.5.2): + ts-jest@29.2.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)))(typescript@5.6.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.14.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2)) + jest: 29.7.0(@types/node@20.17.11)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.6.2 - typescript: 5.5.2 + semver: 7.6.3 + typescript: 5.6.3 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.24.7 @@ -17569,17 +17646,17 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-loader@9.5.1(typescript@5.5.2)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): + ts-loader@9.5.1(typescript@5.6.3)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))): dependencies: chalk: 4.1.2 - enhanced-resolve: 5.17.0 + enhanced-resolve: 5.18.0 micromatch: 4.0.7 - semver: 7.6.2 + semver: 7.6.3 source-map: 0.7.4 - typescript: 5.5.2 - webpack: 5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) + typescript: 5.6.3 + webpack: 5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5)) - ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.5.2): + ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -17587,28 +17664,29 @@ snapshots: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.14.9 - acorn: 8.12.0 - acorn-walk: 8.3.3 + acorn: 8.14.0 + acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.5.2 + typescript: 5.6.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) + optional: true - ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.14.9)(typescript@5.6.3): + ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@20.17.11)(typescript@5.6.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.14.9 - acorn: 8.12.0 - acorn-walk: 8.3.3 + '@types/node': 20.17.11 + acorn: 8.14.0 + acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 @@ -17618,12 +17696,33 @@ snapshots: yn: 3.1.1 optionalDependencies: '@swc/core': 1.6.6(@swc/helpers@0.5.5) + + ts-node@10.9.2(@swc/core@1.6.6(@swc/helpers@0.5.5))(@types/node@22.9.0)(typescript@5.7.2): + 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.9.0 + acorn: 8.14.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.7.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.6.6(@swc/helpers@0.5.5) optional: true - tsconfig-paths-webpack-plugin@4.1.0: + tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 - enhanced-resolve: 5.17.0 + enhanced-resolve: 5.18.0 + tapable: 2.2.1 tsconfig-paths: 4.2.0 tsconfig-paths@4.2.0: @@ -17634,10 +17733,10 @@ snapshots: tslib@2.4.0: {} - tslib@2.6.2: {} - tslib@2.6.3: {} + tslib@2.8.1: {} + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 @@ -17716,12 +17815,12 @@ snapshots: - supports-color - ts-node - typescript@5.3.3: {} - typescript@5.5.2: {} typescript@5.6.3: {} + typescript@5.7.2: {} + uc.micro@2.1.0: {} ufo@1.5.3: {} @@ -17737,8 +17836,12 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + uncrypto@0.1.3: {} + undici-types@5.26.5: {} + undici-types@6.19.8: {} + undici@6.19.8: {} unicorn-magic@0.1.0: {} @@ -17811,6 +17914,12 @@ snapshots: escalade: 3.1.2 picocolors: 1.0.1 + update-browserslist-db@1.1.1(browserslist@4.24.3): + dependencies: + browserslist: 4.24.3 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -17820,7 +17929,7 @@ snapshots: use-callback-ref@1.3.2(@types/react@18.3.5)(react@19.0.0-rc-a7d1240c-20240731): dependencies: react: 19.0.0-rc-a7d1240c-20240731 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.5 @@ -17840,7 +17949,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 19.0.0-rc-a7d1240c-20240731 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.5 @@ -17897,12 +18006,12 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-node@2.1.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1): + vite-node@2.1.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0): dependencies: cac: 6.7.14 debug: 4.4.0 pathe: 1.1.2 - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + vite: 5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) transitivePeerDependencies: - '@types/node' - less @@ -17913,47 +18022,47 @@ snapshots: - supports-color - terser - vite-plugin-svgr@4.2.0(rollup@4.24.0)(typescript@5.6.3)(vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1)): + vite-plugin-svgr@4.2.0(rollup@4.24.0)(typescript@5.7.2)(vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0)): dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.24.0) - '@svgr/core': 8.1.0(typescript@5.6.3) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.6.3)) - vite: 6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1) + '@svgr/core': 8.1.0(typescript@5.7.2) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.2)) + vite: 6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1): + vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0): dependencies: esbuild: 0.21.3 postcss: 8.4.45 rollup: 4.24.0 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 22.9.0 fsevents: 2.3.3 less: 4.2.0 sass: 1.77.6 stylus: 0.62.0 sugarss: 4.0.1(postcss@8.4.39) - terser: 5.31.1 + terser: 5.37.0 optional: true - vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1): + vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0): dependencies: esbuild: 0.21.3 postcss: 8.4.45 rollup: 4.24.0 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 22.9.0 fsevents: 2.3.3 less: 4.2.0 sass: 1.77.6 stylus: 0.62.0 sugarss: 4.0.1(postcss@8.4.45) - terser: 5.31.1 + terser: 5.37.0 - vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.31.1): + vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0): dependencies: esbuild: 0.21.3 postcss: 8.4.45 @@ -17964,27 +18073,41 @@ snapshots: less: 4.2.0 sass: 1.77.6 stylus: 0.62.0 + sugarss: 4.0.1(postcss@8.4.45) + terser: 5.37.0 + + vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.39))(terser@5.37.0): + dependencies: + esbuild: 0.21.3 + postcss: 8.4.45 + rollup: 4.24.0 + optionalDependencies: + '@types/node': 22.9.0 + fsevents: 2.3.3 + less: 4.2.0 + sass: 1.77.6 + stylus: 0.62.0 sugarss: 4.0.1(postcss@8.4.39) - terser: 5.31.1 + terser: 5.37.0 - vite@6.0.0-alpha.18(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1): + vite@6.0.0-alpha.18(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0): dependencies: esbuild: 0.21.3 postcss: 8.4.45 rollup: 4.24.0 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 22.9.0 fsevents: 2.3.3 less: 4.2.0 sass: 1.77.6 stylus: 0.62.0 sugarss: 4.0.1(postcss@8.4.45) - terser: 5.31.1 + terser: 5.37.0 - vitest@2.1.3(@types/node@20.14.9)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1): + vitest@2.1.3(@types/node@22.9.0)(@vitest/ui@2.1.3)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0): dependencies: '@vitest/expect': 2.1.3 - '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1)) + '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0)) '@vitest/pretty-format': 2.1.8 '@vitest/runner': 2.1.3 '@vitest/snapshot': 2.1.3 @@ -17999,11 +18122,11 @@ snapshots: tinyexec: 0.3.1 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) - vite-node: 2.1.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.31.1) + vite: 5.3.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) + vite-node: 2.1.3(@types/node@22.9.0)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)(sugarss@4.0.1(postcss@8.4.45))(terser@5.37.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 22.9.0 '@vitest/ui': 2.1.3(vitest@2.1.3) transitivePeerDependencies: - less @@ -18021,7 +18144,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 @@ -18038,19 +18161,18 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5)): + webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.12.0 - acorn-import-assertions: 1.9.0(acorn@8.12.0) - browserslist: 4.23.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.14.0 + browserslist: 4.24.3 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.17.0 - es-module-lexer: 1.5.4 + enhanced-resolve: 5.18.0 + es-module-lexer: 1.6.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -18061,27 +18183,26 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.6.6(@swc/helpers@0.5.5))(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) - watchpack: 2.4.1 + terser-webpack-plugin: 5.3.11(@swc/core@1.6.6(@swc/helpers@0.5.5))(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))) + watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12): + webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.12.0 - acorn-import-assertions: 1.9.0(acorn@8.12.0) - browserslist: 4.23.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.14.0 + browserslist: 4.24.3 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.17.0 - es-module-lexer: 1.5.4 + enhanced-resolve: 5.18.0 + es-module-lexer: 1.6.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -18092,8 +18213,8 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)(webpack@5.90.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)) - watchpack: 2.4.1 + terser-webpack-plugin: 5.3.11(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)(webpack@5.97.1(@swc/core@1.6.6(@swc/helpers@0.5.5))(esbuild@0.19.12)) + watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' diff --git a/test/__test__/apps/mantine.spec.mjs b/test/__test__/apps/mantine.spec.mjs index 7095e83..fdd4bec 100644 --- a/test/__test__/apps/mantine.spec.mjs +++ b/test/__test__/apps/mantine.spec.mjs @@ -14,6 +14,9 @@ process.chdir(join(process.cwd(), "../examples/mantine")); test( "mantine and extensions", + { + timeout: 360000, + }, async () => { await server(null); let res = await page.goto(hostname, { timeout: 60000 }); @@ -186,8 +189,5 @@ test( expect(await page.textContent("body")).toContain( "Welcome to Mantine rich text editor" ); - }, - { - timeout: 360000, } ); diff --git a/test/__test__/apps/pokemon.spec.mjs b/test/__test__/apps/pokemon.spec.mjs new file mode 100644 index 0000000..199c667 --- /dev/null +++ b/test/__test__/apps/pokemon.spec.mjs @@ -0,0 +1,14 @@ +import { join } from "node:path"; + +import { hostname, page, server } from "playground/utils"; +import { expect, test } from "vitest"; + +process.env.POKEMON_LIMIT = "20"; +process.chdir(join(process.cwd(), "../examples/pokemon")); + +test("pokemon load", async () => { + await server(null); + await page.goto(hostname); + await page.waitForLoadState("networkidle"); + expect(await page.textContent("body")).toContain("Pokémon Catalog"); +}); diff --git a/test/__test__/apps/session-cookie.spec.mjs b/test/__test__/apps/session-cookie.spec.mjs new file mode 100644 index 0000000..dd245fc --- /dev/null +++ b/test/__test__/apps/session-cookie.spec.mjs @@ -0,0 +1,54 @@ +import { join } from "node:path"; + +import { hostname, page, server, waitForHydration } from "playground/utils"; +import { expect, test } from "vitest"; + +process.chdir(join(process.cwd(), "../examples/session-cookie")); + +test("session cookie", async () => { + await server("./App.jsx", { + resolve: { + external: ["iron-session"], + }, + }); + + await page.goto(hostname); + await page.waitForLoadState("networkidle"); + await waitForHydration(); + + let loginButton = page.getByRole("button", { name: "Login" }); + await loginButton.waitFor({ state: "visible" }); + expect(await loginButton.isVisible()).toBe(true); + await loginButton.click(); + + let logoutButton = page.getByRole("button", { name: "Logout" }); + await logoutButton.waitFor({ state: "visible" }); + expect(await logoutButton.isVisible()).toBe(true); + expect(await page.getByRole("button", { name: "New User" }).isVisible()).toBe( + false + ); + + await page.goto(hostname); + await page.waitForLoadState("networkidle"); + + logoutButton = page.getByRole("button", { name: "Logout" }); + await logoutButton.waitFor({ state: "visible" }); + expect(await logoutButton.isVisible()).toBe(true); + await logoutButton.click(); + + loginButton = page.getByRole("button", { name: "Login" }); + await loginButton.waitFor({ state: "visible" }); + expect(await loginButton.isVisible()).toBe(true); + + const newUserButton = page.getByRole("button", { name: "New User" }); + await newUserButton.waitFor({ state: "visible" }); + expect(await newUserButton.isVisible()).toBe(true); + + await newUserButton.click(); + await page.waitForLoadState("networkidle"); + expect(await page.textContent("body")).toContain("User code: 100000"); + + await newUserButton.click(); + await page.waitForLoadState("networkidle"); + expect(await page.textContent("body")).toContain("User code: 100001"); +}); diff --git a/test/__test__/error-boundary.spec.mjs b/test/__test__/error-boundary.spec.mjs index 92faadf..aeb7d5d 100644 --- a/test/__test__/error-boundary.spec.mjs +++ b/test/__test__/error-boundary.spec.mjs @@ -6,12 +6,8 @@ test("error boundary", async () => { await page.goto(hostname + "/error-boundary"); const message = await page.getByTestId("error-message"); expect(await message.textContent()).toContain("Uh oh, something went wrong!"); - const stack = await page.getByTestId("error-stack"); - if (process.env.NODE_ENV === "production") { - expect(await stack.textContent()).toContain( - "An error occurred in the Server Components render" - ); - } else { + if (process.env.NODE_ENV !== "production") { + const stack = await page.getByTestId("error-stack"); expect(await stack.textContent()).toContain("Error: test"); expect(await stack.textContent()).toContain("at ThrowError"); } @@ -21,12 +17,8 @@ test("throw error", async () => { await server("fixtures/error-boundary.jsx"); await page.goto(hostname + "/throw-error"); if (process.env.NODE_ENV === "production") { - expect(await page.textContent("body")).toContain( - "An error occurred in the Server Components render" - ); + expect(await page.textContent("body")).toContain("test"); } else { - expect(await page.evaluate(() => document.body.innerHTML)).toContain( - "vite-error-overlay" - ); + expect(await page.textContent("body")).toContain("at ThrowError"); } }); diff --git a/test/vitestGlobalSetup.mjs b/test/vitestGlobalSetup.mjs index 93b9781..a19ad68 100644 --- a/test/vitestGlobalSetup.mjs +++ b/test/vitestGlobalSetup.mjs @@ -17,12 +17,15 @@ export async function setup({ provide }) { export async function teardown() { await browserServer.close(); - const files = await readdir(process.cwd(), { withFileTypes: true }); - await Promise.all( - files - .filter( - (file) => file.isDirectory() && file.name.includes(".react-server") - ) - .map((file) => rm(join(process.cwd(), file.name), { recursive: true })) - ); + + if (!process.env.CI) { + const files = await readdir(process.cwd(), { withFileTypes: true }); + await Promise.all( + files + .filter( + (file) => file.isDirectory() && file.name.includes(".react-server") + ) + .map((file) => rm(join(process.cwd(), file.name), { recursive: true })) + ); + } } diff --git a/test/vitestSetup.mjs b/test/vitestSetup.mjs index b804547..9bf0cff 100644 --- a/test/vitestSetup.mjs +++ b/test/vitestSetup.mjs @@ -1,4 +1,5 @@ import { createHash } from "node:crypto"; +import { readdir, rm } from "node:fs/promises"; import { createServer } from "node:http"; import { dirname, join } from "node:path"; import { afterEach } from "node:test"; @@ -15,6 +16,8 @@ export let hostname; export let logs; export let serverLogs; +export const testCwd = process.cwd(); + console.log = (...args) => { logs.push(args.join(" ")); serverLogs.push(args.join(" ")); @@ -154,4 +157,15 @@ afterEach(async () => { afterAll(async () => { await page?.close(); await browser?.close(); + + if (!process.env.CI && testCwd !== process.cwd()) { + const files = await readdir(process.cwd(), { withFileTypes: true }); + await Promise.all( + files + .filter( + (file) => file.isDirectory() && file.name.includes(".react-server") + ) + .map((file) => rm(join(process.cwd(), file.name), { recursive: true })) + ); + } });