diff --git a/.changeset/warm-dots-obey.md b/.changeset/warm-dots-obey.md new file mode 100644 index 00000000..6e480ed1 --- /dev/null +++ b/.changeset/warm-dots-obey.md @@ -0,0 +1,8 @@ +--- +'@asgardeo/javascript': patch +'@asgardeo/browser': patch +'@asgardeo/nextjs': patch +'@asgardeo/react': patch +--- + +Expose `http` module instead of `fetch` diff --git a/packages/browser/src/__legacy__/client.ts b/packages/browser/src/__legacy__/client.ts index 0d24c47e..f4b0292e 100755 --- a/packages/browser/src/__legacy__/client.ts +++ b/packages/browser/src/__legacy__/client.ts @@ -813,7 +813,7 @@ export class AsgardeoSPAClient { * * @preserve */ - public async getAccessToken(): Promise { + public async getAccessToken(sessionId?: string): Promise { await this._validateMethod(); if (this._storage && [(BrowserStorage.WebWorker, BrowserStorage.BrowserMemory)].includes(this._storage)) { @@ -827,7 +827,7 @@ export class AsgardeoSPAClient { } const mainThreadClient = this._client as MainThreadClientInterface; - return mainThreadClient.getAccessToken(); + return mainThreadClient.getAccessToken(sessionId); } /** diff --git a/packages/browser/src/__legacy__/clients/main-thread-client.ts b/packages/browser/src/__legacy__/clients/main-thread-client.ts index 72573016..0bdb7222 100755 --- a/packages/browser/src/__legacy__/clients/main-thread-client.ts +++ b/packages/browser/src/__legacy__/clients/main-thread-client.ts @@ -380,7 +380,7 @@ export const MainThreadClient = async ( const getOpenIDProviderEndpoints = async (): Promise => _authenticationHelper.getOpenIDProviderEndpoints(); - const getAccessToken = async (): Promise => _authenticationHelper.getAccessToken(); + const getAccessToken = async (sessionId?: string): Promise => _authenticationHelper.getAccessToken(sessionId); const getStorageManager = async (): Promise> => _authenticationHelper.getStorageManager(); diff --git a/packages/browser/src/__legacy__/helpers/authentication-helper.ts b/packages/browser/src/__legacy__/helpers/authentication-helper.ts index 6a556bf5..dc75514a 100644 --- a/packages/browser/src/__legacy__/helpers/authentication-helper.ts +++ b/packages/browser/src/__legacy__/helpers/authentication-helper.ts @@ -679,8 +679,8 @@ export class AuthenticationHelper { - return this._authenticationClient.getAccessToken(); + public async getAccessToken(sessionId?: string): Promise { + return this._authenticationClient.getAccessToken(sessionId); } public async getIDPAccessToken(): Promise { diff --git a/packages/browser/src/__legacy__/models/client.ts b/packages/browser/src/__legacy__/models/client.ts index 023f5d1b..72c2b746 100755 --- a/packages/browser/src/__legacy__/models/client.ts +++ b/packages/browser/src/__legacy__/models/client.ts @@ -64,7 +64,7 @@ export interface MainThreadClientInterface { getConfigData(): Promise>; getIdToken(): Promise; getOpenIDProviderEndpoints(): Promise; - getAccessToken(): Promise; + getAccessToken(sessionId?: string): Promise; getStorageManager(): Promise>; isSignedIn(): Promise; reInitialize(config: Partial>): Promise; diff --git a/packages/javascript/src/AsgardeoJavaScriptClient.ts b/packages/javascript/src/AsgardeoJavaScriptClient.ts index 97d3db18..50d1013e 100644 --- a/packages/javascript/src/AsgardeoJavaScriptClient.ts +++ b/packages/javascript/src/AsgardeoJavaScriptClient.ts @@ -78,6 +78,8 @@ abstract class AsgardeoJavaScriptClient implements AsgardeoClient abstract signUp(options?: SignUpOptions): Promise; abstract signUp(payload: EmbeddedFlowExecuteRequestPayload): Promise; abstract signUp(payload?: unknown): Promise | Promise; + + abstract getAccessToken(sessionId?: string): Promise; } export default AsgardeoJavaScriptClient; diff --git a/packages/javascript/src/models/client.ts b/packages/javascript/src/models/client.ts index ee497f55..a6c28c06 100644 --- a/packages/javascript/src/models/client.ts +++ b/packages/javascript/src/models/client.ts @@ -187,4 +187,11 @@ export interface AsgardeoClient { * @returns A promise that resolves to an EmbeddedFlowExecuteResponse containing the flow execution details. */ signUp(payload: EmbeddedFlowExecuteRequestPayload): Promise; + + /** + * Retrieves the access token for the current session. + * @param sessionId - Optional session ID to retrieve the access token for a specific session. + * @returns A promise that resolves to the access token string. + */ + getAccessToken(sessionId?: string): Promise; } diff --git a/packages/nextjs/QUICKSTART.md b/packages/nextjs/QUICKSTART.md index 4ef1d3b4..7781965d 100644 --- a/packages/nextjs/QUICKSTART.md +++ b/packages/nextjs/QUICKSTART.md @@ -72,7 +72,7 @@ Create a `.env` file in your project root and add the following environment vari **.env** ```bash -NEXT_PUBLIC_ASGARDEO_BASE_URL="https://api.asgardeo.io/t/" +NEXT_PUBLIC_ASGARDEO_BASE_URL="https://api.asgardeo.io/t/" NEXT_PUBLIC_ASGARDEO_CLIENT_ID="" ASGARDEO_CLIENT_SECRET="" ``` diff --git a/packages/nextjs/README.md b/packages/nextjs/README.md index 7d24da4b..336a678a 100644 --- a/packages/nextjs/README.md +++ b/packages/nextjs/README.md @@ -28,7 +28,7 @@ yarn add @asgardeo/nextjs 1. Create a `.env.local` file with your Asgardeo configuration: ```bash -NEXT_PUBLIC_ASGARDEO_BASE_URL=https://api.asgardeo.io/t/ +NEXT_PUBLIC_ASGARDEO_BASE_URL=https://api.asgardeo.io/t/ NEXT_PUBLIC_ASGARDEO_CLIENT_ID= NEXT_PUBLIC_ASGARDEO_CLIENT_SECRET= ``` diff --git a/packages/react/docs/OVERVIEW.md b/packages/react/docs/OVERVIEW.md deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/react/docs/README.md b/packages/react/docs/README.md new file mode 100644 index 00000000..f149c2f9 --- /dev/null +++ b/packages/react/docs/README.md @@ -0,0 +1,19 @@ +# @asgardeo/react - Overview + +The Asgardeo React SDK provides a comprehensive set of hooks, components, and utilities to integrate Asgardeo authentication into your React applications. Built on top of the `@asgardeo/browser` SDK, it offers a React-specific wrapper with pre-built components and React hooks for seamless authentication experiences. + +## Features + +- πŸ” **Complete Authentication Flow**: Sign-in, sign-up, and sign-out functionality +- 🎨 **Pre-built Components**: Ready-to-use UI components for authentication +- πŸͺ **React Hooks**: Powerful hooks for authentication state management +- 🌐 **Multi-language Support**: Built-in internationalization (i18n) support +- 🎭 **Theming & Branding**: Customizable themes and branding options +- 🏒 **Organization Management**: Support for organization-based authentication +- πŸ“± **Social Login**: Built-in support for popular social providers +- πŸ”’ **Type Safe**: Full TypeScript support for better developer experience +- ⚑ **Performance Optimized**: Efficient re-rendering and state management + +## What's Next + +- [Quickstart Guide](./getting-started/overview.md): Get started with a simple integration. diff --git a/packages/react/docs/components/OVERVIEW.md b/packages/react/docs/components/OVERVIEW.md new file mode 100644 index 00000000..bf7887d9 --- /dev/null +++ b/packages/react/docs/components/OVERVIEW.md @@ -0,0 +1,59 @@ +# Components Overview + +The Asgardeo React SDK provides a comprehensive set of components to handle authentication, user management, and organization features in your React applications. The components are organized into different categories based on their functionality. + +## Root Components + +Root components are the entry points for integrating Asgardeo authentication into your React application. They provide the necessary context and configuration for the SDK. + +- [**`AsgardeoProvider`**](./asgardeo-provider.md) - The main provider component that wraps your application, providing authentication context and configuration. + +## Action Components + +Action components trigger specific authentication-related actions when users interact with them. + +### Sign-In Components + +- **`SignInButton`** - A customizable button that initiates the sign-in flow +- **`SignUpButton`** - A button for user registration flows +- **`SignOutButton`** - A button that handles user sign-out + +These components support both render props and traditional props patterns, giving you flexibility in how you implement them. + +## Control Components + +Control components manage the conditional rendering of content based on authentication state. + +- **`SignedIn`** - Renders children only when the user is authenticated +- **`SignedOut`** - Renders children only when the user is not authenticated +- **`Loading`** - Shows loading state during authentication operations + +## Presentation Components + +Presentation components display user and organization information with built-in styling and functionality. + +### User Components + +- **`User`** - Provides render props access to user data +- **`UserProfile`** - Displays comprehensive user profile information +- **`UserDropdown`** - A dropdown menu with user info and actions + +### Organization Components + +- **`Organization`** - Displays organization information +- **`OrganizationProfile`** - Shows detailed organization profile +- **`OrganizationSwitcher`** - Allows switching between organizations +- **`OrganizationList`** - Lists available organizations +- **`CreateOrganization`** - Form for creating new organizations + +### Authentication UI Components + +- **`SignIn`** - Complete sign-in form with multiple authentication options +- **`SignUp`** - User registration form + +## Next Steps + +- [Explore Action Components](./actions/) - Learn about sign-in, sign-out, and sign-up buttons +- [Learn Control Components](./control/) - Understand conditional rendering based on auth state +- [Discover Presentation Components](./presentation/) - Explore user and organization display components +- [Customize with Primitives](./primitives/) - Use low-level UI components for custom implementations diff --git a/packages/react/docs/components/asgardeo-provider.md b/packages/react/docs/components/asgardeo-provider.md new file mode 100644 index 00000000..a4000622 --- /dev/null +++ b/packages/react/docs/components/asgardeo-provider.md @@ -0,0 +1,150 @@ +# AsgardeoProvider + +The `AsgardeoProvider` is the root context provider component that configures the Asgardeo React SDK and provides authentication context to your entire React application. It must wrap your application to enable authentication features. + +## Overview + +The `AsgardeoProvider` initializes the Asgardeo authentication client, manages authentication state, and provides context to child components through React Context. It handles token management, user sessions, organization switching, and branding preferences automatically. + +## Props + +All props are based on the `AsgardeoReactConfig` interface, which extends the base configuration from `@asgardeo/javascript`. + +### Required Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `baseUrl` | `string` | **REQUIRED** | The base URL of your Asgardeo organization. Format: `https://api.asgardeo.io/t/{org_name}` | +| `clientId` | `string` | **REQUIRED** | The client ID obtained from your Asgardeo application registration | +| `afterSignInUrl` | `string` | `window.location.origin` | URL to redirect users after successful sign-in. Must match configured redirect URIs in Asgardeo | +| `afterSignOutUrl` | `string` | `window.location.origin` | URL to redirect users after sign-out. Must match configured post-logout redirect URIs | +| `scopes` | `string \| string[]` | `openid profile internal_login` | OAuth scopes to request during authentication (e.g., `"openid profile email"` or `["openid", "profile", "email"]`) | +| `organizationHandle` | `string` | - | Organization handle for organization-specific features like branding. Auto-derived from `baseUrl` if not provided. Required for custom domains | +| `applicationId` | `string` | - | UUID of the Asgardeo application for application-specific branding and features | +| `signInUrl` | `string` | - | Custom sign-in page URL. If provided, users will be redirected here instead of Asgardeo's default sign-in page | +| `signUpUrl` | `string` | - | Custom sign-up page URL. If provided, users will be redirected here instead of Asgardeo's default sign-up page | +| `clientSecret` | `string` | - | Client secret for confidential clients. Not recommended for browser applications | +| `tokenValidation` | [TokenValidation](#tokenvalidation) | - | Token validation configuration for ID tokens including validation flags and clock tolerance | +| `preferences` | [Preferences](#preferences) | - | Configuration object for theming, internationalization, and UI customization | + +
+ +

TokenValidation

+ +The `tokenValidation` prop allows you to configure how ID tokens are validated. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `idToken` | `IdTokenValidation` | `{}` | Configuration for ID token validation | + +#### IdTokenValidation + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `validate` | `boolean` | `true` | Whether to validate the ID token | +| `validateIssuer` | `boolean` | `true` | Whether to validate the issuer | +| `clockTolerance` | `number` | `300` | Allowed clock skew in seconds | + +
+ +
+ +

Preferences

+ +The `preferences` prop allows you to customize the UI components provided by the SDK. + +#### Theme Preferences (`preferences.theme`) + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `inheritFromBranding` | `boolean` | `true` | Whether to inherit theme from Asgardeo organization/application branding | +| `mode` | `'light' \| 'dark' \| 'system'` | `'system'` | Theme mode. `'system'` follows user's OS preference | +| `overrides` | `ThemeConfig` | `{}` | Custom theme overrides for colors, typography, spacing, etc. | + +#### Internationalization Preferences (`preferences.i18n`) + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `language` | `string` | Browser default | Language code for UI text (e.g., `'en-US'`, `'es-ES'`) | +| `fallbackLanguage` | `string` | `'en-US'` | Fallback language when translations aren't available | +| `bundles` | `object` | `{}` | Custom translation bundles to override default text | + +
+ +## Usage + +### Basic Setup + +```tsx +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { AsgardeoProvider } from '@asgardeo/react'; +import App from './App'; + +const root = createRoot(document.getElementById('root')); + +root.render( + + + +); +``` + +### Advanced Configuration + +```tsx +import React from 'react'; +import { AsgardeoProvider } from '@asgardeo/react'; +import App from './App'; + +function MyApp() { + return ( + + + + ); +} +``` + +### Environment Variables + +You can use environment variables for configuration: + +```tsx + + + +``` diff --git a/packages/react/docs/components/sign-in-button.md b/packages/react/docs/components/sign-in-button.md new file mode 100644 index 00000000..64dc0a98 --- /dev/null +++ b/packages/react/docs/components/sign-in-button.md @@ -0,0 +1,338 @@ +# SignInButton + +The `SignInButton` component provides a pre-built, customizable button that handles user authentication through the Asgardeo identity provider. It supports both render props and traditional props patterns, making it flexible for various UI implementations. + +## Overview + +The `SignInButton` component automatically integrates with the Asgardeo authentication context and handles the sign-in flow including loading states, error handling, and redirection. It leverages the `useAsgardeo` hook to access authentication methods and can be customized with preferences for internationalization and theming. + +## Basic Usage + +### Traditional Props Pattern + +```tsx +import React from 'react'; +import { SignInButton } from '@asgardeo/react'; + +function LoginPage() { + return ( +
+

Welcome to Our App

+ Sign In +
+ ); +} +``` + +### With Custom Styling + +```tsx +import React from 'react'; +import { SignInButton } from '@asgardeo/react'; + +function CustomLoginPage() { + return ( + + Get Started + + ); +} +``` + +## Advanced Usage + +### Render Props Pattern + +The render props pattern gives you full control over the button's appearance and behavior while still leveraging the authentication logic: + +```tsx +import React from 'react'; +import { SignInButton } from '@asgardeo/react'; + +function AdvancedLoginPage() { + return ( + + {({ signIn, isLoading }) => ( + + )} + + ); +} +``` + +### Custom Click Handler + +```tsx +import React from 'react'; +import { SignInButton } from '@asgardeo/react'; + +function TrackingLoginPage() { + const handleSignInClick = (event) => { + // Track analytics event + analytics.track('sign_in_button_clicked'); + console.log('User initiated sign-in process'); + }; + + return ( + + Sign In + + ); +} +``` + +### Component-Level Internationalization + +```tsx +import React from 'react'; +import { SignInButton } from '@asgardeo/react'; + +function LocalizedLoginPage() { + return ( + + {/* Will use localized text from preferences */} + + ); +} +``` + +## Props + +The `SignInButton` component accepts all standard HTML button attributes plus the following: + +### SignInButtonProps + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `children` | `ReactNode \| ((props: RenderProps) => ReactNode)` | Localized "Sign In" text | Button content or render function | +| `onClick` | `(event: MouseEvent) => void` | - | Custom click handler called after sign-in initiation | +| `className` | `string` | - | Additional CSS classes to apply to the button | +| `style` | `CSSProperties` | - | Inline styles to apply to the button | +| `preferences` | `Preferences` | - | Component-level configuration for theming and internationalization | +| `disabled` | `boolean` | `false` | Whether the button is disabled (overridden during loading) | +| `type` | `"button" \| "submit" \| "reset"` | `"button"` | HTML button type | + +### Render Props + +When using the render props pattern, the function receives the following props: + +| Prop | Type | Description | +|------|------|-------------| +| `signIn` | `() => Promise` | Function to initiate the sign-in process | +| `isLoading` | `boolean` | Whether the sign-in process is currently in progress | + +## Preferences + +The `preferences` prop allows you to customize the component's behavior and appearance. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `i18n` | `I18nConfig` | - | Internationalization configuration for custom translations | +| `theme` | `ThemeConfig` | - | Theme configuration for styling customization | + +### I18nConfig + +| Property | Type | Description | +|----------|------|-------------| +| `bundles` | `Record }>` | Translation bundles keyed by locale | + +For the SignInButton, the relevant translation key is: + +- `elements.buttons.signIn` - The default button text + + +## Behavior + +### Authentication Flow + +1. **Initial State**: Button displays with default or custom text +2. **Click Event**: User clicks the button, triggering the sign-in process +3. **Loading State**: Button becomes disabled and shows loading indicator +4. **Navigation**: User is redirected to Asgardeo sign-in page or custom sign-in URL +5. **Completion**: After successful authentication, user returns to the application + +### Custom Sign-In URL + +If a `signInUrl` is configured in the `AsgardeoProvider`, the button will navigate to that URL instead of initiating the OAuth flow directly: + +```tsx +// In your AsgardeoProvider configuration + + + +``` + +### Error Handling + +The component automatically handles sign-in errors and throws an `AsgardeoRuntimeError` with detailed information: + +```tsx +// Error details include: +// - Error message +// - Error code: 'SignInButton-handleSignIn-RuntimeError-001' +// - Package: 'react' +// - User-friendly message +``` + +## Accessibility + +The `SignInButton` component includes accessibility features: + +- **Keyboard Navigation**: Fully keyboard accessible +- **Screen Readers**: Proper ARIA attributes and semantic HTML +- **Loading States**: Disabled state prevents multiple submissions +- **Focus Management**: Maintains focus states for keyboard users + +## Integration with BaseSignInButton + +The `SignInButton` is built on top of `BaseSignInButton`, which provides the core functionality. If you need more control or want to build a custom implementation, you can use `BaseSignInButton` directly: + +```tsx +import React, { useState } from 'react'; +import { BaseSignInButton } from '@asgardeo/react'; +import { useAsgardeo } from '@asgardeo/react'; + +function CustomSignInButton() { + const { signIn } = useAsgardeo(); + const [isLoading, setIsLoading] = useState(false); + + const handleSignIn = async () => { + setIsLoading(true); + try { + await signIn(); + } finally { + setIsLoading(false); + } + }; + + return ( + + Custom Sign In Implementation + + ); +} +``` + +## Best Practices + +### 1. Consistent Styling + +Maintain consistent button styling across your application: + +```tsx +// Create a styled wrapper +const StyledSignInButton = styled(SignInButton)` + background: var(--primary-color); + color: white; + border-radius: 8px; + padding: 12px 24px; + font-weight: 600; + + &:hover { + background: var(--primary-hover-color); + } +`; +``` + +### 2. Loading States + +Always provide clear feedback during the sign-in process: + +```tsx + + {({ isLoading }) => ( + <> + {isLoading && } + {isLoading ? 'Signing in...' : 'Sign In'} + + )} + +``` + +### 3. Error Boundaries + +Wrap your authentication components in error boundaries to handle potential errors gracefully: + +```tsx +Something went wrong}> + Sign In + +``` + +### 4. Responsive Design + +Ensure your sign-in button works well on all device sizes: + +```tsx + + Sign In + +``` + +## Common Issues + +### Button Not Working + +- Ensure `AsgardeoProvider` is properly configured and wrapping your component +- Check that all required configuration props are provided +- Verify network connectivity and Asgardeo service availability + +### Custom Styling Not Applied + +- Check CSS specificity and ensure your styles are not being overridden +- Use browser developer tools to inspect the rendered element +- Consider using CSS-in-JS solutions or CSS modules for better style isolation + +### Translation Not Showing + +- Verify the translation key `elements.buttons.signIn` exists in your bundles +- Check that the locale is correctly set in your preferences +- Ensure the `preferences` prop is passed correctly + +## Related Components + +- [`AsgardeoProvider`](./asgardeo-provider.md) - Required context provider for authentication +- [`BaseSignInButton`](#integration-with-basesigninbutton) - Lower-level component for custom implementations +- [`SignOutButton`](./sign-out-button.md) - Companion component for signing out users diff --git a/packages/react/docs/getting-started/QUICKSTART.md b/packages/react/docs/getting-started/QUICKSTART.md new file mode 100644 index 00000000..36a4ee18 --- /dev/null +++ b/packages/react/docs/getting-started/QUICKSTART.md @@ -0,0 +1,184 @@ +# React Quickstart + +Welcome to the React Quickstart guide! In this document, you will learn to build a React app, add user sign-in and display user profile information using Asgardeo. + +## What You Will Learn + +- Create new React app using Vite +- Install @asgardeo/react package +- Add user sign-in and sign-out +- Display user profile information + +## Prerequisites + +Before you start, ensure you have the following: + +- About 15 minutes +- Asgardeo account +- Install Node.js on your system +- Make sure you have a JavaScript package manager like npm, yarn, or pnpm +- A favorite text editor or IDE + +## Example Source Code + +[React Vite App Sample](../../samples/) + +## 1. Configure an Application in Asgardeo + +1. Sign into the Asgardeo Console and navigate to **Applications** > **New Application**. +2. Select **React** and complete the wizard by providing a suitable name and an authorized redirect URL. + +**Example:** + +- Name: `asgardeo-react` +- Authorized redirect URL: `http://localhost:5173` + +Once you finish creating the application, note down the following values from its **Guide** tab. You will need them to configure Asgardeo React SDK. + +- **Client ID** - The unique identifier for your application. +- **Base URL** - The base URL of your Asgardeo organization. This typically follows the format `https://api.asgardeo.io/t/` + +> **Info**: The authorized redirect URL determines where Asgardeo should send users after they successfully log in. Typically, this will be the web address where your app is hosted. For this guide, we'll use `http://localhost:5173`, as the sample app will be accessible at this URL. + +## 2. Create a React App Using Vite + +Create (scaffold) your new React app using Vite: + +```bash +npm create vite@latest asgardeo-react -- --template react +cd asgardeo-react +npm install +npm run dev +``` + +## 3. Install @asgardeo/react + +Asgardeo React SDK provides all the components and hooks you need to integrate Asgardeo into your app. To get started, simply add the Asgardeo React SDK to the project. Make sure to stop the dev server you started in the previous step. + +```bash +# Using npm +npm install @asgardeo/react + +# Using pnpm +pnpm add @asgardeo/react + +# Using yarn +yarn add @asgardeo/react +``` + +## 4. Add `` to Your App + +The `` serves as a context provider for the SDK. You can integrate this provider to your app by wrapping the root component. + +Add the following changes to the `main.jsx` file. + +> **Important**: Replace below placeholders with your registered organization name in Asgardeo and the generated client-id from the app you registered in Asgardeo. +> +> - `` +> - `https://api.asgardeo.io/t/` + +```jsx +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.jsx' +import { AsgardeoProvider } from '@asgardeo/react' + +createRoot(document.getElementById('root')).render( + + + + + +) +``` + +## 5. Add Sign-In and Sign-Out to Your App + +Asgardeo SDK provides `SignInButton`, `SignOutButton` components to handle user sign-in and sign-out. You can use these components alongside `SignedIn` and `SignedOut` components to conditionally render content based on the user's logged in state. + +Replace the existing content of the `App.jsx` file with following content: + +```jsx +import { SignedIn, SignedOut, SignInButton, SignOutButton } from '@asgardeo/react' +import './App.css' + +function App() { + return ( +
+ + + + + + +
+ ) +} + +export default App +``` + +## 6. Display Signed-In User's Profile Information + +You can use the `User`, `UserProfile`, or `UserDropdown` components to access and display user profile information in a declarative way. + +- **User**: The `User` component provides a render prop pattern to access user profile information: +- **UserProfile**: The `UserProfile` component provides a declarative way to display and update user profile information. +- **UserDropdown**: The `UserDropdown` component provides a dropdown menu with built-in user information and sign-out functionality. + +```jsx +import { SignedIn, SignedOut, SignInButton, SignOutButton, User, UserDropdown, UserProfile } from '@asgardeo/react' +import './App.css' + +function App() { + return ( + <> +
+ + + + + + + +
+
+ + + {(user) => ( +
+

Welcome back, {user.userName || user.username || user.sub}

+
+ )} +
+ +
+
+ + ) +} + +export default App +``` + +## 7. Run the App + +To run the app, use the following command: + +```bash +npm run dev +``` + +Visit your app's homepage at [http://localhost:5173](http://localhost:5173). + +> **Important**: To try out sign-in and sign-out features, create a test user in Asgardeo by following [this guide](https://wso2.com/asgardeo/docs/guides/users/manage-users/#onboard-a-user). + +## What's Next? + +Now that you have basic authentication working, you can: + +- [Explore all available components](../components/overview.md) to enhance your app. diff --git a/packages/react/docs/guides/accessing-protected-apis.md b/packages/react/docs/guides/accessing-protected-apis.md new file mode 100644 index 00000000..ac7ae391 --- /dev/null +++ b/packages/react/docs/guides/accessing-protected-apis.md @@ -0,0 +1,264 @@ +# Accessing Protected APIs + +This guide shows how to make authenticated API calls to protected resources using the Asgardeo React SDK. The SDK provides an authenticated `http` module that automatically handles authentication headers and token refresh. + +## Overview + +When your application is wrapped with `AsgardeoProvider`, you can use the `useAsgardeo` hook to access the authenticated `http` module. This module has the following features: + +- Includes the necessary authentication headers (Bearer token) +- Handles token refresh when tokens expire +- Provides methods like `request()` and `requestAll()` for making API calls + +## Basic Usage + +```tsx +import React, { useEffect, useState } from 'react'; +import { useAsgardeo } from '@asgardeo/react'; + +export default function UserProfile() { + const { http, isSignedIn } = useAsgardeo(); + const [userData, setUserData] = useState(null); + + useEffect(() => { + if (!isSignedIn) { + return; + } + + (async () => { + try { + const response = await http.request({ + url: 'https://api.asgardeo.io/t//scim2/Me', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + }, + method: 'GET', + }); + + setUserData(response.data); + } catch (error) { + console.error('Error fetching user data:', error); + } + })(); + }, [http, isSignedIn]); + + if (!isSignedIn) { + return
Please sign in to view your profile.
; + } + + return ( +
+

User Profile

+ {userData && ( +
{JSON.stringify(userData, null, 2)}
+ )} +
+ ); +} +``` + +## Multiple API Calls with `requestAll()` + +When you need to make multiple API calls simultaneously, you can use the `http.requestAll()` method: + +```tsx +import React, { useEffect, useState } from 'react'; +import { useAsgardeo } from '@asgardeo/react'; + +export default function UserProfile() { + const { http, isSignedIn } = useAsgardeo(); + const [userData, setUserData] = useState({ + profile: null, + discoverableApplications: [], + }); + + useEffect(() => { + if (!isSignedIn) { + return; + } + + const requests = []; + + requests.push({ + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + method: 'GET', + url: 'https://api.asgardeo.io/t//api/users/v1/me/applications', + }); + + requests.push({ + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + }, + method: 'GET', + url: 'https://api.asgardeo.io/t//scim2/Me', + }); + + (async () => { + try { + const response = await http.requestAll(requests); + + setUserData({ + discoverableApplications: response[0].data.applications, + profile: response[1].data, + }); + } catch (error) { + console.error('Error fetching data:', error); + } + })(); + }, [http, isSignedIn]); + + return
{JSON.stringify(userData, null, 4)}
; +} +``` + +## Making Different Types of API Calls + +### GET Request + +```tsx +const fetchUsers = async () => { + try { + const response = await http.request({ + url: 'https://api.asgardeo.io/t//scim2/Users', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + }, + method: 'GET', + }); + + return response.data; + } catch (error) { + console.error('Error fetching users:', error); + throw error; + } +}; +``` + +### POST Request + +```tsx +const createUser = async (userData) => { + try { + const response = await http.request({ + url: 'https://api.asgardeo.io/t//scim2/Users', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + }, + method: 'POST', + data: userData, + }); + + return response.data; + } catch (error) { + console.error('Error creating user:', error); + throw error; + } +}; +``` + +### PUT Request + +```tsx +const updateUser = async (userId, userData) => { + try { + const response = await http.request({ + url: `https://api.asgardeo.io/t//scim2/Users/${userId}`, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + }, + method: 'PUT', + data: userData, + }); + + return response.data; + } catch (error) { + console.error('Error updating user:', error); + throw error; + } +}; +``` + +### DELETE Request + +```tsx +const deleteUser = async (userId) => { + try { + const response = await http.request({ + url: `https://api.asgardeo.io/t//scim2/Users/${userId}`, + headers: { + Accept: 'application/json', + }, + method: 'DELETE', + }); + + return true; + } catch (error) { + console.error('Error deleting user:', error); + throw error; + } +}; +``` + +## Bring your own HTTP Client + +If you prefer to use your own HTTP client (like the native `fetch` API), you can use the `getAccessToken()` method to manually add the authorization header: + +```tsx +import React, { useEffect, useState } from 'react'; +import { useAsgardeo } from '@asgardeo/react'; + +export default function UserProfile() { + const { isSignedIn, getAccessToken } = useAsgardeo(); + const [userData, setUserData] = useState(null); + + useEffect(() => { + if (!isSignedIn) { + return; + } + + (async () => { + try { + const response = await fetch('https://api.asgardeo.io/t//scim2/Me', { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/scim+json', + Authorization: `Bearer ${await getAccessToken()}`, + }, + method: 'GET', + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const responseData = await response.json(); + + setUserData(responseData); + } catch (error) { + console.error('Error fetching data:', error); + } + })(); + }, [isSignedIn, getAccessToken]); + + if (!isSignedIn) { + return
Please sign in to view your profile.
; + } + + return ( +
+

User Profile

+ {userData && ( +
{JSON.stringify(userData, null, 2)}
+ )} +
+ ); +} +``` diff --git a/packages/react/src/AsgardeoReactClient.ts b/packages/react/src/AsgardeoReactClient.ts index 9b2ae5a1..f605d968 100644 --- a/packages/react/src/AsgardeoReactClient.ts +++ b/packages/react/src/AsgardeoReactClient.ts @@ -213,7 +213,6 @@ class AsgardeoReactClient e return this.withLoading(async () => { try { const configData = await this.asgardeo.getConfigData(); - const scopes = configData?.scopes; if (!organization.id) { throw new AsgardeoRuntimeError( @@ -238,11 +237,7 @@ class AsgardeoReactClient e signInRequired: true, }; - return (await this.asgardeo.exchangeToken( - exchangeConfig, - (user: User) => {}, - () => null, - )) as TokenResponse | Response; + return (await this.asgardeo.exchangeToken(exchangeConfig, (user: User) => {})) as TokenResponse | Response; } catch (error) { throw new AsgardeoRuntimeError( `Failed to switch organization: ${error.message || error}`, @@ -350,11 +345,16 @@ class AsgardeoReactClient e ); } - async fetch(url: string, options?: HttpRequestConfig): Promise> { - return this.asgardeo.httpRequest({ - url, - ...options, - }); + async request(requestConfig?: HttpRequestConfig): Promise> { + return this.asgardeo.httpRequest(requestConfig); + } + + async requestAll(requestConfigs?: HttpRequestConfig[]): Promise[]> { + return this.asgardeo.httpRequestAll(requestConfigs); + } + + override async getAccessToken(sessionId?: string): Promise { + return this.asgardeo.getAccessToken(sessionId); } } diff --git a/packages/react/src/__temp__/api.ts b/packages/react/src/__temp__/api.ts index d1784703..f9dc3834 100644 --- a/packages/react/src/__temp__/api.ts +++ b/packages/react/src/__temp__/api.ts @@ -29,8 +29,6 @@ import { OIDCEndpoints, SignInConfig, SPACustomGrantConfig, - initializeEmbeddedSignInFlow, - processOpenIDScopes, } from '@asgardeo/browser'; import {AuthStateInterface} from './models'; @@ -229,7 +227,6 @@ class AuthAPI { public exchangeToken( config: SPACustomGrantConfig, callback: (response: User | Response) => void, - dispatch: (state: AuthStateInterface) => void, ): Promise { return this._client .exchangeToken(config) @@ -245,8 +242,6 @@ class AuthAPI { isSignedIn: true, isLoading: false, }); - - dispatch({...(response as User), isSignedIn: true, isLoading: false}); } callback && callback(response); @@ -326,8 +321,8 @@ class AuthAPI { * * @return {Promise} - A Promise that resolves with the access token. */ - public async getAccessToken(): Promise { - return this._client.getAccessToken(); + public async getAccessToken(sessionId?: string): Promise { + return this._client.getAccessToken(sessionId); } /** diff --git a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts index ea947754..ac550625 100644 --- a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts +++ b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts @@ -61,12 +61,24 @@ export type AsgardeoContextProps = { user: any; organization: Organization; /** - * Custom fetch function to make HTTP requests. - * @param url - The URL to fetch. - * @param options - Optional configuration for the HTTP request. + * HTTP request function to make API calls. + * @param requestConfig - Configuration for the HTTP request. * @returns A promise that resolves to the HTTP response. */ - fetch: (url: string, options?: HttpRequestConfig) => Promise>; + http: { + /** + * Makes an HTTP request using the provided configuration. + * @param requestConfig - Configuration for the HTTP request. + * @returns A promise that resolves to the HTTP response. + */ + request: (requestConfig?: HttpRequestConfig) => Promise>; + /** + * Makes multiple HTTP requests based on the provided configuration. + * @param requestConfigs - Set of configurations for the HTTP requests. + * @returns A promise that resolves to an array of HTTP responses. + */ + requestAll: (requestConfigs?: HttpRequestConfig[]) => Promise[]>; + }; }; /** @@ -88,7 +100,10 @@ const AsgardeoContext: Context = createContext null, + http: { + request: () => null, + requestAll: () => null, + }, }); AsgardeoContext.displayName = 'AsgardeoContext'; diff --git a/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx b/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx index c587d396..b6c55d37 100644 --- a/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx +++ b/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx @@ -18,18 +18,14 @@ import { AsgardeoRuntimeError, - EmbeddedFlowExecuteRequestPayload, - EmbeddedFlowExecuteResponse, generateFlattenedUserProfile, Organization, SignInOptions, - SignOutOptions, User, UserProfile, getBrandingPreference, GetBrandingPreferenceConfig, BrandingPreference, - HttpRequestConfig, } from '@asgardeo/browser'; import {FC, RefObject, PropsWithChildren, ReactElement, useEffect, useMemo, useRef, useState, useCallback} from 'react'; import AsgardeoContext from './AsgardeoContext'; @@ -339,22 +335,6 @@ const AsgardeoProvider: FC> = ({ } }; - const signUp = async (payload?: EmbeddedFlowExecuteRequestPayload): Promise => { - try { - return await asgardeo.signUp(payload); - } catch (error) { - throw new AsgardeoRuntimeError( - `Error while signing up: ${error.message || error}`, - 'asgardeo-signUp-Error', - 'react', - 'An error occurred while trying to sign up.', - ); - } - }; - - const signOut = async (options?: SignOutOptions, afterSignOut?: () => void): Promise => - asgardeo.signOut(options, afterSignOut); - const switchOrganization = async (organization: Organization): Promise => { try { setIsLoadingSync(true); @@ -391,31 +371,49 @@ const AsgardeoProvider: FC> = ({ })); }; - const fetch = async (url: string, options?: HttpRequestConfig): Promise => { - return asgardeo.fetch(url, options); - }; + const value = useMemo( + () => ({ + applicationId, + organizationHandle: config?.organizationHandle, + signInUrl, + signUpUrl, + afterSignInUrl, + baseUrl, + getAccessToken: asgardeo.getAccessToken.bind(asgardeo), + isInitialized: isInitializedSync, + isLoading: isLoadingSync, + isSignedIn: isSignedInSync, + organization: currentOrganization, + signIn, + signInSilently, + signOut: asgardeo.signOut.bind(asgardeo), + signUp: asgardeo.signUp.bind(asgardeo), + user, + http: { + request: asgardeo.request.bind(asgardeo), + requestAll: asgardeo.requestAll.bind(asgardeo), + }, + }), + [ + applicationId, + config?.organizationHandle, + signInUrl, + signUpUrl, + afterSignInUrl, + baseUrl, + isInitializedSync, + isLoadingSync, + isSignedInSync, + currentOrganization, + signIn, + signInSilently, + user, + asgardeo, + ], + ); return ( - + =6.9.0'} + '@babel/core@7.28.0': + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + engines: {node: '>=6.9.0'} + '@babel/eslint-parser@7.27.1': resolution: {integrity: sha512-q8rjOuadH0V6Zo4XLMkJ3RMQ9MSBqwaDByyYB0izsYdaIWGNLmEblbCOf1vyFHICcg16CD7Fsi51vcQnYxmt6Q==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} @@ -743,10 +787,18 @@ packages: resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} @@ -757,6 +809,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} @@ -777,11 +835,20 @@ packages: resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.27.2': resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -806,10 +873,18 @@ packages: resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + '@babel/types@7.27.1': resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.0': + resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -1260,10 +1335,18 @@ packages: resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.2.2': resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.3.0': + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.14.0': resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1284,6 +1367,10 @@ packages: resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.30.1': + resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1480,6 +1567,9 @@ packages: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -1501,6 +1591,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} @@ -1788,6 +1881,9 @@ packages: '@types/react': optional: true + '@rolldown/pluginutils@1.0.0-beta.19': + resolution: {integrity: sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==} + '@rolldown/pluginutils@1.0.0-beta.9': resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==} @@ -2168,12 +2264,20 @@ packages: peerDependencies: '@types/react': ^19.0.0 + '@types/react-dom@19.1.6': + resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} + peerDependencies: + '@types/react': ^19.0.0 + '@types/react@18.3.23': resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} '@types/react@19.1.5': resolution: {integrity: sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==} + '@types/react@19.1.8': + resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -2382,6 +2486,12 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + '@vitejs/plugin-react@4.6.0': + resolution: {integrity: sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 + '@vitejs/plugin-vue@5.2.4': resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -2637,6 +2747,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -3644,6 +3759,10 @@ packages: resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-utils@2.1.0: resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} engines: {node: '>=6'} @@ -3670,6 +3789,10 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3686,10 +3809,24 @@ packages: jiti: optional: true + eslint@9.30.1: + resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + espree@10.3.0: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3790,6 +3927,14 @@ packages: picomatch: optional: true + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -3998,6 +4143,10 @@ packages: resolution: {integrity: sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==} engines: {node: '>=18'} + globals@16.3.0: + resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -5359,6 +5508,10 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + preact@10.26.7: resolution: {integrity: sha512-43xS+QYc1X1IPbw03faSgY6I6OYWcLrJRv3hU0+qMOfh/XCHcP0MX2CVjNARYR2cC/guu975sta4OcjlczxD7g==} @@ -6045,6 +6198,10 @@ packages: resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + tinypool@1.0.2: resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -6349,6 +6506,46 @@ packages: yaml: optional: true + vite@7.0.2: + resolution: {integrity: sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitepress@1.6.3: resolution: {integrity: sha512-fCkfdOk8yRZT8GD9BFqusW3+GggWYZ/rYncOfmgcDtP3ualNHCAg+Robxp2/6xfH1WwPHtGpPwv7mbA3qomtBw==} hasBin: true @@ -6751,6 +6948,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.28.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/eslint-parser@7.27.1(@babel/core@7.27.1)(eslint@8.57.0)': dependencies: '@babel/core': 7.27.1 @@ -6767,6 +6984,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.27.2 @@ -6775,6 +7000,8 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} + '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.27.1 @@ -6791,6 +7018,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-string-parser@7.27.1': {} @@ -6804,20 +7040,39 @@ snapshots: '@babel/template': 7.27.2 '@babel/types': 7.27.1 + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.0 + '@babel/parser@7.27.2': dependencies: '@babel/types': 7.27.1 + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.0 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/runtime@7.27.1': {} '@babel/template@7.27.2': @@ -6838,11 +7093,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.0 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + '@babel/types@7.27.1': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.28.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@bcoe/v8-coverage@1.0.2': {} '@changesets/apply-release-plan@7.0.12': @@ -7236,6 +7508,11 @@ snapshots: eslint: 9.28.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@2.4.2))': + dependencies: + eslint: 9.30.1(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} '@eslint/config-array@0.20.0': @@ -7246,8 +7523,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + '@eslint/config-helpers@0.2.2': {} + '@eslint/config-helpers@0.3.0': {} + '@eslint/core@0.14.0': dependencies: '@types/json-schema': 7.0.15 @@ -7284,6 +7571,8 @@ snapshots: '@eslint/js@9.28.0': {} + '@eslint/js@9.30.1': {} + '@eslint/object-schema@2.1.6': {} '@eslint/plugin-kit@0.3.1': @@ -7445,6 +7734,11 @@ snapshots: dependencies: '@sinclair/typebox': 0.27.8 + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.29 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -7468,6 +7762,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jspm/core@2.1.0': {} '@manypkg/find-root@1.1.0': @@ -7678,6 +7977,8 @@ snapshots: optionalDependencies: '@types/react': 19.1.5 + '@rolldown/pluginutils@1.0.0-beta.19': {} + '@rolldown/pluginutils@1.0.0-beta.9': {} '@rollup/plugin-commonjs@25.0.8(rollup@4.40.2)': @@ -8020,6 +8321,10 @@ snapshots: dependencies: '@types/react': 19.1.5 + '@types/react-dom@19.1.6(@types/react@19.1.8)': + dependencies: + '@types/react': 19.1.8 + '@types/react@18.3.23': dependencies: '@types/prop-types': 15.7.15 @@ -8030,6 +8335,10 @@ snapshots: dependencies: csstype: 3.1.3 + '@types/react@19.1.8': + dependencies: + csstype: 3.1.3 + '@types/resolve@1.20.2': {} '@types/semver@7.7.0': {} @@ -8406,14 +8715,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@4.6.0(vite@7.0.2(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.0) + '@rolldown/pluginutils': 1.0.0-beta.19 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 7.0.2(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-vue@5.2.4(vite@5.4.19(@types/node@24.0.3)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2))(vue@3.5.14(typescript@5.8.3))': dependencies: vite: 5.4.19(@types/node@24.0.3)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2) vue: 3.5.14(typescript@5.8.3) - '@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(vue@3.5.14(typescript@5.1.6))': + '@vitejs/plugin-vue@5.2.4(vite@7.0.2(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(vue@3.5.14(typescript@5.1.6))': dependencies: - vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 7.0.2(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) vue: 3.5.14(typescript@5.1.6) '@vitest/browser@3.1.3(playwright@1.52.0)(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(vitest@3.1.3)': @@ -8784,8 +9105,14 @@ snapshots: dependencies: acorn: 8.14.1 + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + acorn@8.14.1: {} + acorn@8.15.0: {} + agent-base@7.1.3: optional: true @@ -10033,10 +10360,18 @@ snapshots: dependencies: eslint: 9.28.0(jiti@2.4.2) + eslint-plugin-react-hooks@5.2.0(eslint@9.30.1(jiti@2.4.2)): + dependencies: + eslint: 9.30.1(jiti@2.4.2) + eslint-plugin-react-refresh@0.4.20(eslint@9.28.0(jiti@2.4.2)): dependencies: eslint: 9.28.0(jiti@2.4.2) + eslint-plugin-react-refresh@0.4.20(eslint@9.30.1(jiti@2.4.2)): + dependencies: + eslint: 9.30.1(jiti@2.4.2) + eslint-plugin-react@7.37.5(eslint@8.57.0): dependencies: array-includes: 3.1.8 @@ -10128,6 +10463,11 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-utils@2.1.0: dependencies: eslint-visitor-keys: 1.3.0 @@ -10145,6 +10485,8 @@ snapshots: eslint-visitor-keys@4.2.0: {} + eslint-visitor-keys@4.2.1: {} + eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.0) @@ -10230,12 +10572,60 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.30.1(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 + '@eslint/core': 0.14.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.30.1 + '@eslint/plugin-kit': 0.3.1 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + espree@10.3.0: dependencies: acorn: 8.14.1 acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.0 + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + espree@9.6.1: dependencies: acorn: 8.14.1 @@ -10347,6 +10737,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fdir@6.4.6(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -10586,6 +10980,8 @@ snapshots: globals@16.1.0: {} + globals@16.3.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -11941,6 +12337,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + preact@10.26.7: {} prelude-ls@1.2.1: {} @@ -12822,6 +13224,11 @@ snapshots: fdir: 6.4.4(picomatch@4.0.2) picomatch: 4.0.2 + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + tinypool@1.0.2: {} tinyrainbow@2.0.0: {} @@ -13153,7 +13560,41 @@ snapshots: terser: 5.39.2 yaml: 2.8.0 - vitepress@1.6.3(@algolia/client-search@5.25.0)(@types/node@24.0.3)(@types/react@18.3.23)(axios@1.9.0)(fuse.js@7.1.0)(jwt-decode@4.0.0)(lightningcss@1.30.1)(postcss@8.5.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.0)(search-insights@2.17.3)(terser@5.39.2)(typescript@5.8.3): + vite@7.0.2(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): + dependencies: + esbuild: 0.25.4 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.6 + rollup: 4.40.2 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 20.17.50 + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.30.1 + sass: 1.89.0 + terser: 5.39.2 + yaml: 2.8.0 + + vite@7.0.2(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): + dependencies: + esbuild: 0.25.4 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.6 + rollup: 4.40.2 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 24.0.3 + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.30.1 + sass: 1.89.0 + terser: 5.39.2 + yaml: 2.8.0 + + vitepress@1.6.3(@algolia/client-search@5.25.0)(@types/node@24.0.3)(@types/react@18.3.23)(axios@1.9.0)(fuse.js@7.1.0)(jwt-decode@4.0.0)(lightningcss@1.30.1)(postcss@8.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.0)(search-insights@2.17.3)(terser@5.39.2)(typescript@5.8.3): dependencies: '@docsearch/css': 3.8.2 '@docsearch/js': 3.8.2(@algolia/client-search@5.25.0)(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) @@ -13174,7 +13615,7 @@ snapshots: vite: 5.4.19(@types/node@24.0.3)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2) vue: 3.5.14(typescript@5.8.3) optionalDependencies: - postcss: 8.5.3 + postcss: 8.5.6 transitivePeerDependencies: - '@algolia/client-search' - '@types/node'